Bug 593440 - Remove remaining child widgets on windows. r=roc, a=joe.
[mozilla-central.git] / uriloader / exthandler / nsExternalProtocolHandler.cpp
blobfac8a26822b6ac93ccf6669d7b9881fa827892e1
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim:set ts=2 sts=2 sw=2 et cin:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
17 * The Original Code is mozilla.org Code.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1998
22 * the Initial Developer. All Rights Reserved.
24 * Contributor(s):
25 * Scott MacGregor <mscott@netscape.com>
26 * Dan Mosedale <dmose@mozilla.org>
28 * Alternatively, the contents of this file may be used under the terms of
29 * either of the GNU General Public License Version 2 or later (the "GPL"),
30 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
42 #include "nsIURI.h"
43 #include "nsIURL.h"
44 #include "nsExternalProtocolHandler.h"
45 #include "nsXPIDLString.h"
46 #include "nsReadableUtils.h"
47 #include "nsCOMPtr.h"
48 #include "nsIServiceManager.h"
49 #include "nsServiceManagerUtils.h"
50 #include "nsIInterfaceRequestor.h"
51 #include "nsIInterfaceRequestorUtils.h"
52 #include "nsIStringBundle.h"
53 #include "nsIPrefService.h"
54 #include "nsIPrompt.h"
55 #include "nsNetUtil.h"
56 #include "nsExternalHelperAppService.h"
58 // used to dispatch urls to default protocol handlers
59 #include "nsCExternalHandlerService.h"
60 #include "nsIExternalProtocolService.h"
62 ////////////////////////////////////////////////////////////////////////
63 // a stub channel implemenation which will map calls to AsyncRead and OpenInputStream
64 // to calls in the OS for loading the url.
65 ////////////////////////////////////////////////////////////////////////
67 class nsExtProtocolChannel : public nsIChannel
69 public:
70 NS_DECL_ISUPPORTS
71 NS_DECL_NSICHANNEL
72 NS_DECL_NSIREQUEST
74 nsExtProtocolChannel();
75 virtual ~nsExtProtocolChannel();
77 nsresult SetURI(nsIURI*);
79 private:
80 nsresult OpenURL();
81 void Finish(nsresult aResult);
83 nsCOMPtr<nsIURI> mUrl;
84 nsCOMPtr<nsIURI> mOriginalURI;
85 nsresult mStatus;
86 nsLoadFlags mLoadFlags;
87 PRBool mWasOpened;
89 nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
90 nsCOMPtr<nsILoadGroup> mLoadGroup;
93 NS_IMPL_THREADSAFE_ADDREF(nsExtProtocolChannel)
94 NS_IMPL_THREADSAFE_RELEASE(nsExtProtocolChannel)
96 NS_INTERFACE_MAP_BEGIN(nsExtProtocolChannel)
97 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIChannel)
98 NS_INTERFACE_MAP_ENTRY(nsIChannel)
99 NS_INTERFACE_MAP_ENTRY(nsIRequest)
100 NS_INTERFACE_MAP_END_THREADSAFE
102 nsExtProtocolChannel::nsExtProtocolChannel() : mStatus(NS_OK),
103 mWasOpened(PR_FALSE)
107 nsExtProtocolChannel::~nsExtProtocolChannel()
110 NS_IMETHODIMP nsExtProtocolChannel::GetLoadGroup(nsILoadGroup * *aLoadGroup)
112 NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
113 return NS_OK;
116 NS_IMETHODIMP nsExtProtocolChannel::SetLoadGroup(nsILoadGroup * aLoadGroup)
118 mLoadGroup = aLoadGroup;
119 return NS_OK;
122 NS_IMETHODIMP nsExtProtocolChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks)
124 NS_IF_ADDREF(*aCallbacks = mCallbacks);
125 return NS_OK;
128 NS_IMETHODIMP nsExtProtocolChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
130 mCallbacks = aCallbacks;
131 return NS_OK;
134 NS_IMETHODIMP
135 nsExtProtocolChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
137 *aSecurityInfo = nsnull;
138 return NS_OK;
141 NS_IMETHODIMP nsExtProtocolChannel::GetOriginalURI(nsIURI* *aURI)
143 NS_ADDREF(*aURI = mOriginalURI);
144 return NS_OK;
147 NS_IMETHODIMP nsExtProtocolChannel::SetOriginalURI(nsIURI* aURI)
149 NS_ENSURE_ARG_POINTER(aURI);
150 mOriginalURI = aURI;
151 return NS_OK;
154 NS_IMETHODIMP nsExtProtocolChannel::GetURI(nsIURI* *aURI)
156 *aURI = mUrl;
157 NS_IF_ADDREF(*aURI);
158 return NS_OK;
161 nsresult nsExtProtocolChannel::SetURI(nsIURI* aURI)
163 mUrl = aURI;
164 return NS_OK;
167 nsresult nsExtProtocolChannel::OpenURL()
169 nsresult rv = NS_ERROR_FAILURE;
170 nsCOMPtr<nsIExternalProtocolService> extProtService (do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
172 if (extProtService)
174 #ifdef DEBUG
175 nsCAutoString urlScheme;
176 mUrl->GetScheme(urlScheme);
177 PRBool haveHandler = PR_FALSE;
178 extProtService->ExternalProtocolHandlerExists(urlScheme.get(), &haveHandler);
179 NS_ASSERTION(haveHandler, "Why do we have a channel for this url if we don't support the protocol?");
180 #endif
182 nsCOMPtr<nsIInterfaceRequestor> aggCallbacks;
183 rv = NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
184 getter_AddRefs(aggCallbacks));
185 if (NS_FAILED(rv)) {
186 goto finish;
189 rv = extProtService->LoadURI(mUrl, aggCallbacks);
190 if (NS_SUCCEEDED(rv)) {
191 // despite success, we need to abort this channel, at the very least
192 // to make it clear to the caller that no on{Start,Stop}Request
193 // should be expected.
194 rv = NS_ERROR_NO_CONTENT;
198 finish:
199 mCallbacks = 0;
200 return rv;
203 NS_IMETHODIMP nsExtProtocolChannel::Open(nsIInputStream **_retval)
205 return OpenURL();
208 NS_IMETHODIMP nsExtProtocolChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
210 NS_ENSURE_ARG_POINTER(listener);
211 NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
213 mWasOpened = PR_TRUE;
215 return OpenURL();
218 NS_IMETHODIMP nsExtProtocolChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
220 *aLoadFlags = mLoadFlags;
221 return NS_OK;
224 NS_IMETHODIMP nsExtProtocolChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
226 mLoadFlags = aLoadFlags;
227 return NS_OK;
230 NS_IMETHODIMP nsExtProtocolChannel::GetContentType(nsACString &aContentType)
232 return NS_ERROR_NOT_IMPLEMENTED;
235 NS_IMETHODIMP nsExtProtocolChannel::SetContentType(const nsACString &aContentType)
237 return NS_ERROR_FAILURE;
240 NS_IMETHODIMP nsExtProtocolChannel::GetContentCharset(nsACString &aContentCharset)
242 return NS_ERROR_NOT_IMPLEMENTED;
245 NS_IMETHODIMP nsExtProtocolChannel::SetContentCharset(const nsACString &aContentCharset)
247 return NS_ERROR_NOT_IMPLEMENTED;
250 NS_IMETHODIMP nsExtProtocolChannel::GetContentLength(PRInt32 * aContentLength)
252 *aContentLength = -1;
253 return NS_OK;
256 NS_IMETHODIMP
257 nsExtProtocolChannel::SetContentLength(PRInt32 aContentLength)
259 NS_NOTREACHED("SetContentLength");
260 return NS_ERROR_NOT_IMPLEMENTED;
263 NS_IMETHODIMP nsExtProtocolChannel::GetOwner(nsISupports * *aPrincipal)
265 NS_NOTREACHED("GetOwner");
266 return NS_ERROR_NOT_IMPLEMENTED;
269 NS_IMETHODIMP nsExtProtocolChannel::SetOwner(nsISupports * aPrincipal)
271 NS_NOTREACHED("SetOwner");
272 return NS_ERROR_NOT_IMPLEMENTED;
275 ////////////////////////////////////////////////////////////////////////////////
276 // From nsIRequest
277 ////////////////////////////////////////////////////////////////////////////////
279 NS_IMETHODIMP nsExtProtocolChannel::GetName(nsACString &result)
281 return mUrl->GetSpec(result);
284 NS_IMETHODIMP nsExtProtocolChannel::IsPending(PRBool *result)
286 *result = PR_FALSE;
287 return NS_OK;
290 NS_IMETHODIMP nsExtProtocolChannel::GetStatus(nsresult *status)
292 *status = mStatus;
293 return NS_OK;
296 NS_IMETHODIMP nsExtProtocolChannel::Cancel(nsresult status)
298 mStatus = status;
299 return NS_OK;
302 NS_IMETHODIMP nsExtProtocolChannel::Suspend()
304 NS_NOTREACHED("Suspend");
305 return NS_ERROR_NOT_IMPLEMENTED;
308 NS_IMETHODIMP nsExtProtocolChannel::Resume()
310 NS_NOTREACHED("Resume");
311 return NS_ERROR_NOT_IMPLEMENTED;
314 ///////////////////////////////////////////////////////////////////////
315 // the default protocol handler implementation
316 //////////////////////////////////////////////////////////////////////
318 nsExternalProtocolHandler::nsExternalProtocolHandler()
320 m_schemeName = "default";
324 nsExternalProtocolHandler::~nsExternalProtocolHandler()
327 NS_IMPL_THREADSAFE_ADDREF(nsExternalProtocolHandler)
328 NS_IMPL_THREADSAFE_RELEASE(nsExternalProtocolHandler)
330 NS_INTERFACE_MAP_BEGIN(nsExternalProtocolHandler)
331 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIProtocolHandler)
332 NS_INTERFACE_MAP_ENTRY(nsIProtocolHandler)
333 NS_INTERFACE_MAP_ENTRY(nsIExternalProtocolHandler)
334 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
335 NS_INTERFACE_MAP_END_THREADSAFE
337 NS_IMETHODIMP nsExternalProtocolHandler::GetScheme(nsACString &aScheme)
339 aScheme = m_schemeName;
340 return NS_OK;
343 NS_IMETHODIMP nsExternalProtocolHandler::GetDefaultPort(PRInt32 *aDefaultPort)
345 *aDefaultPort = 0;
346 return NS_OK;
349 NS_IMETHODIMP
350 nsExternalProtocolHandler::AllowPort(PRInt32 port, const char *scheme, PRBool *_retval)
352 // don't override anything.
353 *_retval = PR_FALSE;
354 return NS_OK;
356 // returns TRUE if the OS can handle this protocol scheme and false otherwise.
357 PRBool nsExternalProtocolHandler::HaveExternalProtocolHandler(nsIURI * aURI)
359 PRBool haveHandler = PR_FALSE;
360 if (aURI)
362 nsCAutoString scheme;
363 aURI->GetScheme(scheme);
364 if (gExtProtSvc)
365 gExtProtSvc->ExternalProtocolHandlerExists(scheme.get(), &haveHandler);
368 return haveHandler;
371 NS_IMETHODIMP nsExternalProtocolHandler::GetProtocolFlags(PRUint32 *aUritype)
373 // Make it norelative since it is a simple uri
374 *aUritype = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_ANYONE |
375 URI_NON_PERSISTABLE | URI_DOES_NOT_RETURN_DATA;
376 return NS_OK;
379 NS_IMETHODIMP nsExternalProtocolHandler::NewURI(const nsACString &aSpec,
380 const char *aCharset, // ignore charset info
381 nsIURI *aBaseURI,
382 nsIURI **_retval)
384 nsresult rv;
385 nsCOMPtr<nsIURI> uri = do_CreateInstance(NS_SIMPLEURI_CONTRACTID, &rv);
386 NS_ENSURE_SUCCESS(rv, rv);
388 rv = uri->SetSpec(aSpec);
389 NS_ENSURE_SUCCESS(rv, rv);
391 NS_ADDREF(*_retval = uri);
392 return NS_OK;
395 NS_IMETHODIMP nsExternalProtocolHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval)
397 // Only try to return a channel if we have a protocol handler for the url.
398 // nsOSHelperAppService::LoadUriInternal relies on this to check trustedness
399 // for some platforms at least. (win uses ::ShellExecute and unix uses
400 // gnome_url_show.)
401 PRBool haveExternalHandler = HaveExternalProtocolHandler(aURI);
402 if (haveExternalHandler)
404 nsCOMPtr<nsIChannel> channel = new nsExtProtocolChannel();
405 if (!channel) return NS_ERROR_OUT_OF_MEMORY;
407 ((nsExtProtocolChannel*) channel.get())->SetURI(aURI);
408 channel->SetOriginalURI(aURI);
410 if (_retval)
412 *_retval = channel;
413 NS_IF_ADDREF(*_retval);
414 return NS_OK;
418 return NS_ERROR_UNKNOWN_PROTOCOL;
421 ///////////////////////////////////////////////////////////////////////
422 // External protocol handler interface implementation
423 //////////////////////////////////////////////////////////////////////
424 NS_IMETHODIMP nsExternalProtocolHandler::ExternalAppExistsForScheme(const nsACString& aScheme, PRBool *_retval)
426 if (gExtProtSvc)
427 return gExtProtSvc->ExternalProtocolHandlerExists(
428 PromiseFlatCString(aScheme).get(), _retval);
430 // In case we don't have external protocol service.
431 *_retval = PR_FALSE;
432 return NS_OK;