/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 | } |