Coverage Report

Created: 2018-09-25 14:53

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