Line data Source code
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:
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 :
8 : #include "nsIURI.h"
9 : #include "nsIURL.h"
10 : #include "nsExternalProtocolHandler.h"
11 : #include "nsXPIDLString.h"
12 : #include "nsReadableUtils.h"
13 : #include "nsCOMPtr.h"
14 : #include "nsContentUtils.h"
15 : #include "nsIServiceManager.h"
16 : #include "nsServiceManagerUtils.h"
17 : #include "nsIInterfaceRequestor.h"
18 : #include "nsIInterfaceRequestorUtils.h"
19 : #include "nsIStringBundle.h"
20 : #include "nsIPrefService.h"
21 : #include "nsIPrompt.h"
22 : #include "nsNetUtil.h"
23 : #include "nsContentSecurityManager.h"
24 : #include "nsExternalHelperAppService.h"
25 :
26 : // used to dispatch urls to default protocol handlers
27 : #include "nsCExternalHandlerService.h"
28 : #include "nsIExternalProtocolService.h"
29 : #include "nsIChildChannel.h"
30 : #include "nsIParentChannel.h"
31 :
32 : class nsILoadInfo;
33 :
34 : ////////////////////////////////////////////////////////////////////////
35 : // a stub channel implemenation which will map calls to AsyncRead and OpenInputStream
36 : // to calls in the OS for loading the url.
37 : ////////////////////////////////////////////////////////////////////////
38 :
39 : class nsExtProtocolChannel : public nsIChannel,
40 : public nsIChildChannel,
41 : public nsIParentChannel
42 : {
43 : public:
44 : NS_DECL_THREADSAFE_ISUPPORTS
45 : NS_DECL_NSICHANNEL
46 : NS_DECL_NSIREQUESTOBSERVER
47 : NS_DECL_NSISTREAMLISTENER
48 : NS_DECL_NSIREQUEST
49 : NS_DECL_NSICHILDCHANNEL
50 : NS_DECL_NSIPARENTCHANNEL
51 :
52 : nsExtProtocolChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo);
53 :
54 : private:
55 : virtual ~nsExtProtocolChannel();
56 :
57 : nsresult OpenURL();
58 : void Finish(nsresult aResult);
59 :
60 : nsCOMPtr<nsIURI> mUrl;
61 : nsCOMPtr<nsIURI> mOriginalURI;
62 : nsresult mStatus;
63 : nsLoadFlags mLoadFlags;
64 : bool mWasOpened;
65 : // Set true (as a result of ConnectParent invoked from child process)
66 : // when this channel is on the parent process and is being used as
67 : // a redirect target channel. It turns AsyncOpen into a no-op since
68 : // we do it on the child.
69 : bool mConnectedParent;
70 :
71 : nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
72 : nsCOMPtr<nsILoadGroup> mLoadGroup;
73 : nsCOMPtr<nsILoadInfo> mLoadInfo;
74 : };
75 :
76 0 : NS_IMPL_ADDREF(nsExtProtocolChannel)
77 0 : NS_IMPL_RELEASE(nsExtProtocolChannel)
78 :
79 0 : NS_INTERFACE_MAP_BEGIN(nsExtProtocolChannel)
80 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIChannel)
81 0 : NS_INTERFACE_MAP_ENTRY(nsIChannel)
82 0 : NS_INTERFACE_MAP_ENTRY(nsIRequest)
83 0 : NS_INTERFACE_MAP_ENTRY(nsIChildChannel)
84 0 : NS_INTERFACE_MAP_ENTRY(nsIParentChannel)
85 0 : NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
86 0 : NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
87 0 : NS_INTERFACE_MAP_END_THREADSAFE
88 :
89 0 : nsExtProtocolChannel::nsExtProtocolChannel(nsIURI* aURI,
90 0 : nsILoadInfo* aLoadInfo)
91 : : mUrl(aURI)
92 : , mOriginalURI(aURI)
93 : , mStatus(NS_OK)
94 : , mLoadFlags(nsIRequest::LOAD_NORMAL)
95 : , mWasOpened(false)
96 : , mConnectedParent(false)
97 0 : , mLoadInfo(aLoadInfo)
98 : {
99 0 : }
100 :
101 0 : nsExtProtocolChannel::~nsExtProtocolChannel()
102 0 : {}
103 :
104 0 : NS_IMETHODIMP nsExtProtocolChannel::GetLoadGroup(nsILoadGroup * *aLoadGroup)
105 : {
106 0 : NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
107 0 : return NS_OK;
108 : }
109 :
110 0 : NS_IMETHODIMP nsExtProtocolChannel::SetLoadGroup(nsILoadGroup * aLoadGroup)
111 : {
112 0 : mLoadGroup = aLoadGroup;
113 0 : return NS_OK;
114 : }
115 :
116 0 : NS_IMETHODIMP nsExtProtocolChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks)
117 : {
118 0 : NS_IF_ADDREF(*aCallbacks = mCallbacks);
119 0 : return NS_OK;
120 : }
121 :
122 0 : NS_IMETHODIMP nsExtProtocolChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
123 : {
124 0 : mCallbacks = aCallbacks;
125 0 : return NS_OK;
126 : }
127 :
128 : NS_IMETHODIMP
129 0 : nsExtProtocolChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
130 : {
131 0 : *aSecurityInfo = nullptr;
132 0 : return NS_OK;
133 : }
134 :
135 0 : NS_IMETHODIMP nsExtProtocolChannel::GetOriginalURI(nsIURI* *aURI)
136 : {
137 0 : NS_ADDREF(*aURI = mOriginalURI);
138 0 : return NS_OK;
139 : }
140 :
141 0 : NS_IMETHODIMP nsExtProtocolChannel::SetOriginalURI(nsIURI* aURI)
142 : {
143 0 : NS_ENSURE_ARG_POINTER(aURI);
144 0 : mOriginalURI = aURI;
145 0 : return NS_OK;
146 : }
147 :
148 0 : NS_IMETHODIMP nsExtProtocolChannel::GetURI(nsIURI* *aURI)
149 : {
150 0 : *aURI = mUrl;
151 0 : NS_IF_ADDREF(*aURI);
152 0 : return NS_OK;
153 : }
154 :
155 0 : nsresult nsExtProtocolChannel::OpenURL()
156 : {
157 0 : nsresult rv = NS_ERROR_FAILURE;
158 0 : nsCOMPtr<nsIExternalProtocolService> extProtService (do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
159 :
160 0 : if (extProtService)
161 : {
162 : #ifdef DEBUG
163 0 : nsAutoCString urlScheme;
164 0 : mUrl->GetScheme(urlScheme);
165 0 : bool haveHandler = false;
166 0 : extProtService->ExternalProtocolHandlerExists(urlScheme.get(), &haveHandler);
167 0 : NS_ASSERTION(haveHandler, "Why do we have a channel for this url if we don't support the protocol?");
168 : #endif
169 :
170 0 : nsCOMPtr<nsIInterfaceRequestor> aggCallbacks;
171 0 : rv = NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
172 0 : getter_AddRefs(aggCallbacks));
173 0 : if (NS_FAILED(rv)) {
174 0 : goto finish;
175 : }
176 :
177 0 : rv = extProtService->LoadURI(mUrl, aggCallbacks);
178 0 : if (NS_SUCCEEDED(rv)) {
179 : // despite success, we need to abort this channel, at the very least
180 : // to make it clear to the caller that no on{Start,Stop}Request
181 : // should be expected.
182 0 : rv = NS_ERROR_NO_CONTENT;
183 : }
184 : }
185 :
186 : finish:
187 0 : mCallbacks = nullptr;
188 0 : return rv;
189 : }
190 :
191 0 : NS_IMETHODIMP nsExtProtocolChannel::Open(nsIInputStream **_retval)
192 : {
193 0 : return OpenURL();
194 : }
195 :
196 0 : NS_IMETHODIMP nsExtProtocolChannel::Open2(nsIInputStream** aStream)
197 : {
198 0 : nsCOMPtr<nsIStreamListener> listener;
199 0 : nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
200 0 : NS_ENSURE_SUCCESS(rv, rv);
201 0 : return Open(aStream);
202 : }
203 :
204 0 : NS_IMETHODIMP nsExtProtocolChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
205 : {
206 0 : if (mConnectedParent) {
207 0 : return NS_OK;
208 : }
209 :
210 0 : MOZ_ASSERT(!mLoadInfo ||
211 : mLoadInfo->GetSecurityMode() == 0 ||
212 : mLoadInfo->GetInitialSecurityCheckDone() ||
213 : (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL &&
214 : nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())),
215 : "security flags in loadInfo but asyncOpen2() not called");
216 :
217 0 : NS_ENSURE_ARG_POINTER(listener);
218 0 : NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
219 :
220 0 : mWasOpened = true;
221 :
222 0 : return OpenURL();
223 : }
224 :
225 0 : NS_IMETHODIMP nsExtProtocolChannel::AsyncOpen2(nsIStreamListener *aListener)
226 : {
227 0 : nsCOMPtr<nsIStreamListener> listener = aListener;
228 0 : nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
229 0 : if (NS_FAILED(rv)) {
230 0 : mCallbacks = nullptr;
231 0 : return rv;
232 : }
233 0 : return AsyncOpen(listener, nullptr);
234 : }
235 :
236 0 : NS_IMETHODIMP nsExtProtocolChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
237 : {
238 0 : *aLoadFlags = mLoadFlags;
239 0 : return NS_OK;
240 : }
241 :
242 0 : NS_IMETHODIMP nsExtProtocolChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
243 : {
244 0 : mLoadFlags = aLoadFlags;
245 0 : return NS_OK;
246 : }
247 :
248 0 : NS_IMETHODIMP nsExtProtocolChannel::GetIsDocument(bool *aIsDocument)
249 : {
250 0 : return NS_GetIsDocumentChannel(this, aIsDocument);
251 : }
252 :
253 0 : NS_IMETHODIMP nsExtProtocolChannel::GetContentType(nsACString &aContentType)
254 : {
255 0 : return NS_ERROR_NOT_IMPLEMENTED;
256 : }
257 :
258 0 : NS_IMETHODIMP nsExtProtocolChannel::SetContentType(const nsACString &aContentType)
259 : {
260 0 : return NS_ERROR_FAILURE;
261 : }
262 :
263 0 : NS_IMETHODIMP nsExtProtocolChannel::GetContentCharset(nsACString &aContentCharset)
264 : {
265 0 : return NS_ERROR_NOT_IMPLEMENTED;
266 : }
267 :
268 0 : NS_IMETHODIMP nsExtProtocolChannel::SetContentCharset(const nsACString &aContentCharset)
269 : {
270 0 : return NS_ERROR_NOT_IMPLEMENTED;
271 : }
272 :
273 0 : NS_IMETHODIMP nsExtProtocolChannel::GetContentDisposition(uint32_t *aContentDisposition)
274 : {
275 0 : return NS_ERROR_NOT_AVAILABLE;
276 : }
277 :
278 0 : NS_IMETHODIMP nsExtProtocolChannel::SetContentDisposition(uint32_t aContentDisposition)
279 : {
280 0 : return NS_ERROR_NOT_AVAILABLE;
281 : }
282 :
283 0 : NS_IMETHODIMP nsExtProtocolChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
284 : {
285 0 : return NS_ERROR_NOT_AVAILABLE;
286 : }
287 :
288 0 : NS_IMETHODIMP nsExtProtocolChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename)
289 : {
290 0 : return NS_ERROR_NOT_AVAILABLE;
291 : }
292 :
293 0 : NS_IMETHODIMP nsExtProtocolChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
294 : {
295 0 : return NS_ERROR_NOT_AVAILABLE;
296 : }
297 :
298 0 : NS_IMETHODIMP nsExtProtocolChannel::GetContentLength(int64_t * aContentLength)
299 : {
300 0 : *aContentLength = -1;
301 0 : return NS_OK;
302 : }
303 :
304 : NS_IMETHODIMP
305 0 : nsExtProtocolChannel::SetContentLength(int64_t aContentLength)
306 : {
307 0 : NS_NOTREACHED("SetContentLength");
308 0 : return NS_ERROR_NOT_IMPLEMENTED;
309 : }
310 :
311 0 : NS_IMETHODIMP nsExtProtocolChannel::GetOwner(nsISupports * *aPrincipal)
312 : {
313 0 : return NS_ERROR_NOT_IMPLEMENTED;
314 : }
315 :
316 0 : NS_IMETHODIMP nsExtProtocolChannel::SetOwner(nsISupports * aPrincipal)
317 : {
318 0 : return NS_ERROR_NOT_IMPLEMENTED;
319 : }
320 :
321 0 : NS_IMETHODIMP nsExtProtocolChannel::GetLoadInfo(nsILoadInfo **aLoadInfo)
322 : {
323 0 : NS_IF_ADDREF(*aLoadInfo = mLoadInfo);
324 0 : return NS_OK;
325 : }
326 :
327 0 : NS_IMETHODIMP nsExtProtocolChannel::SetLoadInfo(nsILoadInfo *aLoadInfo)
328 : {
329 0 : mLoadInfo = aLoadInfo;
330 0 : return NS_OK;
331 : }
332 :
333 : ////////////////////////////////////////////////////////////////////////////////
334 : // From nsIRequest
335 : ////////////////////////////////////////////////////////////////////////////////
336 :
337 0 : NS_IMETHODIMP nsExtProtocolChannel::GetName(nsACString &result)
338 : {
339 0 : return mUrl->GetSpec(result);
340 : }
341 :
342 0 : NS_IMETHODIMP nsExtProtocolChannel::IsPending(bool *result)
343 : {
344 0 : *result = false;
345 0 : return NS_OK;
346 : }
347 :
348 0 : NS_IMETHODIMP nsExtProtocolChannel::GetStatus(nsresult *status)
349 : {
350 0 : *status = mStatus;
351 0 : return NS_OK;
352 : }
353 :
354 0 : NS_IMETHODIMP nsExtProtocolChannel::Cancel(nsresult status)
355 : {
356 0 : mStatus = status;
357 0 : return NS_OK;
358 : }
359 :
360 0 : NS_IMETHODIMP nsExtProtocolChannel::Suspend()
361 : {
362 0 : NS_NOTREACHED("Suspend");
363 0 : return NS_ERROR_NOT_IMPLEMENTED;
364 : }
365 :
366 0 : NS_IMETHODIMP nsExtProtocolChannel::Resume()
367 : {
368 0 : NS_NOTREACHED("Resume");
369 0 : return NS_ERROR_NOT_IMPLEMENTED;
370 : }
371 :
372 : ///////////////////////////////////////////////////////////////////////
373 : // From nsIChildChannel
374 : //////////////////////////////////////////////////////////////////////
375 :
376 0 : NS_IMETHODIMP nsExtProtocolChannel::ConnectParent(uint32_t registrarId)
377 : {
378 0 : mozilla::dom::ContentChild::GetSingleton()->
379 0 : SendExtProtocolChannelConnectParent(registrarId);
380 0 : return NS_OK;
381 : }
382 :
383 0 : NS_IMETHODIMP nsExtProtocolChannel::CompleteRedirectSetup(nsIStreamListener *listener,
384 : nsISupports *context)
385 : {
386 : // For redirects to external protocols we AsyncOpen on the child
387 : // (not the parent) because child channel has the right docshell
388 : // (which is needed for the select dialog).
389 0 : return AsyncOpen(listener, context);
390 : }
391 :
392 : ///////////////////////////////////////////////////////////////////////
393 : // From nsIParentChannel (derives from nsIStreamListener)
394 : //////////////////////////////////////////////////////////////////////
395 :
396 0 : NS_IMETHODIMP nsExtProtocolChannel::SetParentListener(HttpChannelParentListener* aListener)
397 : {
398 : // This is called as part of the connect parent operation from
399 : // ContentParent::RecvExtProtocolChannelConnectParent. Setting
400 : // this flag tells this channel to not proceed and makes AsyncOpen
401 : // just no-op. Actual operation will happen from the child process
402 : // via CompleteRedirectSetup call on the child channel.
403 0 : mConnectedParent = true;
404 0 : return NS_OK;
405 : }
406 :
407 0 : NS_IMETHODIMP nsExtProtocolChannel::NotifyTrackingProtectionDisabled()
408 : {
409 : // nothing to do
410 0 : return NS_OK;
411 : }
412 :
413 0 : NS_IMETHODIMP nsExtProtocolChannel::SetClassifierMatchedInfo(const nsACString& aList,
414 : const nsACString& aProvider,
415 : const nsACString& aPrefix)
416 : {
417 : // nothing to do
418 0 : return NS_OK;
419 : }
420 :
421 0 : NS_IMETHODIMP nsExtProtocolChannel::NotifyTrackingResource()
422 : {
423 : // nothing to do
424 0 : return NS_OK;
425 : }
426 :
427 0 : NS_IMETHODIMP nsExtProtocolChannel::Delete()
428 : {
429 : // nothing to do
430 0 : return NS_OK;
431 : }
432 :
433 0 : NS_IMETHODIMP nsExtProtocolChannel::OnStartRequest(nsIRequest *aRequest,
434 : nsISupports *aContext)
435 : {
436 : // no data is expected
437 0 : MOZ_CRASH("No data expected from external protocol channel");
438 : return NS_ERROR_UNEXPECTED;
439 : }
440 :
441 0 : NS_IMETHODIMP nsExtProtocolChannel::OnStopRequest(nsIRequest *aRequest,
442 : nsISupports *aContext,
443 : nsresult aStatusCode)
444 : {
445 : // no data is expected
446 0 : MOZ_CRASH("No data expected from external protocol channel");
447 : return NS_ERROR_UNEXPECTED;
448 : }
449 :
450 0 : NS_IMETHODIMP nsExtProtocolChannel::OnDataAvailable(nsIRequest *aRequest,
451 : nsISupports *aContext,
452 : nsIInputStream *aInputStream,
453 : uint64_t aOffset,
454 : uint32_t aCount)
455 : {
456 : // no data is expected
457 0 : MOZ_CRASH("No data expected from external protocol channel");
458 : return NS_ERROR_UNEXPECTED;
459 : }
460 :
461 : ///////////////////////////////////////////////////////////////////////
462 : // the default protocol handler implementation
463 : //////////////////////////////////////////////////////////////////////
464 :
465 2 : nsExternalProtocolHandler::nsExternalProtocolHandler()
466 : {
467 2 : m_schemeName = "default";
468 2 : }
469 :
470 :
471 0 : nsExternalProtocolHandler::~nsExternalProtocolHandler()
472 0 : {}
473 :
474 23 : NS_IMPL_ADDREF(nsExternalProtocolHandler)
475 21 : NS_IMPL_RELEASE(nsExternalProtocolHandler)
476 :
477 19 : NS_INTERFACE_MAP_BEGIN(nsExternalProtocolHandler)
478 19 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIProtocolHandler)
479 17 : NS_INTERFACE_MAP_ENTRY(nsIProtocolHandler)
480 0 : NS_INTERFACE_MAP_ENTRY(nsIExternalProtocolHandler)
481 0 : NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
482 0 : NS_INTERFACE_MAP_END_THREADSAFE
483 :
484 0 : NS_IMETHODIMP nsExternalProtocolHandler::GetScheme(nsACString &aScheme)
485 : {
486 0 : aScheme = m_schemeName;
487 0 : return NS_OK;
488 : }
489 :
490 0 : NS_IMETHODIMP nsExternalProtocolHandler::GetDefaultPort(int32_t *aDefaultPort)
491 : {
492 0 : *aDefaultPort = 0;
493 0 : return NS_OK;
494 : }
495 :
496 : NS_IMETHODIMP
497 0 : nsExternalProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
498 : {
499 : // don't override anything.
500 0 : *_retval = false;
501 0 : return NS_OK;
502 : }
503 : // returns TRUE if the OS can handle this protocol scheme and false otherwise.
504 0 : bool nsExternalProtocolHandler::HaveExternalProtocolHandler(nsIURI * aURI)
505 : {
506 0 : MOZ_ASSERT(aURI);
507 0 : nsAutoCString scheme;
508 0 : aURI->GetScheme(scheme);
509 :
510 0 : nsCOMPtr<nsIExternalProtocolService> extProtSvc(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
511 0 : if (!extProtSvc) {
512 0 : return false;
513 : }
514 :
515 0 : bool haveHandler = false;
516 0 : extProtSvc->ExternalProtocolHandlerExists(scheme.get(), &haveHandler);
517 0 : return haveHandler;
518 : }
519 :
520 0 : NS_IMETHODIMP nsExternalProtocolHandler::GetProtocolFlags(uint32_t *aUritype)
521 : {
522 : // Make it norelative since it is a simple uri
523 0 : *aUritype = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_ANYONE |
524 : URI_NON_PERSISTABLE | URI_DOES_NOT_RETURN_DATA;
525 0 : return NS_OK;
526 : }
527 :
528 1 : NS_IMETHODIMP nsExternalProtocolHandler::NewURI(const nsACString &aSpec,
529 : const char *aCharset, // ignore charset info
530 : nsIURI *aBaseURI,
531 : nsIURI **_retval)
532 : {
533 : nsresult rv;
534 2 : nsCOMPtr<nsIURI> uri = do_CreateInstance(NS_SIMPLEURI_CONTRACTID, &rv);
535 1 : NS_ENSURE_SUCCESS(rv, rv);
536 :
537 1 : rv = uri->SetSpec(aSpec);
538 1 : NS_ENSURE_SUCCESS(rv, rv);
539 :
540 1 : NS_ADDREF(*_retval = uri);
541 1 : return NS_OK;
542 : }
543 :
544 : NS_IMETHODIMP
545 0 : nsExternalProtocolHandler::NewChannel2(nsIURI* aURI,
546 : nsILoadInfo* aLoadInfo,
547 : nsIChannel** aRetval)
548 : {
549 0 : NS_ENSURE_TRUE(aURI, NS_ERROR_UNKNOWN_PROTOCOL);
550 0 : NS_ENSURE_TRUE(aRetval, NS_ERROR_UNKNOWN_PROTOCOL);
551 :
552 : // Only try to return a channel if we have a protocol handler for the url.
553 : // nsOSHelperAppService::LoadUriInternal relies on this to check trustedness
554 : // for some platforms at least. (win uses ::ShellExecute and unix uses
555 : // gnome_url_show.)
556 0 : if (!HaveExternalProtocolHandler(aURI)) {
557 0 : return NS_ERROR_UNKNOWN_PROTOCOL;
558 : }
559 :
560 0 : nsCOMPtr<nsIChannel> channel = new nsExtProtocolChannel(aURI, aLoadInfo);
561 0 : channel.forget(aRetval);
562 0 : return NS_OK;
563 : }
564 :
565 0 : NS_IMETHODIMP nsExternalProtocolHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval)
566 : {
567 0 : return NewChannel2(aURI, nullptr, _retval);
568 : }
569 :
570 : ///////////////////////////////////////////////////////////////////////
571 : // External protocol handler interface implementation
572 : //////////////////////////////////////////////////////////////////////
573 0 : NS_IMETHODIMP nsExternalProtocolHandler::ExternalAppExistsForScheme(const nsACString& aScheme, bool *_retval)
574 : {
575 0 : nsCOMPtr<nsIExternalProtocolService> extProtSvc(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
576 0 : if (extProtSvc)
577 0 : return extProtSvc->ExternalProtocolHandlerExists(
578 0 : PromiseFlatCString(aScheme).get(), _retval);
579 :
580 : // In case we don't have external protocol service.
581 0 : *_retval = false;
582 0 : return NS_OK;
583 : }
|