nsViewSourceChannel.cpp (38582B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=4 sw=2 sts=2 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 "mozilla/NullPrincipal.h" 9 #include "nsContentSecurityManager.h" 10 #include "nsContentUtils.h" 11 #include "nsHttpChannel.h" 12 #include "nsIExternalProtocolHandler.h" 13 #include "nsIHttpHeaderVisitor.h" 14 #include "nsIIOService.h" 15 #include "nsIInputStreamChannel.h" 16 #include "nsIReferrerInfo.h" 17 #include "nsMimeTypes.h" 18 #include "nsNetUtil.h" 19 #include "nsServiceManagerUtils.h" 20 21 NS_IMPL_ADDREF(nsViewSourceChannel) 22 NS_IMPL_RELEASE(nsViewSourceChannel) 23 /* 24 This QI uses NS_INTERFACE_MAP_ENTRY_CONDITIONAL to check for 25 non-nullness of mHttpChannel, mCachingChannel, and mUploadChannel. 26 */ 27 NS_INTERFACE_MAP_BEGIN(nsViewSourceChannel) 28 NS_INTERFACE_MAP_ENTRY(nsIViewSourceChannel) 29 NS_INTERFACE_MAP_ENTRY(nsIStreamListener) 30 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver) 31 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) 32 NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink) 33 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIHttpChannel, mHttpChannel) 34 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIdentChannel, mHttpChannel) 35 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIHttpChannelInternal, 36 mHttpChannelInternal) 37 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICachingChannel, mCachingChannel) 38 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICacheInfoChannel, mCacheInfoChannel) 39 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIUploadChannel, mUploadChannel) 40 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIFormPOSTActionChannel, mPostChannel) 41 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIChildChannel, mChildChannel) 42 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIRequest, nsIViewSourceChannel) 43 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIChannel, nsIViewSourceChannel) 44 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIViewSourceChannel) 45 NS_INTERFACE_MAP_END 46 47 static nsresult WillUseExternalProtocolHandler(nsIIOService* aIOService, 48 const char* aScheme) { 49 nsCOMPtr<nsIProtocolHandler> handler; 50 nsresult rv = 51 aIOService->GetProtocolHandler(aScheme, getter_AddRefs(handler)); 52 if (NS_FAILED(rv)) { 53 return rv; 54 } 55 56 nsCOMPtr<nsIExternalProtocolHandler> externalHandler = 57 do_QueryInterface(handler); 58 // We should not allow view-source to open any external app. 59 if (externalHandler) { 60 NS_WARNING(nsPrintfCString("blocking view-source:%s:", aScheme).get()); 61 return NS_ERROR_MALFORMED_URI; 62 } 63 64 return NS_OK; 65 } 66 67 nsresult nsViewSourceChannel::Init(nsIURI* uri, nsILoadInfo* aLoadInfo) { 68 mOriginalURI = uri; 69 70 nsAutoCString path; 71 nsresult rv = uri->GetPathQueryRef(path); 72 if (NS_FAILED(rv)) return rv; 73 74 nsCOMPtr<nsIIOService> pService(do_GetIOService(&rv)); 75 if (NS_FAILED(rv)) return rv; 76 77 nsAutoCString scheme; 78 rv = pService->ExtractScheme(path, scheme); 79 if (NS_FAILED(rv)) return rv; 80 81 // prevent viewing source of javascript URIs (see bug 204779) 82 if (scheme.EqualsLiteral("javascript")) { 83 NS_WARNING("blocking view-source:javascript:"); 84 return NS_ERROR_INVALID_ARG; 85 } 86 87 rv = WillUseExternalProtocolHandler(pService, scheme.get()); 88 if (NS_FAILED(rv)) { 89 return rv; 90 } 91 92 nsCOMPtr<nsIURI> newChannelURI; 93 rv = pService->NewURI(path, nullptr, nullptr, getter_AddRefs(newChannelURI)); 94 NS_ENSURE_SUCCESS(rv, rv); 95 96 rv = pService->NewChannelFromURIWithLoadInfo(newChannelURI, aLoadInfo, 97 getter_AddRefs(mChannel)); 98 NS_ENSURE_SUCCESS(rv, rv); 99 100 mIsSrcdocChannel = false; 101 102 mChannel->SetOriginalURI(mOriginalURI); 103 UpdateChannelInterfaces(); 104 105 return NS_OK; 106 } 107 108 nsresult nsViewSourceChannel::InitSrcdoc(nsIURI* aURI, nsIURI* aBaseURI, 109 const nsAString& aSrcdoc, 110 nsILoadInfo* aLoadInfo) { 111 nsresult rv; 112 113 nsCOMPtr<nsIURI> inStreamURI; 114 // Need to strip view-source: from the URI. Hardcoded to 115 // about:srcdoc as this is the only permissible URI for srcdoc 116 // loads 117 rv = NS_NewURI(getter_AddRefs(inStreamURI), u"about:srcdoc"_ns); 118 NS_ENSURE_SUCCESS(rv, rv); 119 120 rv = NS_NewInputStreamChannelInternal(getter_AddRefs(mChannel), inStreamURI, 121 aSrcdoc, "text/html"_ns, aLoadInfo, 122 true); 123 124 NS_ENSURE_SUCCESS(rv, rv); 125 mOriginalURI = aURI; 126 mIsSrcdocChannel = true; 127 128 mChannel->SetOriginalURI(mOriginalURI); 129 UpdateChannelInterfaces(); 130 131 rv = UpdateLoadInfoResultPrincipalURI(); 132 NS_ENSURE_SUCCESS(rv, rv); 133 134 nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(mChannel); 135 MOZ_ASSERT(isc); 136 isc->SetBaseURI(aBaseURI); 137 return NS_OK; 138 } 139 140 void nsViewSourceChannel::UpdateChannelInterfaces() { 141 mHttpChannel = do_QueryInterface(mChannel); 142 mHttpChannelInternal = do_QueryInterface(mChannel); 143 mCachingChannel = do_QueryInterface(mChannel); 144 mCacheInfoChannel = do_QueryInterface(mChannel); 145 mUploadChannel = do_QueryInterface(mChannel); 146 mPostChannel = do_QueryInterface(mChannel); 147 mChildChannel = do_QueryInterface(mChannel); 148 } 149 150 void nsViewSourceChannel::ReleaseListeners() { 151 mListener = nullptr; 152 mCallbacks = nullptr; 153 } 154 155 nsresult nsViewSourceChannel::UpdateLoadInfoResultPrincipalURI() { 156 nsresult rv; 157 158 MOZ_ASSERT(mChannel); 159 160 nsCOMPtr<nsILoadInfo> channelLoadInfo = mChannel->LoadInfo(); 161 nsCOMPtr<nsIURI> channelResultPrincipalURI; 162 rv = channelLoadInfo->GetResultPrincipalURI( 163 getter_AddRefs(channelResultPrincipalURI)); 164 if (NS_FAILED(rv)) { 165 return rv; 166 } 167 168 if (!channelResultPrincipalURI) { 169 mChannel->GetOriginalURI(getter_AddRefs(channelResultPrincipalURI)); 170 return NS_OK; 171 } 172 173 if (!channelResultPrincipalURI) { 174 return NS_ERROR_UNEXPECTED; 175 } 176 177 if (channelResultPrincipalURI->SchemeIs("view-source")) { 178 // already view-source 179 return NS_OK; 180 } 181 182 nsCOMPtr<nsIURI> updatedResultPrincipalURI; 183 rv = BuildViewSourceURI(channelResultPrincipalURI, 184 getter_AddRefs(updatedResultPrincipalURI)); 185 if (NS_FAILED(rv)) { 186 return rv; 187 } 188 189 rv = channelLoadInfo->SetResultPrincipalURI(updatedResultPrincipalURI); 190 if (NS_FAILED(rv)) { 191 return rv; 192 } 193 194 return NS_OK; 195 } 196 197 nsresult nsViewSourceChannel::BuildViewSourceURI(nsIURI* aURI, 198 nsIURI** aResult) { 199 nsresult rv; 200 201 // protect ourselves against broken channel implementations 202 if (!aURI) { 203 NS_ERROR("no URI to build view-source uri!"); 204 return NS_ERROR_UNEXPECTED; 205 } 206 207 nsAutoCString spec; 208 rv = aURI->GetSpec(spec); 209 if (NS_FAILED(rv)) { 210 return rv; 211 } 212 213 return NS_NewURI(aResult, "view-source:"_ns + spec); 214 } 215 216 //////////////////////////////////////////////////////////////////////////////// 217 // nsIRequest methods: 218 219 NS_IMETHODIMP 220 nsViewSourceChannel::GetName(nsACString& result) { 221 nsCOMPtr<nsIURI> uri; 222 GetURI(getter_AddRefs(uri)); 223 if (uri) { 224 return uri->GetSpec(result); 225 } 226 return NS_ERROR_NOT_IMPLEMENTED; 227 } 228 229 NS_IMETHODIMP 230 nsViewSourceChannel::GetTransferSize(uint64_t* aTransferSize) { 231 return NS_ERROR_NOT_IMPLEMENTED; 232 } 233 234 NS_IMETHODIMP 235 nsViewSourceChannel::GetRequestSize(uint64_t* aRequestSize) { 236 return NS_ERROR_NOT_IMPLEMENTED; 237 } 238 239 NS_IMETHODIMP 240 nsViewSourceChannel::GetDecodedBodySize(uint64_t* aDecodedBodySize) { 241 return NS_ERROR_NOT_IMPLEMENTED; 242 } 243 244 NS_IMETHODIMP 245 nsViewSourceChannel::GetEncodedBodySize(uint64_t* aEncodedBodySize) { 246 return NS_ERROR_NOT_IMPLEMENTED; 247 } 248 249 NS_IMETHODIMP 250 nsViewSourceChannel::IsPending(bool* result) { 251 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 252 253 return mChannel->IsPending(result); 254 } 255 256 NS_IMETHODIMP 257 nsViewSourceChannel::GetStatus(nsresult* status) { 258 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 259 260 return mChannel->GetStatus(status); 261 } 262 263 NS_IMETHODIMP nsViewSourceChannel::SetCanceledReason( 264 const nsACString& aReason) { 265 return nsIViewSourceChannel::SetCanceledReasonImpl(aReason); 266 } 267 268 NS_IMETHODIMP nsViewSourceChannel::GetCanceledReason(nsACString& aReason) { 269 return nsIViewSourceChannel::GetCanceledReasonImpl(aReason); 270 } 271 272 NS_IMETHODIMP nsViewSourceChannel::CancelWithReason(nsresult aStatus, 273 const nsACString& aReason) { 274 return nsIViewSourceChannel::CancelWithReasonImpl(aStatus, aReason); 275 } 276 277 NS_IMETHODIMP 278 nsViewSourceChannel::Cancel(nsresult status) { 279 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 280 281 return mChannel->Cancel(status); 282 } 283 284 NS_IMETHODIMP 285 nsViewSourceChannel::GetCanceled(bool* aCanceled) { 286 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 287 288 return mChannel->GetCanceled(aCanceled); 289 } 290 291 NS_IMETHODIMP 292 nsViewSourceChannel::Suspend(void) { 293 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 294 295 return mChannel->Suspend(); 296 } 297 298 NS_IMETHODIMP 299 nsViewSourceChannel::Resume(void) { 300 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 301 302 return mChannel->Resume(); 303 } 304 305 //////////////////////////////////////////////////////////////////////////////// 306 // nsIChannel methods: 307 308 NS_IMETHODIMP 309 nsViewSourceChannel::GetOriginalURI(nsIURI** aURI) { 310 *aURI = do_AddRef(mOriginalURI).take(); 311 return NS_OK; 312 } 313 314 NS_IMETHODIMP 315 nsViewSourceChannel::SetOriginalURI(nsIURI* aURI) { 316 NS_ENSURE_ARG_POINTER(aURI); 317 mOriginalURI = aURI; 318 return NS_OK; 319 } 320 321 NS_IMETHODIMP 322 nsViewSourceChannel::GetURI(nsIURI** aURI) { 323 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 324 325 nsCOMPtr<nsIURI> uri; 326 nsresult rv = mChannel->GetURI(getter_AddRefs(uri)); 327 if (NS_FAILED(rv)) { 328 return rv; 329 } 330 331 return BuildViewSourceURI(uri, aURI); 332 } 333 334 NS_IMETHODIMP 335 nsViewSourceChannel::Open(nsIInputStream** aStream) { 336 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 337 return Open(aStream); 338 } 339 340 NS_IMETHODIMP 341 nsViewSourceChannel::AsyncOpen(nsIStreamListener* aListener) { 342 // We can't ensure GetInitialSecurityCheckDone here 343 344 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 345 346 mListener = aListener; 347 348 /* 349 * We want to add ourselves to the loadgroup before opening 350 * mChannel, since we want to make sure we're in the loadgroup 351 * when mChannel finishes and fires OnStopRequest() 352 */ 353 354 nsCOMPtr<nsILoadGroup> loadGroup; 355 mChannel->GetLoadGroup(getter_AddRefs(loadGroup)); 356 if (loadGroup) { 357 loadGroup->AddRequest(static_cast<nsIViewSourceChannel*>(this), nullptr); 358 } 359 360 nsresult rv = NS_OK; 361 rv = mChannel->AsyncOpen(this); 362 363 if (NS_FAILED(rv) && loadGroup) { 364 loadGroup->RemoveRequest(static_cast<nsIViewSourceChannel*>(this), nullptr, 365 rv); 366 } 367 368 if (NS_SUCCEEDED(rv)) { 369 // We do this here to make sure all notification callbacks changes have been 370 // made first before we inject this view-source channel. 371 mChannel->GetNotificationCallbacks(getter_AddRefs(mCallbacks)); 372 mChannel->SetNotificationCallbacks(this); 373 374 MOZ_ASSERT(mCallbacks != this, "We have a cycle"); 375 376 mOpened = true; 377 } 378 379 if (NS_FAILED(rv)) { 380 ReleaseListeners(); 381 } 382 383 return rv; 384 } 385 386 /* 387 * Both the view source channel and mChannel are added to the 388 * loadgroup. There should never be more than one request in the 389 * loadgroup that has LOAD_DOCUMENT_URI set. The one that has this 390 * flag set is the request whose URI is used to refetch the document, 391 * so it better be the viewsource channel. 392 * 393 * Therefore, we need to make sure that 394 * 1) The load flags on mChannel _never_ include LOAD_DOCUMENT_URI 395 * 2) The load flags on |this| include LOAD_DOCUMENT_URI when it was 396 * set via SetLoadFlags (mIsDocument keeps track of this flag). 397 */ 398 399 NS_IMETHODIMP 400 nsViewSourceChannel::GetLoadFlags(uint32_t* aLoadFlags) { 401 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 402 403 nsresult rv = mChannel->GetLoadFlags(aLoadFlags); 404 if (NS_FAILED(rv)) return rv; 405 406 // This should actually be just LOAD_DOCUMENT_URI but the win32 compiler 407 // fails to deal due to amiguous inheritance. nsIChannel::LOAD_DOCUMENT_URI 408 // also fails; the Win32 compiler thinks that's supposed to be a method. 409 if (mIsDocument) *aLoadFlags |= ::nsIChannel::LOAD_DOCUMENT_URI; 410 411 return rv; 412 } 413 414 NS_IMETHODIMP 415 nsViewSourceChannel::SetLoadFlags(uint32_t aLoadFlags) { 416 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 417 418 // "View source" always wants the currently cached content. 419 // We also want to have _this_ channel, not mChannel to be the 420 // 'document' channel in the loadgroup. 421 422 // These should actually be just LOAD_FROM_CACHE and LOAD_DOCUMENT_URI but 423 // the win32 compiler fails to deal due to amiguous inheritance. 424 // nsIChannel::LOAD_DOCUMENT_URI/nsIRequest::LOAD_FROM_CACHE also fails; the 425 // Win32 compiler thinks that's supposed to be a method. 426 mIsDocument = (aLoadFlags & ::nsIChannel::LOAD_DOCUMENT_URI) != 0; 427 428 nsresult rv = 429 mChannel->SetLoadFlags((aLoadFlags | ::nsIRequest::LOAD_FROM_CACHE) & 430 ~::nsIChannel::LOAD_DOCUMENT_URI); 431 if (NS_WARN_IF(NS_FAILED(rv))) { 432 return rv; 433 } 434 435 if (mHttpChannel) { 436 rv = mHttpChannel->SetIsMainDocumentChannel( 437 aLoadFlags & ::nsIChannel::LOAD_DOCUMENT_URI); 438 MOZ_ASSERT(NS_SUCCEEDED(rv)); 439 } 440 441 return NS_OK; 442 } 443 444 NS_IMETHODIMP 445 nsViewSourceChannel::GetTRRMode(nsIRequest::TRRMode* aTRRMode) { 446 return nsIViewSourceChannel::GetTRRModeImpl(aTRRMode); 447 } 448 449 NS_IMETHODIMP 450 nsViewSourceChannel::SetTRRMode(nsIRequest::TRRMode aTRRMode) { 451 return nsIViewSourceChannel::SetTRRModeImpl(aTRRMode); 452 } 453 454 NS_IMETHODIMP 455 nsViewSourceChannel::GetContentType(nsACString& aContentType) { 456 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 457 458 aContentType.Truncate(); 459 460 if (mContentType.IsEmpty()) { 461 // Get the current content type 462 nsresult rv; 463 nsAutoCString contentType; 464 rv = mChannel->GetContentType(contentType); 465 if (NS_FAILED(rv)) return rv; 466 467 // If we don't know our type, just say so. The unknown 468 // content decoder will then kick in automatically, and it 469 // will call our SetOriginalContentType method instead of our 470 // SetContentType method to set the type it determines. 471 if (!contentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE) && 472 !contentType.IsEmpty()) { 473 contentType = VIEWSOURCE_CONTENT_TYPE; 474 } 475 476 mContentType = contentType; 477 } 478 479 aContentType = mContentType; 480 return NS_OK; 481 } 482 483 NS_IMETHODIMP 484 nsViewSourceChannel::SetContentType(const nsACString& aContentType) { 485 // Our GetContentType() currently returns VIEWSOURCE_CONTENT_TYPE 486 // 487 // However, during the parsing phase the parser calls our 488 // channel's GetContentType(). Returning the string above trips up 489 // the parser. In order to avoid messy changes and not to have the 490 // parser depend on nsIViewSourceChannel Vidur proposed the 491 // following solution: 492 // 493 // The ViewSourceChannel initially returns a content type of 494 // VIEWSOURCE_CONTENT_TYPE. Based on this type decisions to 495 // create a viewer for doing a view source are made. After the 496 // viewer is created, nsLayoutDLF::CreateInstance() calls this 497 // SetContentType() with the original content type. When it's 498 // time for the parser to find out the content type it will call 499 // our channel's GetContentType() and it will get the original 500 // content type, such as, text/html and everything is kosher from 501 // then on. 502 503 if (!mOpened) { 504 // We do not take hints 505 return NS_ERROR_NOT_AVAILABLE; 506 } 507 508 mContentType = aContentType; 509 return NS_OK; 510 } 511 512 NS_IMETHODIMP 513 nsViewSourceChannel::GetContentCharset(nsACString& aContentCharset) { 514 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 515 516 return mChannel->GetContentCharset(aContentCharset); 517 } 518 519 NS_IMETHODIMP 520 nsViewSourceChannel::SetContentCharset(const nsACString& aContentCharset) { 521 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 522 523 return mChannel->SetContentCharset(aContentCharset); 524 } 525 526 // We don't forward these methods becacuse content-disposition isn't whitelisted 527 // (see GetResponseHeader/VisitResponseHeaders). 528 NS_IMETHODIMP 529 nsViewSourceChannel::GetContentDisposition(uint32_t* aContentDisposition) { 530 return NS_ERROR_NOT_AVAILABLE; 531 } 532 533 NS_IMETHODIMP 534 nsViewSourceChannel::SetContentDisposition(uint32_t aContentDisposition) { 535 return NS_ERROR_NOT_AVAILABLE; 536 } 537 538 NS_IMETHODIMP 539 nsViewSourceChannel::GetContentDispositionFilename( 540 nsAString& aContentDispositionFilename) { 541 return NS_ERROR_NOT_AVAILABLE; 542 } 543 544 NS_IMETHODIMP 545 nsViewSourceChannel::SetContentDispositionFilename( 546 const nsAString& aContentDispositionFilename) { 547 return NS_ERROR_NOT_AVAILABLE; 548 } 549 550 NS_IMETHODIMP 551 nsViewSourceChannel::GetContentDispositionHeader( 552 nsACString& aContentDispositionHeader) { 553 return NS_ERROR_NOT_AVAILABLE; 554 } 555 556 NS_IMETHODIMP 557 nsViewSourceChannel::GetContentLength(int64_t* aContentLength) { 558 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 559 560 return mChannel->GetContentLength(aContentLength); 561 } 562 563 NS_IMETHODIMP 564 nsViewSourceChannel::SetContentLength(int64_t aContentLength) { 565 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 566 567 return mChannel->SetContentLength(aContentLength); 568 } 569 570 NS_IMETHODIMP 571 nsViewSourceChannel::GetLoadGroup(nsILoadGroup** aLoadGroup) { 572 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 573 574 return mChannel->GetLoadGroup(aLoadGroup); 575 } 576 577 NS_IMETHODIMP 578 nsViewSourceChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) { 579 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 580 581 return mChannel->SetLoadGroup(aLoadGroup); 582 } 583 584 NS_IMETHODIMP 585 nsViewSourceChannel::GetOwner(nsISupports** aOwner) { 586 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 587 588 return mChannel->GetOwner(aOwner); 589 } 590 591 NS_IMETHODIMP 592 nsViewSourceChannel::SetOwner(nsISupports* aOwner) { 593 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 594 595 return mChannel->SetOwner(aOwner); 596 } 597 598 NS_IMETHODIMP 599 nsViewSourceChannel::GetLoadInfo(nsILoadInfo** aLoadInfo) { 600 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 601 602 return mChannel->GetLoadInfo(aLoadInfo); 603 } 604 605 NS_IMETHODIMP 606 nsViewSourceChannel::SetLoadInfo(nsILoadInfo* aLoadInfo) { 607 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 608 MOZ_RELEASE_ASSERT(aLoadInfo, "loadinfo can't be null"); 609 return mChannel->SetLoadInfo(aLoadInfo); 610 } 611 612 NS_IMETHODIMP 613 nsViewSourceChannel::GetIsDocument(bool* aIsDocument) { 614 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 615 616 return mChannel->GetIsDocument(aIsDocument); 617 } 618 619 NS_IMETHODIMP 620 nsViewSourceChannel::GetNotificationCallbacks( 621 nsIInterfaceRequestor** aNotificationCallbacks) { 622 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 623 624 return mChannel->GetNotificationCallbacks(aNotificationCallbacks); 625 } 626 627 NS_IMETHODIMP 628 nsViewSourceChannel::SetNotificationCallbacks( 629 nsIInterfaceRequestor* aNotificationCallbacks) { 630 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 631 632 return mChannel->SetNotificationCallbacks(aNotificationCallbacks); 633 } 634 635 NS_IMETHODIMP 636 nsViewSourceChannel::GetSecurityInfo(nsITransportSecurityInfo** aSecurityInfo) { 637 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 638 639 return mChannel->GetSecurityInfo(aSecurityInfo); 640 } 641 642 // nsIViewSourceChannel methods 643 NS_IMETHODIMP 644 nsViewSourceChannel::GetOriginalContentType(nsACString& aContentType) { 645 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 646 647 return mChannel->GetContentType(aContentType); 648 } 649 650 NS_IMETHODIMP 651 nsViewSourceChannel::SetOriginalContentType(const nsACString& aContentType) { 652 NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 653 654 // clear our cached content-type value 655 mContentType.Truncate(); 656 657 return mChannel->SetContentType(aContentType); 658 } 659 660 NS_IMETHODIMP 661 nsViewSourceChannel::GetIsSrcdocChannel(bool* aIsSrcdocChannel) { 662 *aIsSrcdocChannel = mIsSrcdocChannel; 663 return NS_OK; 664 } 665 666 NS_IMETHODIMP 667 nsViewSourceChannel::GetBaseURI(nsIURI** aBaseURI) { 668 if (mIsSrcdocChannel) { 669 nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(mChannel); 670 if (isc) { 671 return isc->GetBaseURI(aBaseURI); 672 } 673 } 674 *aBaseURI = do_AddRef(mBaseURI).take(); 675 return NS_OK; 676 } 677 678 NS_IMETHODIMP 679 nsViewSourceChannel::SetBaseURI(nsIURI* aBaseURI) { 680 mBaseURI = aBaseURI; 681 return NS_OK; 682 } 683 684 nsIChannel* nsViewSourceChannel::GetInnerChannel() { return mChannel; } 685 686 NS_IMETHODIMP 687 nsViewSourceChannel::GetProtocolVersion(nsACString& aProtocolVersion) { 688 return NS_ERROR_NOT_IMPLEMENTED; 689 } 690 691 // nsIRequestObserver methods 692 NS_IMETHODIMP 693 nsViewSourceChannel::OnStartRequest(nsIRequest* aRequest) { 694 NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE); 695 // The channel may have gotten redirected... Time to update our info 696 mChannel = do_QueryInterface(aRequest); 697 UpdateChannelInterfaces(); 698 699 nsresult rv = UpdateLoadInfoResultPrincipalURI(); 700 if (NS_FAILED(rv)) { 701 Cancel(rv); 702 } 703 704 return mListener->OnStartRequest(static_cast<nsIViewSourceChannel*>(this)); 705 } 706 707 NS_IMETHODIMP 708 nsViewSourceChannel::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) { 709 NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE); 710 if (mChannel) { 711 nsCOMPtr<nsILoadGroup> loadGroup; 712 mChannel->GetLoadGroup(getter_AddRefs(loadGroup)); 713 if (loadGroup) { 714 loadGroup->RemoveRequest(static_cast<nsIViewSourceChannel*>(this), 715 nullptr, aStatus); 716 } 717 } 718 719 nsresult rv = mListener->OnStopRequest( 720 static_cast<nsIViewSourceChannel*>(this), aStatus); 721 722 ReleaseListeners(); 723 724 return rv; 725 } 726 727 // nsIStreamListener methods 728 NS_IMETHODIMP 729 nsViewSourceChannel::OnDataAvailable(nsIRequest* aRequest, 730 nsIInputStream* aInputStream, 731 uint64_t aSourceOffset, uint32_t aLength) { 732 NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE); 733 return mListener->OnDataAvailable(static_cast<nsIViewSourceChannel*>(this), 734 aInputStream, aSourceOffset, aLength); 735 } 736 737 // nsIHttpChannel methods 738 739 // We want to forward most of nsIHttpChannel over to mHttpChannel, but we want 740 // to override GetRequestHeader and VisitHeaders. The reason is that we don't 741 // want various headers like Link: and Refresh: applying to view-source. 742 NS_IMETHODIMP 743 nsViewSourceChannel::GetChannelId(uint64_t* aChannelId) { 744 NS_ENSURE_ARG_POINTER(aChannelId); 745 return !mHttpChannel ? NS_ERROR_NULL_POINTER 746 : mHttpChannel->GetChannelId(aChannelId); 747 } 748 749 NS_IMETHODIMP 750 nsViewSourceChannel::SetChannelId(uint64_t aChannelId) { 751 return !mHttpChannel ? NS_ERROR_NULL_POINTER 752 : mHttpChannel->SetChannelId(aChannelId); 753 } 754 755 NS_IMETHODIMP 756 nsViewSourceChannel::GetTopLevelContentWindowId(uint64_t* aWindowId) { 757 return !mHttpChannel ? NS_ERROR_NULL_POINTER 758 : mHttpChannel->GetTopLevelContentWindowId(aWindowId); 759 } 760 761 NS_IMETHODIMP 762 nsViewSourceChannel::SetTopLevelContentWindowId(uint64_t aWindowId) { 763 return !mHttpChannel ? NS_ERROR_NULL_POINTER 764 : mHttpChannel->SetTopLevelContentWindowId(aWindowId); 765 } 766 767 NS_IMETHODIMP 768 nsViewSourceChannel::GetBrowserId(uint64_t* aId) { 769 return !mHttpChannel ? NS_ERROR_NULL_POINTER 770 : mHttpChannel->GetBrowserId(aId); 771 } 772 773 NS_IMETHODIMP 774 nsViewSourceChannel::SetBrowserId(uint64_t aId) { 775 return !mHttpChannel ? NS_ERROR_NULL_POINTER 776 : mHttpChannel->SetBrowserId(aId); 777 } 778 779 NS_IMETHODIMP 780 nsViewSourceChannel::GetRequestMethod(nsACString& aRequestMethod) { 781 return !mHttpChannel ? NS_ERROR_NULL_POINTER 782 : mHttpChannel->GetRequestMethod(aRequestMethod); 783 } 784 785 NS_IMETHODIMP 786 nsViewSourceChannel::SetRequestMethod(const nsACString& aRequestMethod) { 787 return !mHttpChannel ? NS_ERROR_NULL_POINTER 788 : mHttpChannel->SetRequestMethod(aRequestMethod); 789 } 790 791 NS_IMETHODIMP 792 nsViewSourceChannel::GetReferrerInfo(nsIReferrerInfo** aReferrerInfo) { 793 return !mHttpChannel ? NS_ERROR_NULL_POINTER 794 : mHttpChannel->GetReferrerInfo(aReferrerInfo); 795 } 796 797 NS_IMETHODIMP 798 nsViewSourceChannel::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) { 799 return !mHttpChannel ? NS_ERROR_NULL_POINTER 800 : mHttpChannel->SetReferrerInfo(aReferrerInfo); 801 } 802 803 NS_IMETHODIMP nsViewSourceChannel::SetReferrerInfoWithoutClone( 804 nsIReferrerInfo* aReferrerInfo) { 805 return !mHttpChannel 806 ? NS_ERROR_NULL_POINTER 807 : mHttpChannel->SetReferrerInfoWithoutClone(aReferrerInfo); 808 } 809 810 NS_IMETHODIMP 811 nsViewSourceChannel::GetRequestHeader(const nsACString& aHeader, 812 nsACString& aValue) { 813 aValue.Truncate(); 814 return !mHttpChannel ? NS_ERROR_NULL_POINTER 815 : mHttpChannel->GetRequestHeader(aHeader, aValue); 816 } 817 818 NS_IMETHODIMP 819 nsViewSourceChannel::SetRequestHeader(const nsACString& aHeader, 820 const nsACString& aValue, bool aMerge) { 821 return !mHttpChannel 822 ? NS_ERROR_NULL_POINTER 823 : mHttpChannel->SetRequestHeader(aHeader, aValue, aMerge); 824 } 825 826 NS_IMETHODIMP 827 nsViewSourceChannel::SetNewReferrerInfo( 828 const nsACString& aUrl, nsIReferrerInfo::ReferrerPolicyIDL aPolicy, 829 bool aSendReferrer) { 830 return !mHttpChannel 831 ? NS_ERROR_NULL_POINTER 832 : mHttpChannel->SetNewReferrerInfo(aUrl, aPolicy, aSendReferrer); 833 } 834 835 NS_IMETHODIMP 836 nsViewSourceChannel::SetEmptyRequestHeader(const nsACString& aHeader) { 837 return !mHttpChannel ? NS_ERROR_NULL_POINTER 838 : mHttpChannel->SetEmptyRequestHeader(aHeader); 839 } 840 841 NS_IMETHODIMP 842 nsViewSourceChannel::VisitRequestHeaders(nsIHttpHeaderVisitor* aVisitor) { 843 return !mHttpChannel ? NS_ERROR_NULL_POINTER 844 : mHttpChannel->VisitRequestHeaders(aVisitor); 845 } 846 847 NS_IMETHODIMP 848 nsViewSourceChannel::VisitNonDefaultRequestHeaders( 849 nsIHttpHeaderVisitor* aVisitor) { 850 return !mHttpChannel ? NS_ERROR_NULL_POINTER 851 : mHttpChannel->VisitNonDefaultRequestHeaders(aVisitor); 852 } 853 854 NS_IMETHODIMP 855 nsViewSourceChannel::ShouldStripRequestBodyHeader(const nsACString& aMethod, 856 bool* aResult) { 857 return !mHttpChannel 858 ? NS_ERROR_NULL_POINTER 859 : mHttpChannel->ShouldStripRequestBodyHeader(aMethod, aResult); 860 } 861 862 NS_IMETHODIMP 863 nsViewSourceChannel::GetAllowSTS(bool* aAllowSTS) { 864 return !mHttpChannel ? NS_ERROR_NULL_POINTER 865 : mHttpChannel->GetAllowSTS(aAllowSTS); 866 } 867 868 NS_IMETHODIMP 869 nsViewSourceChannel::SetAllowSTS(bool aAllowSTS) { 870 return !mHttpChannel ? NS_ERROR_NULL_POINTER 871 : mHttpChannel->SetAllowSTS(aAllowSTS); 872 } 873 874 NS_IMETHODIMP 875 nsViewSourceChannel::GetRedirectionLimit(uint32_t* aRedirectionLimit) { 876 return !mHttpChannel ? NS_ERROR_NULL_POINTER 877 : mHttpChannel->GetRedirectionLimit(aRedirectionLimit); 878 } 879 880 NS_IMETHODIMP 881 nsViewSourceChannel::SetRedirectionLimit(uint32_t aRedirectionLimit) { 882 return !mHttpChannel ? NS_ERROR_NULL_POINTER 883 : mHttpChannel->SetRedirectionLimit(aRedirectionLimit); 884 } 885 886 NS_IMETHODIMP 887 nsViewSourceChannel::GetResponseStatus(uint32_t* aResponseStatus) { 888 return !mHttpChannel ? NS_ERROR_NULL_POINTER 889 : mHttpChannel->GetResponseStatus(aResponseStatus); 890 } 891 892 NS_IMETHODIMP 893 nsViewSourceChannel::GetResponseStatusText(nsACString& aResponseStatusText) { 894 return !mHttpChannel 895 ? NS_ERROR_NULL_POINTER 896 : mHttpChannel->GetResponseStatusText(aResponseStatusText); 897 } 898 899 NS_IMETHODIMP 900 nsViewSourceChannel::GetRequestSucceeded(bool* aRequestSucceeded) { 901 return !mHttpChannel ? NS_ERROR_NULL_POINTER 902 : mHttpChannel->GetRequestSucceeded(aRequestSucceeded); 903 } 904 905 NS_IMETHODIMP 906 nsViewSourceChannel::GetResponseHeader(const nsACString& aHeader, 907 nsACString& aValue) { 908 aValue.Truncate(); 909 if (!mHttpChannel) return NS_ERROR_NULL_POINTER; 910 911 if (!aHeader.Equals("Content-Type"_ns, nsCaseInsensitiveCStringComparator) && 912 !aHeader.Equals("Content-Security-Policy"_ns, 913 nsCaseInsensitiveCStringComparator) && 914 !aHeader.Equals("Content-Security-Policy-Report-Only"_ns, 915 nsCaseInsensitiveCStringComparator) && 916 !aHeader.Equals("X-Frame-Options"_ns, 917 nsCaseInsensitiveCStringComparator)) { 918 // We simulate the NS_ERROR_NOT_AVAILABLE error which is produced by 919 // GetResponseHeader via nsHttpHeaderArray::GetHeader when the entry is 920 // not present, such that it appears as though no headers except for the 921 // whitelisted ones were set on this channel. 922 return NS_ERROR_NOT_AVAILABLE; 923 } 924 925 return mHttpChannel->GetResponseHeader(aHeader, aValue); 926 } 927 928 NS_IMETHODIMP 929 nsViewSourceChannel::SetResponseHeader(const nsACString& header, 930 const nsACString& value, bool merge) { 931 return !mHttpChannel ? NS_ERROR_NULL_POINTER 932 : mHttpChannel->SetResponseHeader(header, value, merge); 933 } 934 935 NS_IMETHODIMP 936 nsViewSourceChannel::VisitResponseHeaders(nsIHttpHeaderVisitor* aVisitor) { 937 if (!mHttpChannel) return NS_ERROR_NULL_POINTER; 938 939 constexpr auto contentTypeStr = "Content-Type"_ns; 940 nsAutoCString contentType; 941 nsresult rv = mHttpChannel->GetResponseHeader(contentTypeStr, contentType); 942 if (NS_SUCCEEDED(rv)) { 943 return aVisitor->VisitHeader(contentTypeStr, contentType); 944 } 945 return NS_OK; 946 } 947 948 NS_IMETHODIMP 949 nsViewSourceChannel::GetOriginalResponseHeader(const nsACString& aHeader, 950 nsIHttpHeaderVisitor* aVisitor) { 951 nsAutoCString value; 952 nsresult rv = GetResponseHeader(aHeader, value); 953 if (NS_FAILED(rv)) { 954 return rv; 955 } 956 return aVisitor->VisitHeader(aHeader, value); 957 } 958 959 NS_IMETHODIMP 960 nsViewSourceChannel::VisitOriginalResponseHeaders( 961 nsIHttpHeaderVisitor* aVisitor) { 962 return VisitResponseHeaders(aVisitor); 963 } 964 965 NS_IMETHODIMP 966 nsViewSourceChannel::IsNoStoreResponse(bool* _retval) { 967 return !mHttpChannel ? NS_ERROR_NULL_POINTER 968 : mHttpChannel->IsNoStoreResponse(_retval); 969 } 970 971 NS_IMETHODIMP 972 nsViewSourceChannel::IsNoCacheResponse(bool* _retval) { 973 return !mHttpChannel ? NS_ERROR_NULL_POINTER 974 : mHttpChannel->IsNoCacheResponse(_retval); 975 } 976 977 NS_IMETHODIMP 978 nsViewSourceChannel::RedirectTo(nsIURI* uri) { 979 return !mHttpChannel ? NS_ERROR_NULL_POINTER : mHttpChannel->RedirectTo(uri); 980 } 981 982 NS_IMETHODIMP 983 nsViewSourceChannel::UpgradeToSecure() { 984 return !mHttpChannel ? NS_ERROR_NULL_POINTER 985 : mHttpChannel->UpgradeToSecure(); 986 } 987 988 NS_IMETHODIMP 989 nsViewSourceChannel::GetRequestObserversCalled(bool* aCalled) { 990 return !mHttpChannel ? NS_ERROR_NULL_POINTER 991 : mHttpChannel->GetRequestObserversCalled(aCalled); 992 } 993 994 NS_IMETHODIMP 995 nsViewSourceChannel::SetRequestObserversCalled(bool aCalled) { 996 return !mHttpChannel ? NS_ERROR_NULL_POINTER 997 : mHttpChannel->SetRequestObserversCalled(aCalled); 998 } 999 1000 NS_IMETHODIMP 1001 nsViewSourceChannel::GetRequestContextID(uint64_t* _retval) { 1002 return !mHttpChannel ? NS_ERROR_NULL_POINTER 1003 : mHttpChannel->GetRequestContextID(_retval); 1004 } 1005 1006 NS_IMETHODIMP 1007 nsViewSourceChannel::SetRequestContextID(uint64_t rcid) { 1008 return !mHttpChannel ? NS_ERROR_NULL_POINTER 1009 : mHttpChannel->SetRequestContextID(rcid); 1010 } 1011 1012 NS_IMETHODIMP 1013 nsViewSourceChannel::GetIsUserAgentHeaderOutdated(bool* aValue) { 1014 return !mHttpChannel ? NS_ERROR_NULL_POINTER 1015 : mHttpChannel->GetIsUserAgentHeaderOutdated(aValue); 1016 } 1017 1018 NS_IMETHODIMP 1019 nsViewSourceChannel::SetIsUserAgentHeaderOutdated(bool aValue) { 1020 return !mHttpChannel ? NS_ERROR_NULL_POINTER 1021 : mHttpChannel->SetIsUserAgentHeaderOutdated(aValue); 1022 } 1023 1024 NS_IMETHODIMP 1025 nsViewSourceChannel::GetIsMainDocumentChannel(bool* aValue) { 1026 return !mHttpChannel ? NS_ERROR_NULL_POINTER 1027 : mHttpChannel->GetIsMainDocumentChannel(aValue); 1028 } 1029 1030 NS_IMETHODIMP 1031 nsViewSourceChannel::SetIsMainDocumentChannel(bool aValue) { 1032 return !mHttpChannel ? NS_ERROR_NULL_POINTER 1033 : mHttpChannel->SetIsMainDocumentChannel(aValue); 1034 } 1035 1036 NS_IMETHODIMP nsViewSourceChannel::SetClassicScriptHintCharset( 1037 const nsAString& aClassicScriptHintCharset) { 1038 return !mHttpChannel ? NS_ERROR_NULL_POINTER 1039 : mHttpChannel->SetClassicScriptHintCharset( 1040 aClassicScriptHintCharset); 1041 } 1042 1043 NS_IMETHODIMP nsViewSourceChannel::GetClassicScriptHintCharset( 1044 nsAString& aClassicScriptHintCharset) { 1045 return !mHttpChannel ? NS_ERROR_NULL_POINTER 1046 : mHttpChannel->GetClassicScriptHintCharset( 1047 aClassicScriptHintCharset); 1048 } 1049 1050 NS_IMETHODIMP nsViewSourceChannel::SetDocumentCharacterSet( 1051 const nsAString& aDocumentCharacterSet) { 1052 return !mHttpChannel 1053 ? NS_ERROR_NULL_POINTER 1054 : mHttpChannel->SetDocumentCharacterSet(aDocumentCharacterSet); 1055 } 1056 1057 NS_IMETHODIMP nsViewSourceChannel::GetDocumentCharacterSet( 1058 nsAString& aDocumentCharacterSet) { 1059 return !mHttpChannel 1060 ? NS_ERROR_NULL_POINTER 1061 : mHttpChannel->GetDocumentCharacterSet(aDocumentCharacterSet); 1062 } 1063 // Have to manually forward SetCorsPreflightParameters since it's [notxpcom] 1064 void nsViewSourceChannel::SetCorsPreflightParameters( 1065 const nsTArray<nsCString>& aUnsafeHeaders, 1066 bool aShouldStripRequestBodyHeader, bool aShouldStripAuthHeader) { 1067 mHttpChannelInternal->SetCorsPreflightParameters( 1068 aUnsafeHeaders, aShouldStripRequestBodyHeader, aShouldStripAuthHeader); 1069 } 1070 1071 void nsViewSourceChannel::SetAltDataForChild(bool aIsForChild) { 1072 mHttpChannelInternal->SetAltDataForChild(aIsForChild); 1073 } 1074 1075 void nsViewSourceChannel::DisableAltDataCache() { 1076 mHttpChannelInternal->DisableAltDataCache(); 1077 } 1078 1079 NS_IMETHODIMP 1080 nsViewSourceChannel::LogBlockedCORSRequest(const nsAString& aMessage, 1081 const nsACString& aCategory, 1082 bool aIsWarning) { 1083 if (!mHttpChannel) { 1084 NS_WARNING( 1085 "nsViewSourceChannel::LogBlockedCORSRequest mHttpChannel is null"); 1086 return NS_ERROR_UNEXPECTED; 1087 } 1088 return mHttpChannel->LogBlockedCORSRequest(aMessage, aCategory, aIsWarning); 1089 } 1090 1091 NS_IMETHODIMP 1092 nsViewSourceChannel::LogMimeTypeMismatch(const nsACString& aMessageName, 1093 bool aWarning, const nsAString& aURL, 1094 const nsAString& aContentType) { 1095 if (!mHttpChannel) { 1096 NS_WARNING("nsViewSourceChannel::LogMimeTypeMismatch mHttpChannel is null"); 1097 return NS_ERROR_UNEXPECTED; 1098 } 1099 return mHttpChannel->LogMimeTypeMismatch(aMessageName, aWarning, aURL, 1100 aContentType); 1101 } 1102 1103 // FIXME: Should this forward to mHttpChannel? This was previously handled by a 1104 // default empty implementation. 1105 void nsViewSourceChannel::SetSource( 1106 mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aSource) {} 1107 1108 const nsTArray<mozilla::net::PreferredAlternativeDataTypeParams>& 1109 nsViewSourceChannel::PreferredAlternativeDataTypes() { 1110 if (mCacheInfoChannel) { 1111 return mCacheInfoChannel->PreferredAlternativeDataTypes(); 1112 } 1113 return mEmptyArray; 1114 } 1115 1116 void nsViewSourceChannel::DoDiagnosticAssertWhenOnStopNotCalledOnDestroy() { 1117 if (mHttpChannelInternal) { 1118 mHttpChannelInternal->DoDiagnosticAssertWhenOnStopNotCalledOnDestroy(); 1119 } 1120 } 1121 1122 // FIXME: Should this forward to mHttpChannelInternal? This was previously 1123 // handled by a default empty implementation. 1124 void nsViewSourceChannel::SetConnectionInfo( 1125 mozilla::net::nsHttpConnectionInfo* aInfo) {} 1126 1127 // nsIChildChannel methods 1128 1129 NS_IMETHODIMP 1130 nsViewSourceChannel::ConnectParent(uint32_t aRegistarId) { 1131 NS_ENSURE_TRUE(mChildChannel, NS_ERROR_NULL_POINTER); 1132 1133 return mChildChannel->ConnectParent(aRegistarId); 1134 } 1135 1136 NS_IMETHODIMP 1137 nsViewSourceChannel::CompleteRedirectSetup(nsIStreamListener* aListener) { 1138 NS_ENSURE_TRUE(mChildChannel, NS_ERROR_NULL_POINTER); 1139 1140 mListener = aListener; 1141 1142 /* 1143 * We want to add ourselves to the loadgroup before opening 1144 * mChannel, since we want to make sure we're in the loadgroup 1145 * when mChannel finishes and fires OnStopRequest() 1146 */ 1147 1148 nsCOMPtr<nsILoadGroup> loadGroup; 1149 mChannel->GetLoadGroup(getter_AddRefs(loadGroup)); 1150 if (loadGroup) { 1151 loadGroup->AddRequest(static_cast<nsIViewSourceChannel*>(this), nullptr); 1152 } 1153 1154 nsresult rv = NS_OK; 1155 rv = mChildChannel->CompleteRedirectSetup(this); 1156 1157 if (NS_FAILED(rv) && loadGroup) { 1158 loadGroup->RemoveRequest(static_cast<nsIViewSourceChannel*>(this), nullptr, 1159 rv); 1160 } 1161 1162 if (NS_SUCCEEDED(rv)) { 1163 mOpened = true; 1164 } 1165 1166 return rv; 1167 } 1168 1169 // nsIChannelEventSink 1170 1171 NS_IMETHODIMP 1172 nsViewSourceChannel::AsyncOnChannelRedirect( 1173 nsIChannel* oldChannel, nsIChannel* newChannel, uint32_t flags, 1174 nsIAsyncVerifyRedirectCallback* callback) { 1175 nsresult rv; 1176 1177 // We want consumers of the new inner channel be able to recognize it's 1178 // actually used for view-source. Hence we modify its original URI here. 1179 // This will not affect security checks because those have already been 1180 // synchronously done before our event sink is called. Note that result 1181 // principal URI is still modified at the OnStartRequest notification. 1182 nsCOMPtr<nsIURI> newChannelOrigURI; 1183 rv = newChannel->GetOriginalURI(getter_AddRefs(newChannelOrigURI)); 1184 NS_ENSURE_SUCCESS(rv, rv); 1185 1186 nsAutoCString scheme; 1187 rv = newChannelOrigURI->GetScheme(scheme); 1188 if (NS_FAILED(rv)) { 1189 return rv; 1190 } 1191 1192 nsCOMPtr<nsIIOService> ioService(do_GetIOService(&rv)); 1193 if (NS_FAILED(rv)) { 1194 return rv; 1195 } 1196 1197 rv = WillUseExternalProtocolHandler(ioService, scheme.get()); 1198 if (NS_FAILED(rv)) { 1199 return rv; 1200 } 1201 1202 nsCOMPtr<nsIURI> newChannelUpdatedOrigURI; 1203 rv = BuildViewSourceURI(newChannelOrigURI, 1204 getter_AddRefs(newChannelUpdatedOrigURI)); 1205 NS_ENSURE_SUCCESS(rv, rv); 1206 1207 rv = newChannel->SetOriginalURI(newChannelUpdatedOrigURI); 1208 NS_ENSURE_SUCCESS(rv, rv); 1209 1210 nsCOMPtr<nsIChannelEventSink> sink(do_QueryInterface(mCallbacks)); 1211 if (sink) { 1212 return sink->AsyncOnChannelRedirect(oldChannel, newChannel, flags, 1213 callback); 1214 } 1215 1216 callback->OnRedirectVerifyCallback(NS_OK); 1217 return NS_OK; 1218 } 1219 1220 NS_IMETHODIMP 1221 nsViewSourceChannel::GetDecompressDictionary( 1222 mozilla::net::DictionaryCacheEntry** aDictionary) { 1223 *aDictionary = nullptr; 1224 return NS_OK; 1225 } 1226 1227 NS_IMETHODIMP 1228 nsViewSourceChannel::SetDecompressDictionary( 1229 mozilla::net::DictionaryCacheEntry* aDictionary) { 1230 return NS_OK; 1231 } 1232 1233 // nsIInterfaceRequestor 1234 1235 NS_IMETHODIMP 1236 nsViewSourceChannel::GetInterface(const nsIID& aIID, void** aResult) { 1237 if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) { 1238 nsCOMPtr<nsIChannelEventSink> self(this); 1239 self.forget(aResult); 1240 return NS_OK; 1241 } 1242 1243 if (mCallbacks) { 1244 return mCallbacks->GetInterface(aIID, aResult); 1245 } 1246 1247 return NS_ERROR_NO_INTERFACE; 1248 }