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