1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:set ts=4 sw=4 sts=4 et: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "nsViewSourceChannel.h"
8 #include "nsIIOService.h"
9 #include "nsMimeTypes.h"
10 #include "nsNetUtil.h"
11 #include "nsContentUtils.h"
12 #include "nsIHttpHeaderVisitor.h"
13 #include "nsContentSecurityManager.h"
14 #include "nsNullPrincipal.h"
15 #include "nsServiceManagerUtils.h"
16 #include "nsIInputStreamChannel.h"
17 #include "mozilla/DebugOnly.h"
18
19 NS_IMPL_ADDREF(nsViewSourceChannel)
NS_IMPL_RELEASE(nsViewSourceChannel)20 NS_IMPL_RELEASE(nsViewSourceChannel)
21 /*
22 This QI uses NS_INTERFACE_MAP_ENTRY_CONDITIONAL to check for
23 non-nullness of mHttpChannel, mCachingChannel, and mUploadChannel.
24 */
25 NS_INTERFACE_MAP_BEGIN(nsViewSourceChannel)
26 NS_INTERFACE_MAP_ENTRY(nsIViewSourceChannel)
27 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
28 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
29 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIHttpChannel, mHttpChannel)
30 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIHttpChannelInternal, mHttpChannelInternal)
31 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICachingChannel, mCachingChannel)
32 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICacheInfoChannel, mCacheInfoChannel)
33 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIApplicationCacheChannel, mApplicationCacheChannel)
34 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIUploadChannel, mUploadChannel)
35 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIFormPOSTActionChannel, mPostChannel)
36 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIRequest, nsIViewSourceChannel)
37 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIChannel, nsIViewSourceChannel)
38 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIViewSourceChannel)
39 NS_INTERFACE_MAP_END
40
41 nsresult
42 nsViewSourceChannel::Init(nsIURI* uri)
43 {
44 mOriginalURI = uri;
45
46 nsAutoCString path;
47 nsresult rv = uri->GetPath(path);
48 if (NS_FAILED(rv))
49 return rv;
50
51 nsCOMPtr<nsIIOService> pService(do_GetIOService(&rv));
52 if (NS_FAILED(rv)) return rv;
53
54 nsAutoCString scheme;
55 rv = pService->ExtractScheme(path, scheme);
56 if (NS_FAILED(rv))
57 return rv;
58
59 // prevent viewing source of javascript URIs (see bug 204779)
60 if (scheme.LowerCaseEqualsLiteral("javascript")) {
61 NS_WARNING("blocking view-source:javascript:");
62 return NS_ERROR_INVALID_ARG;
63 }
64
65 // This function is called from within nsViewSourceHandler::NewChannel2
66 // and sets the right loadInfo right after returning from this function.
67 // Until then we follow the principal of least privilege and use
68 // nullPrincipal as the loadingPrincipal and the least permissive
69 // securityflag.
70 nsCOMPtr<nsIPrincipal> nullPrincipal = nsNullPrincipal::Create();
71
72 rv = pService->NewChannel2(path,
73 nullptr, // aOriginCharset
74 nullptr, // aCharSet
75 nullptr, // aLoadingNode
76 nullPrincipal,
77 nullptr, // aTriggeringPrincipal
78 nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
79 nsIContentPolicy::TYPE_OTHER,
80 getter_AddRefs(mChannel));
81 NS_ENSURE_SUCCESS(rv, rv);
82
83 mIsSrcdocChannel = false;
84
85 mChannel->SetOriginalURI(mOriginalURI);
86 mHttpChannel = do_QueryInterface(mChannel);
87 mHttpChannelInternal = do_QueryInterface(mChannel);
88 mCachingChannel = do_QueryInterface(mChannel);
89 mCacheInfoChannel = do_QueryInterface(mChannel);
90 mApplicationCacheChannel = do_QueryInterface(mChannel);
91 mUploadChannel = do_QueryInterface(mChannel);
92 mPostChannel = do_QueryInterface(mChannel);
93
94 return NS_OK;
95 }
96
97 nsresult
InitSrcdoc(nsIURI * aURI,nsIURI * aBaseURI,const nsAString & aSrcdoc,nsILoadInfo * aLoadInfo)98 nsViewSourceChannel::InitSrcdoc(nsIURI* aURI,
99 nsIURI* aBaseURI,
100 const nsAString &aSrcdoc,
101 nsILoadInfo* aLoadInfo)
102 {
103 nsresult rv;
104
105 nsCOMPtr<nsIURI> inStreamURI;
106 // Need to strip view-source: from the URI. Hardcoded to
107 // about:srcdoc as this is the only permissible URI for srcdoc
108 // loads
109 rv = NS_NewURI(getter_AddRefs(inStreamURI),
110 NS_LITERAL_STRING("about:srcdoc"));
111 NS_ENSURE_SUCCESS(rv, rv);
112
113 rv = NS_NewInputStreamChannelInternal(getter_AddRefs(mChannel),
114 inStreamURI,
115 aSrcdoc,
116 NS_LITERAL_CSTRING("text/html"),
117 aLoadInfo,
118 true);
119
120 NS_ENSURE_SUCCESS(rv, rv);
121 mOriginalURI = aURI;
122 mIsSrcdocChannel = true;
123
124 mChannel->SetOriginalURI(mOriginalURI);
125 mHttpChannel = do_QueryInterface(mChannel);
126 mHttpChannelInternal = do_QueryInterface(mChannel);
127 mCachingChannel = do_QueryInterface(mChannel);
128 mCacheInfoChannel = do_QueryInterface(mChannel);
129 mApplicationCacheChannel = do_QueryInterface(mChannel);
130 mUploadChannel = do_QueryInterface(mChannel);
131
132 nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(mChannel);
133 MOZ_ASSERT(isc);
134 isc->SetBaseURI(aBaseURI);
135 return NS_OK;
136 }
137
138 ////////////////////////////////////////////////////////////////////////////////
139 // nsIRequest methods:
140
141 NS_IMETHODIMP
GetName(nsACString & result)142 nsViewSourceChannel::GetName(nsACString &result)
143 {
144 return NS_ERROR_NOT_IMPLEMENTED;
145 }
146
147 NS_IMETHODIMP
GetTransferSize(uint64_t * aTransferSize)148 nsViewSourceChannel::GetTransferSize(uint64_t *aTransferSize)
149 {
150 return NS_ERROR_NOT_IMPLEMENTED;
151 }
152
153 NS_IMETHODIMP
GetDecodedBodySize(uint64_t * aDecodedBodySize)154 nsViewSourceChannel::GetDecodedBodySize(uint64_t *aDecodedBodySize)
155 {
156 return NS_ERROR_NOT_IMPLEMENTED;
157 }
158
159 NS_IMETHODIMP
GetEncodedBodySize(uint64_t * aEncodedBodySize)160 nsViewSourceChannel::GetEncodedBodySize(uint64_t *aEncodedBodySize)
161 {
162 return NS_ERROR_NOT_IMPLEMENTED;
163 }
164
165 NS_IMETHODIMP
IsPending(bool * result)166 nsViewSourceChannel::IsPending(bool *result)
167 {
168 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
169
170 return mChannel->IsPending(result);
171 }
172
173 NS_IMETHODIMP
GetStatus(nsresult * status)174 nsViewSourceChannel::GetStatus(nsresult *status)
175 {
176 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
177
178 return mChannel->GetStatus(status);
179 }
180
181 NS_IMETHODIMP
Cancel(nsresult status)182 nsViewSourceChannel::Cancel(nsresult status)
183 {
184 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
185
186 return mChannel->Cancel(status);
187 }
188
189 NS_IMETHODIMP
Suspend(void)190 nsViewSourceChannel::Suspend(void)
191 {
192 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
193
194 return mChannel->Suspend();
195 }
196
197 NS_IMETHODIMP
Resume(void)198 nsViewSourceChannel::Resume(void)
199 {
200 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
201
202 return mChannel->Resume();
203 }
204
205 ////////////////////////////////////////////////////////////////////////////////
206 // nsIChannel methods:
207
208 NS_IMETHODIMP
GetOriginalURI(nsIURI ** aURI)209 nsViewSourceChannel::GetOriginalURI(nsIURI* *aURI)
210 {
211 NS_ASSERTION(aURI, "Null out param!");
212 *aURI = mOriginalURI;
213 NS_ADDREF(*aURI);
214 return NS_OK;
215 }
216
217 NS_IMETHODIMP
SetOriginalURI(nsIURI * aURI)218 nsViewSourceChannel::SetOriginalURI(nsIURI* aURI)
219 {
220 NS_ENSURE_ARG_POINTER(aURI);
221 mOriginalURI = aURI;
222 return NS_OK;
223 }
224
225 NS_IMETHODIMP
GetURI(nsIURI ** aURI)226 nsViewSourceChannel::GetURI(nsIURI* *aURI)
227 {
228 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
229
230 nsCOMPtr<nsIURI> uri;
231 nsresult rv = mChannel->GetURI(getter_AddRefs(uri));
232 if (NS_FAILED(rv))
233 return rv;
234
235 // protect ourselves against broken channel implementations
236 if (!uri) {
237 NS_ERROR("inner channel returned NS_OK and a null URI");
238 return NS_ERROR_UNEXPECTED;
239 }
240
241 nsAutoCString spec;
242 rv = uri->GetSpec(spec);
243 if (NS_FAILED(rv)) {
244 return rv;
245 }
246
247 /* XXX Gross hack -- NS_NewURI goes into an infinite loop on
248 non-flat specs. See bug 136980 */
249 return NS_NewURI(aURI, nsAutoCString(NS_LITERAL_CSTRING("view-source:")+spec), nullptr);
250 }
251
252 NS_IMETHODIMP
Open(nsIInputStream ** _retval)253 nsViewSourceChannel::Open(nsIInputStream **_retval)
254 {
255 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
256
257 nsresult rv = NS_MaybeOpenChannelUsingOpen2(mChannel, _retval);
258 if (NS_SUCCEEDED(rv)) {
259 mOpened = true;
260 }
261 return rv;
262 }
263
264 NS_IMETHODIMP
Open2(nsIInputStream ** aStream)265 nsViewSourceChannel::Open2(nsIInputStream** aStream)
266 {
267 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
268 nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
269 if(!loadInfo) {
270 MOZ_ASSERT(loadInfo, "can not enforce security without loadInfo");
271 return NS_ERROR_UNEXPECTED;
272 }
273 // setting the flag on the loadInfo indicates that the underlying
274 // channel will be openend using Open2() and hence performs
275 // the necessary security checks.
276 loadInfo->SetEnforceSecurity(true);
277 return Open(aStream);
278 }
279
280 NS_IMETHODIMP
AsyncOpen(nsIStreamListener * aListener,nsISupports * ctxt)281 nsViewSourceChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
282 {
283 #ifdef DEBUG
284 {
285 nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
286 MOZ_ASSERT(!loadInfo || loadInfo->GetSecurityMode() == 0 ||
287 loadInfo->GetEnforceSecurity(),
288 "security flags in loadInfo but asyncOpen2() not called");
289 }
290 #endif
291
292 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
293
294 mListener = aListener;
295
296 /*
297 * We want to add ourselves to the loadgroup before opening
298 * mChannel, since we want to make sure we're in the loadgroup
299 * when mChannel finishes and fires OnStopRequest()
300 */
301
302 nsCOMPtr<nsILoadGroup> loadGroup;
303 mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
304 if (loadGroup)
305 loadGroup->AddRequest(static_cast<nsIViewSourceChannel*>
306 (this), nullptr);
307
308 nsresult rv = NS_OK;
309 nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
310 if (loadInfo && loadInfo->GetEnforceSecurity()) {
311 rv = mChannel->AsyncOpen2(this);
312 }
313 else {
314 rv = mChannel->AsyncOpen(this, ctxt);
315 }
316
317 if (NS_FAILED(rv) && loadGroup)
318 loadGroup->RemoveRequest(static_cast<nsIViewSourceChannel*>
319 (this),
320 nullptr, rv);
321
322 if (NS_SUCCEEDED(rv)) {
323 mOpened = true;
324 }
325
326 return rv;
327 }
328
329 NS_IMETHODIMP
AsyncOpen2(nsIStreamListener * aListener)330 nsViewSourceChannel::AsyncOpen2(nsIStreamListener *aListener)
331 {
332 nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
333 if(!loadInfo) {
334 MOZ_ASSERT(loadInfo, "can not enforce security without loadInfo");
335 return NS_ERROR_UNEXPECTED;
336 }
337 // setting the flag on the loadInfo indicates that the underlying
338 // channel will be openend using AsyncOpen2() and hence performs
339 // the necessary security checks.
340 loadInfo->SetEnforceSecurity(true);
341 return AsyncOpen(aListener, nullptr);
342 }
343 /*
344 * Both the view source channel and mChannel are added to the
345 * loadgroup. There should never be more than one request in the
346 * loadgroup that has LOAD_DOCUMENT_URI set. The one that has this
347 * flag set is the request whose URI is used to refetch the document,
348 * so it better be the viewsource channel.
349 *
350 * Therefore, we need to make sure that
351 * 1) The load flags on mChannel _never_ include LOAD_DOCUMENT_URI
352 * 2) The load flags on |this| include LOAD_DOCUMENT_URI when it was
353 * set via SetLoadFlags (mIsDocument keeps track of this flag).
354 */
355
356 NS_IMETHODIMP
GetLoadFlags(uint32_t * aLoadFlags)357 nsViewSourceChannel::GetLoadFlags(uint32_t *aLoadFlags)
358 {
359 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
360
361 nsresult rv = mChannel->GetLoadFlags(aLoadFlags);
362 if (NS_FAILED(rv))
363 return rv;
364
365 // This should actually be just LOAD_DOCUMENT_URI but the win32 compiler
366 // fails to deal due to amiguous inheritance. nsIChannel::LOAD_DOCUMENT_URI
367 // also fails; the Win32 compiler thinks that's supposed to be a method.
368 if (mIsDocument)
369 *aLoadFlags |= ::nsIChannel::LOAD_DOCUMENT_URI;
370
371 return rv;
372 }
373
374 NS_IMETHODIMP
SetLoadFlags(uint32_t aLoadFlags)375 nsViewSourceChannel::SetLoadFlags(uint32_t aLoadFlags)
376 {
377 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
378
379 // "View source" always wants the currently cached content.
380 // We also want to have _this_ channel, not mChannel to be the
381 // 'document' channel in the loadgroup.
382
383 // These should actually be just LOAD_FROM_CACHE and LOAD_DOCUMENT_URI but
384 // the win32 compiler fails to deal due to amiguous inheritance.
385 // nsIChannel::LOAD_DOCUMENT_URI/nsIRequest::LOAD_FROM_CACHE also fails; the
386 // Win32 compiler thinks that's supposed to be a method.
387 mIsDocument = (aLoadFlags & ::nsIChannel::LOAD_DOCUMENT_URI) ? true : false;
388
389 nsresult rv = mChannel->SetLoadFlags((aLoadFlags |
390 ::nsIRequest::LOAD_FROM_CACHE) &
391 ~::nsIChannel::LOAD_DOCUMENT_URI);
392 if (NS_WARN_IF(NS_FAILED(rv))) {
393 return rv;
394 }
395
396 if (mHttpChannel) {
397 rv = mHttpChannel->SetIsMainDocumentChannel(aLoadFlags & ::nsIChannel::LOAD_DOCUMENT_URI);
398 MOZ_ASSERT(NS_SUCCEEDED(rv));
399 }
400
401 return NS_OK;
402 }
403
404 NS_IMETHODIMP
GetContentType(nsACString & aContentType)405 nsViewSourceChannel::GetContentType(nsACString &aContentType)
406 {
407 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
408
409 aContentType.Truncate();
410
411 if (mContentType.IsEmpty())
412 {
413 // Get the current content type
414 nsresult rv;
415 nsAutoCString contentType;
416 rv = mChannel->GetContentType(contentType);
417 if (NS_FAILED(rv)) return rv;
418
419 // If we don't know our type, just say so. The unknown
420 // content decoder will then kick in automatically, and it
421 // will call our SetOriginalContentType method instead of our
422 // SetContentType method to set the type it determines.
423 if (!contentType.Equals(UNKNOWN_CONTENT_TYPE)) {
424 contentType = VIEWSOURCE_CONTENT_TYPE;
425 }
426
427 mContentType = contentType;
428 }
429
430 aContentType = mContentType;
431 return NS_OK;
432 }
433
434 NS_IMETHODIMP
SetContentType(const nsACString & aContentType)435 nsViewSourceChannel::SetContentType(const nsACString &aContentType)
436 {
437 // Our GetContentType() currently returns VIEWSOURCE_CONTENT_TYPE
438 //
439 // However, during the parsing phase the parser calls our
440 // channel's GetContentType(). Returning the string above trips up
441 // the parser. In order to avoid messy changes and not to have the
442 // parser depend on nsIViewSourceChannel Vidur proposed the
443 // following solution:
444 //
445 // The ViewSourceChannel initially returns a content type of
446 // VIEWSOURCE_CONTENT_TYPE. Based on this type decisions to
447 // create a viewer for doing a view source are made. After the
448 // viewer is created, nsLayoutDLF::CreateInstance() calls this
449 // SetContentType() with the original content type. When it's
450 // time for the parser to find out the content type it will call
451 // our channel's GetContentType() and it will get the original
452 // content type, such as, text/html and everything is kosher from
453 // then on.
454
455 if (!mOpened) {
456 // We do not take hints
457 return NS_ERROR_NOT_AVAILABLE;
458 }
459
460 mContentType = aContentType;
461 return NS_OK;
462 }
463
464 NS_IMETHODIMP
GetContentCharset(nsACString & aContentCharset)465 nsViewSourceChannel::GetContentCharset(nsACString &aContentCharset)
466 {
467 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
468
469 return mChannel->GetContentCharset(aContentCharset);
470 }
471
472 NS_IMETHODIMP
SetContentCharset(const nsACString & aContentCharset)473 nsViewSourceChannel::SetContentCharset(const nsACString &aContentCharset)
474 {
475 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
476
477 return mChannel->SetContentCharset(aContentCharset);
478 }
479
480 // We don't forward these methods becacuse content-disposition isn't whitelisted
481 // (see GetResponseHeader/VisitResponseHeaders).
482 NS_IMETHODIMP
GetContentDisposition(uint32_t * aContentDisposition)483 nsViewSourceChannel::GetContentDisposition(uint32_t *aContentDisposition)
484 {
485 return NS_ERROR_NOT_AVAILABLE;
486 }
487
488 NS_IMETHODIMP
SetContentDisposition(uint32_t aContentDisposition)489 nsViewSourceChannel::SetContentDisposition(uint32_t aContentDisposition)
490 {
491 return NS_ERROR_NOT_AVAILABLE;
492 }
493
494 NS_IMETHODIMP
GetContentDispositionFilename(nsAString & aContentDispositionFilename)495 nsViewSourceChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
496 {
497 return NS_ERROR_NOT_AVAILABLE;
498 }
499
500 NS_IMETHODIMP
SetContentDispositionFilename(const nsAString & aContentDispositionFilename)501 nsViewSourceChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename)
502 {
503 return NS_ERROR_NOT_AVAILABLE;
504 }
505
506 NS_IMETHODIMP
GetContentDispositionHeader(nsACString & aContentDispositionHeader)507 nsViewSourceChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
508 {
509 return NS_ERROR_NOT_AVAILABLE;
510 }
511
512 NS_IMETHODIMP
GetContentLength(int64_t * aContentLength)513 nsViewSourceChannel::GetContentLength(int64_t *aContentLength)
514 {
515 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
516
517 return mChannel->GetContentLength(aContentLength);
518 }
519
520 NS_IMETHODIMP
SetContentLength(int64_t aContentLength)521 nsViewSourceChannel::SetContentLength(int64_t aContentLength)
522 {
523 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
524
525 return mChannel->SetContentLength(aContentLength);
526 }
527
528 NS_IMETHODIMP
GetLoadGroup(nsILoadGroup ** aLoadGroup)529 nsViewSourceChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
530 {
531 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
532
533 return mChannel->GetLoadGroup(aLoadGroup);
534 }
535
536 NS_IMETHODIMP
SetLoadGroup(nsILoadGroup * aLoadGroup)537 nsViewSourceChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
538 {
539 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
540
541 return mChannel->SetLoadGroup(aLoadGroup);
542 }
543
544 NS_IMETHODIMP
GetOwner(nsISupports ** aOwner)545 nsViewSourceChannel::GetOwner(nsISupports* *aOwner)
546 {
547 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
548
549 return mChannel->GetOwner(aOwner);
550 }
551
552 NS_IMETHODIMP
SetOwner(nsISupports * aOwner)553 nsViewSourceChannel::SetOwner(nsISupports* aOwner)
554 {
555 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
556
557 return mChannel->SetOwner(aOwner);
558 }
559
560 NS_IMETHODIMP
GetLoadInfo(nsILoadInfo ** aLoadInfo)561 nsViewSourceChannel::GetLoadInfo(nsILoadInfo* *aLoadInfo)
562 {
563 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
564
565 return mChannel->GetLoadInfo(aLoadInfo);
566 }
567
568 NS_IMETHODIMP
SetLoadInfo(nsILoadInfo * aLoadInfo)569 nsViewSourceChannel::SetLoadInfo(nsILoadInfo* aLoadInfo)
570 {
571 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
572
573 return mChannel->SetLoadInfo(aLoadInfo);
574 }
575
576 NS_IMETHODIMP
GetNotificationCallbacks(nsIInterfaceRequestor ** aNotificationCallbacks)577 nsViewSourceChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
578 {
579 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
580
581 return mChannel->GetNotificationCallbacks(aNotificationCallbacks);
582 }
583
584 NS_IMETHODIMP
SetNotificationCallbacks(nsIInterfaceRequestor * aNotificationCallbacks)585 nsViewSourceChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
586 {
587 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
588
589 return mChannel->SetNotificationCallbacks(aNotificationCallbacks);
590 }
591
592 NS_IMETHODIMP
GetSecurityInfo(nsISupports ** aSecurityInfo)593 nsViewSourceChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
594 {
595 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
596
597 return mChannel->GetSecurityInfo(aSecurityInfo);
598 }
599
600 // nsIViewSourceChannel methods
601 NS_IMETHODIMP
GetOriginalContentType(nsACString & aContentType)602 nsViewSourceChannel::GetOriginalContentType(nsACString &aContentType)
603 {
604 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
605
606 return mChannel->GetContentType(aContentType);
607 }
608
609 NS_IMETHODIMP
SetOriginalContentType(const nsACString & aContentType)610 nsViewSourceChannel::SetOriginalContentType(const nsACString &aContentType)
611 {
612 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
613
614 // clear our cached content-type value
615 mContentType.Truncate();
616
617 return mChannel->SetContentType(aContentType);
618 }
619
620 NS_IMETHODIMP
GetIsSrcdocChannel(bool * aIsSrcdocChannel)621 nsViewSourceChannel::GetIsSrcdocChannel(bool* aIsSrcdocChannel)
622 {
623 *aIsSrcdocChannel = mIsSrcdocChannel;
624 return NS_OK;
625 }
626
627 NS_IMETHODIMP
GetBaseURI(nsIURI ** aBaseURI)628 nsViewSourceChannel::GetBaseURI(nsIURI** aBaseURI)
629 {
630 if (mIsSrcdocChannel) {
631 nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(mChannel);
632 if (isc) {
633 return isc->GetBaseURI(aBaseURI);
634 }
635 }
636 *aBaseURI = mBaseURI;
637 NS_IF_ADDREF(*aBaseURI);
638 return NS_OK;
639 }
640
641 NS_IMETHODIMP
SetBaseURI(nsIURI * aBaseURI)642 nsViewSourceChannel::SetBaseURI(nsIURI* aBaseURI)
643 {
644 mBaseURI = aBaseURI;
645 return NS_OK;
646 }
647
648 NS_IMETHODIMP
GetProtocolVersion(nsACString & aProtocolVersion)649 nsViewSourceChannel::GetProtocolVersion(nsACString& aProtocolVersion)
650 {
651 return NS_ERROR_NOT_IMPLEMENTED;
652 }
653
654 // nsIRequestObserver methods
655 NS_IMETHODIMP
OnStartRequest(nsIRequest * aRequest,nsISupports * aContext)656 nsViewSourceChannel::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
657 {
658 NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE);
659 // The channel may have gotten redirected... Time to update our info
660 mChannel = do_QueryInterface(aRequest);
661 mHttpChannel = do_QueryInterface(aRequest);
662 mCachingChannel = do_QueryInterface(aRequest);
663 mCacheInfoChannel = do_QueryInterface(mChannel);
664 mUploadChannel = do_QueryInterface(aRequest);
665
666 return mListener->OnStartRequest(static_cast<nsIViewSourceChannel*>
667 (this),
668 aContext);
669 }
670
671
672 NS_IMETHODIMP
OnStopRequest(nsIRequest * aRequest,nsISupports * aContext,nsresult aStatus)673 nsViewSourceChannel::OnStopRequest(nsIRequest *aRequest, nsISupports* aContext,
674 nsresult aStatus)
675 {
676 NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE);
677 if (mChannel)
678 {
679 nsCOMPtr<nsILoadGroup> loadGroup;
680 mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
681 if (loadGroup)
682 {
683 loadGroup->RemoveRequest(static_cast<nsIViewSourceChannel*>
684 (this),
685 nullptr, aStatus);
686 }
687 }
688 return mListener->OnStopRequest(static_cast<nsIViewSourceChannel*>
689 (this),
690 aContext, aStatus);
691 }
692
693
694 // nsIStreamListener methods
695 NS_IMETHODIMP
OnDataAvailable(nsIRequest * aRequest,nsISupports * aContext,nsIInputStream * aInputStream,uint64_t aSourceOffset,uint32_t aLength)696 nsViewSourceChannel::OnDataAvailable(nsIRequest *aRequest, nsISupports* aContext,
697 nsIInputStream *aInputStream,
698 uint64_t aSourceOffset,
699 uint32_t aLength)
700 {
701 NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE);
702 return mListener->OnDataAvailable(static_cast<nsIViewSourceChannel*>
703 (this),
704 aContext, aInputStream,
705 aSourceOffset, aLength);
706 }
707
708
709 // nsIHttpChannel methods
710
711 // We want to forward most of nsIHttpChannel over to mHttpChannel, but we want
712 // to override GetRequestHeader and VisitHeaders. The reason is that we don't
713 // want various headers like Link: and Refresh: applying to view-source.
714 NS_IMETHODIMP
GetChannelId(nsACString & aChannelId)715 nsViewSourceChannel::GetChannelId(nsACString& aChannelId)
716 {
717 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
718 mHttpChannel->GetChannelId(aChannelId);
719 }
720
721 NS_IMETHODIMP
SetChannelId(const nsACString & aChannelId)722 nsViewSourceChannel::SetChannelId(const nsACString& aChannelId)
723 {
724 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
725 mHttpChannel->SetChannelId(aChannelId);
726 }
727
728 NS_IMETHODIMP
GetTopLevelContentWindowId(uint64_t * aWindowId)729 nsViewSourceChannel::GetTopLevelContentWindowId(uint64_t *aWindowId)
730 {
731 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
732 mHttpChannel->GetTopLevelContentWindowId(aWindowId);
733 }
734
735 NS_IMETHODIMP
SetTopLevelContentWindowId(uint64_t aWindowId)736 nsViewSourceChannel::SetTopLevelContentWindowId(uint64_t aWindowId)
737 {
738 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
739 mHttpChannel->SetTopLevelContentWindowId(aWindowId);
740 }
741
742 NS_IMETHODIMP
GetRequestMethod(nsACString & aRequestMethod)743 nsViewSourceChannel::GetRequestMethod(nsACString & aRequestMethod)
744 {
745 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
746 mHttpChannel->GetRequestMethod(aRequestMethod);
747 }
748
749 NS_IMETHODIMP
SetRequestMethod(const nsACString & aRequestMethod)750 nsViewSourceChannel::SetRequestMethod(const nsACString & aRequestMethod)
751 {
752 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
753 mHttpChannel->SetRequestMethod(aRequestMethod);
754 }
755
756 NS_IMETHODIMP
GetReferrer(nsIURI ** aReferrer)757 nsViewSourceChannel::GetReferrer(nsIURI * *aReferrer)
758 {
759 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
760 mHttpChannel->GetReferrer(aReferrer);
761 }
762
763 NS_IMETHODIMP
SetReferrer(nsIURI * aReferrer)764 nsViewSourceChannel::SetReferrer(nsIURI * aReferrer)
765 {
766 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
767 mHttpChannel->SetReferrer(aReferrer);
768 }
769
770 NS_IMETHODIMP
GetReferrerPolicy(uint32_t * aReferrerPolicy)771 nsViewSourceChannel::GetReferrerPolicy(uint32_t *aReferrerPolicy)
772 {
773 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
774 mHttpChannel->GetReferrerPolicy(aReferrerPolicy);
775 }
776
777 NS_IMETHODIMP
SetReferrerWithPolicy(nsIURI * aReferrer,uint32_t aReferrerPolicy)778 nsViewSourceChannel::SetReferrerWithPolicy(nsIURI * aReferrer,
779 uint32_t aReferrerPolicy)
780 {
781 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
782 mHttpChannel->SetReferrerWithPolicy(aReferrer, aReferrerPolicy);
783 }
784
785 NS_IMETHODIMP
GetRequestHeader(const nsACString & aHeader,nsACString & aValue)786 nsViewSourceChannel::GetRequestHeader(const nsACString & aHeader,
787 nsACString & aValue)
788 {
789 aValue.Truncate();
790 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
791 mHttpChannel->GetRequestHeader(aHeader, aValue);
792 }
793
794 NS_IMETHODIMP
SetRequestHeader(const nsACString & aHeader,const nsACString & aValue,bool aMerge)795 nsViewSourceChannel::SetRequestHeader(const nsACString & aHeader,
796 const nsACString & aValue,
797 bool aMerge)
798 {
799 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
800 mHttpChannel->SetRequestHeader(aHeader, aValue, aMerge);
801 }
802
803 NS_IMETHODIMP
SetEmptyRequestHeader(const nsACString & aHeader)804 nsViewSourceChannel::SetEmptyRequestHeader(const nsACString & aHeader)
805 {
806 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
807 mHttpChannel->SetEmptyRequestHeader(aHeader);
808 }
809
810 NS_IMETHODIMP
VisitRequestHeaders(nsIHttpHeaderVisitor * aVisitor)811 nsViewSourceChannel::VisitRequestHeaders(nsIHttpHeaderVisitor *aVisitor)
812 {
813 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
814 mHttpChannel->VisitRequestHeaders(aVisitor);
815 }
816
817 NS_IMETHODIMP
VisitNonDefaultRequestHeaders(nsIHttpHeaderVisitor * aVisitor)818 nsViewSourceChannel::VisitNonDefaultRequestHeaders(nsIHttpHeaderVisitor *aVisitor)
819 {
820 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
821 mHttpChannel->VisitNonDefaultRequestHeaders(aVisitor);
822 }
823
824 NS_IMETHODIMP
GetAllowPipelining(bool * aAllowPipelining)825 nsViewSourceChannel::GetAllowPipelining(bool *aAllowPipelining)
826 {
827 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
828 mHttpChannel->GetAllowPipelining(aAllowPipelining);
829 }
830
831 NS_IMETHODIMP
SetAllowPipelining(bool aAllowPipelining)832 nsViewSourceChannel::SetAllowPipelining(bool aAllowPipelining)
833 {
834 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
835 mHttpChannel->SetAllowPipelining(aAllowPipelining);
836 }
837
838 NS_IMETHODIMP
GetAllowSTS(bool * aAllowSTS)839 nsViewSourceChannel::GetAllowSTS(bool *aAllowSTS)
840 {
841 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
842 mHttpChannel->GetAllowSTS(aAllowSTS);
843 }
844
845 NS_IMETHODIMP
SetAllowSTS(bool aAllowSTS)846 nsViewSourceChannel::SetAllowSTS(bool aAllowSTS)
847 {
848 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
849 mHttpChannel->SetAllowSTS(aAllowSTS);
850 }
851
852 NS_IMETHODIMP
GetRedirectionLimit(uint32_t * aRedirectionLimit)853 nsViewSourceChannel::GetRedirectionLimit(uint32_t *aRedirectionLimit)
854 {
855 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
856 mHttpChannel->GetRedirectionLimit(aRedirectionLimit);
857 }
858
859 NS_IMETHODIMP
SetRedirectionLimit(uint32_t aRedirectionLimit)860 nsViewSourceChannel::SetRedirectionLimit(uint32_t aRedirectionLimit)
861 {
862 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
863 mHttpChannel->SetRedirectionLimit(aRedirectionLimit);
864 }
865
866 NS_IMETHODIMP
GetResponseStatus(uint32_t * aResponseStatus)867 nsViewSourceChannel::GetResponseStatus(uint32_t *aResponseStatus)
868 {
869 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
870 mHttpChannel->GetResponseStatus(aResponseStatus);
871 }
872
873 NS_IMETHODIMP
GetResponseStatusText(nsACString & aResponseStatusText)874 nsViewSourceChannel::GetResponseStatusText(nsACString & aResponseStatusText)
875 {
876 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
877 mHttpChannel->GetResponseStatusText(aResponseStatusText);
878 }
879
880 NS_IMETHODIMP
GetRequestSucceeded(bool * aRequestSucceeded)881 nsViewSourceChannel::GetRequestSucceeded(bool *aRequestSucceeded)
882 {
883 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
884 mHttpChannel->GetRequestSucceeded(aRequestSucceeded);
885 }
886
887 NS_IMETHODIMP
GetResponseHeader(const nsACString & aHeader,nsACString & aValue)888 nsViewSourceChannel::GetResponseHeader(const nsACString & aHeader,
889 nsACString & aValue)
890 {
891 aValue.Truncate();
892 if (!mHttpChannel)
893 return NS_ERROR_NULL_POINTER;
894
895 if (!aHeader.Equals(NS_LITERAL_CSTRING("Content-Type"),
896 nsCaseInsensitiveCStringComparator()) &&
897 !aHeader.Equals(NS_LITERAL_CSTRING("Content-Security-Policy"),
898 nsCaseInsensitiveCStringComparator()) &&
899 !aHeader.Equals(NS_LITERAL_CSTRING("Content-Security-Policy-Report-Only"),
900 nsCaseInsensitiveCStringComparator()) &&
901 !aHeader.Equals(NS_LITERAL_CSTRING("X-Frame-Options"),
902 nsCaseInsensitiveCStringComparator())) {
903 return NS_OK;
904 }
905
906 return mHttpChannel->GetResponseHeader(aHeader, aValue);
907 }
908
909 NS_IMETHODIMP
SetResponseHeader(const nsACString & header,const nsACString & value,bool merge)910 nsViewSourceChannel::SetResponseHeader(const nsACString & header,
911 const nsACString & value, bool merge)
912 {
913 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
914 mHttpChannel->SetResponseHeader(header, value, merge);
915 }
916
917 NS_IMETHODIMP
VisitResponseHeaders(nsIHttpHeaderVisitor * aVisitor)918 nsViewSourceChannel::VisitResponseHeaders(nsIHttpHeaderVisitor *aVisitor)
919 {
920 if (!mHttpChannel)
921 return NS_ERROR_NULL_POINTER;
922
923 NS_NAMED_LITERAL_CSTRING(contentTypeStr, "Content-Type");
924 nsAutoCString contentType;
925 nsresult rv =
926 mHttpChannel->GetResponseHeader(contentTypeStr, contentType);
927 if (NS_SUCCEEDED(rv))
928 aVisitor->VisitHeader(contentTypeStr, contentType);
929 return NS_OK;
930 }
931
932 NS_IMETHODIMP
GetOriginalResponseHeader(const nsACString & aHeader,nsIHttpHeaderVisitor * aVisitor)933 nsViewSourceChannel::GetOriginalResponseHeader(const nsACString & aHeader,
934 nsIHttpHeaderVisitor *aVisitor)
935 {
936 nsAutoCString value;
937 nsresult rv = GetResponseHeader(aHeader, value);
938 if (NS_FAILED(rv)) {
939 return rv;
940 }
941 aVisitor->VisitHeader(aHeader, value);
942 return NS_OK;
943 }
944
945 NS_IMETHODIMP
VisitOriginalResponseHeaders(nsIHttpHeaderVisitor * aVisitor)946 nsViewSourceChannel::VisitOriginalResponseHeaders(nsIHttpHeaderVisitor *aVisitor)
947 {
948 return VisitResponseHeaders(aVisitor);
949 }
950
951 NS_IMETHODIMP
IsNoStoreResponse(bool * _retval)952 nsViewSourceChannel::IsNoStoreResponse(bool *_retval)
953 {
954 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
955 mHttpChannel->IsNoStoreResponse(_retval);
956 }
957
958 NS_IMETHODIMP
IsNoCacheResponse(bool * _retval)959 nsViewSourceChannel::IsNoCacheResponse(bool *_retval)
960 {
961 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
962 mHttpChannel->IsNoCacheResponse(_retval);
963 }
964
965 NS_IMETHODIMP
IsPrivateResponse(bool * _retval)966 nsViewSourceChannel::IsPrivateResponse(bool *_retval)
967 {
968 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
969 mHttpChannel->IsPrivateResponse(_retval);
970 }
971
972 NS_IMETHODIMP
RedirectTo(nsIURI * uri)973 nsViewSourceChannel::RedirectTo(nsIURI *uri)
974 {
975 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
976 mHttpChannel->RedirectTo(uri);
977 }
978
979 NS_IMETHODIMP
GetRequestContextID(nsID * _retval)980 nsViewSourceChannel::GetRequestContextID(nsID *_retval)
981 {
982 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
983 mHttpChannel->GetRequestContextID(_retval);
984 }
985
986 NS_IMETHODIMP
SetRequestContextID(const nsID rcid)987 nsViewSourceChannel::SetRequestContextID(const nsID rcid)
988 {
989 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
990 mHttpChannel->SetRequestContextID(rcid);
991 }
992
993 NS_IMETHODIMP
GetIsMainDocumentChannel(bool * aValue)994 nsViewSourceChannel::GetIsMainDocumentChannel(bool* aValue)
995 {
996 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
997 mHttpChannel->GetIsMainDocumentChannel(aValue);
998 }
999
1000 NS_IMETHODIMP
SetIsMainDocumentChannel(bool aValue)1001 nsViewSourceChannel::SetIsMainDocumentChannel(bool aValue)
1002 {
1003 return !mHttpChannel ? NS_ERROR_NULL_POINTER :
1004 mHttpChannel->SetIsMainDocumentChannel(aValue);
1005 }
1006
1007 // Have to manually forward since these are [notxpcom]
1008 void
SetCorsPreflightParameters(const nsTArray<nsCString> & aUnsafeHeaders)1009 nsViewSourceChannel::SetCorsPreflightParameters(const nsTArray<nsCString>& aUnsafeHeaders)
1010 {
1011 mHttpChannelInternal->SetCorsPreflightParameters(aUnsafeHeaders);
1012 }
1013
1014 mozilla::net::nsHttpChannel *
QueryHttpChannelImpl()1015 nsViewSourceChannel::QueryHttpChannelImpl()
1016 {
1017 return mHttpChannelInternal->QueryHttpChannelImpl();
1018 }
1019