Files
palemoon27/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
T
roytam1 54259209d7 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 891551 - Part 7: Fix some intermittent failures in multi_tcp_socket_unittest. r=ekr (b0fb5f6167)
- Bug 891551 - Part 11: fix a couple of issues from part 5. r=bwc (1f3586e037)
- Bug 1131779: 403 on permission request no longer invalidates the whole TURN relay. r=bwc (d0c594e2c7)
- Bug 797262 - IPV6 support for webrtc. r=drno (91894f480c)
- Bug 1187775 - Plumb RTCConfiguration.iceTransportPolicy down to NrIceCtx. r=smaug, r=bwc (1edc8f89c7)
- Bug 1191258 - check for IFF_RUNNING to detect online interfaces. r=mcmanus (3882c4d36e)
- Bug 1191253 - start the link monitor, ignore link-local notifications. r=mcmanus (f26b864061)
- Bug 1203658 - mark Linux's nsNotifyAddrListener::mChildThreadShutdown member as Atomic; r=bagder (6459a89dc0)
- re-enable warnings (e132d2f5db)
- Bug 1205266 - log network-change events on Mac. r=mcmanus (4c50d25945)
- Bug 1163419 - Make nsQtNetworkLinkService destructor private. r=dougt (c6993deef9)
- Bug 1178091: Implement RTCDataChannel BufferedAmountLowThreshold and bufferedamountlow event r=smaug,drno (0536f587b4)
- Bug 1194817: disable PMTUD in DataChannels/SCTP, set initial MTU per spec r=tuexen (60db372861)
- Bug 1198730: fix simple bug in PMTUD disable that clears all other flags r=tuexen (aeac9858cf)
- Bug 1148231: fix wrong error message on DataChannel failed resend of packet r=khuey (c1d9d11e17)
- Bug 1152334 - StartWebsocketData null deref mSocketIn, r=bagder (e55850770e)
- Bug 1149872 - Add the missing format specifiers. r=jduell (ffef5c91c2)
- Bug 1182515 - WebSocketChannel leaked when WebSocketChannel::AsyncOpen fails, r=mcmanus (0b52e2eb82)
- Bug 1140765 - Build some network code in unified mode; r=mcmanus (a6b9c325bb)
- Bug 1147749 - View source should go through service worker interception, r=bz, r=jduell (8c5a3cab90)
- Bug 1137151: Marked destructors of ref-counted RTSP classes as protected, r=sworkman (a6873944ee)
- Bug 1117486 - [FFOS2.0][Woodduck] System crash by replaying the same RTSP clip several times. r=bechen (1401ee0f11)
- Bug 1133461 - [RTSP] Remove the extra PLAY request for seek operation. r=bechen (c603b06ac6)
- Bug 1138983 - RTSP not enabled in Lollipop. r=vchang (a42d0bcd30)
- Bug 1144513 - [gonk-lmr1] Adapt RTSPSource.cpp. r=ettseng (8e011ab7bf)
- Bug 1151760 - Separate timeout timer with end of stream. r=ettseng (60bb18556c)
- Bug 1208756 - Hoist shared CheckMayLoad logic into BasePrincipal. r=bz (0108fa0c7c)
- Bug 1208756 - Introduce URI_FETCHABLE_BY_ANYONE and use it for moz-extension. r=bz (04de31fcbd)
- Bug 1188421 - Properly null memory reporter's compressor reference. r=hurley (9275695d87)
- bug 1204614 - test for h2 per stream flow control r=hurley (a56d4aacff)
- Bug 1197847 - Disallow folded headers in h2. r=mcmanus (ec5febf843)
- Bug 1136361 - update node-http2 on ci. rs=mcmanus (a7e2de9e02)
- Bug 1197847 - make debugging h2 and spdy test servers easier. r=mcmanus (7dcc251b63)
- Missing bits of 1132357 (431f194ed7)
- Bug 1207519 - Prevent HashTable shrink from ignoring allocation failures that may have been reported r=Waldo (d9270ce946)
- Bug 920479 - Properly convert all arguments to the Function constructor to strings before parsing out an arguments list for the function to be created. r=arai (2ba9fb0af0)
- Bug 1206520: Create an option to throw on asm.js validation failures; r=luke (6a19a37db7)
- Bug 1210295 - Simplify TOK_DEFAULT case in Parser::exportDeclaration. r=Waldo (850e383381)
- code style (5356d4a123)
- Bug 589199 - Mark non-global lexical scopes are non-extensible. (r=efaust) (d0430a0f5e)
- Bug 589199 - Cleanup: remove unused DEPTH_SLOT from BlockObject. (r=efaust) (97206b2b00)
- Bug 1211100 - Add Vector::infallibleEmplaceBack and use it in JSScript::initScriptCounts() r=nbp (09705ff8db)
- Bug 1199203 - Add support for per-thread OOM testing. r=jonco (2a9919d659)
- Bug 1171226 - Fix mozilla::devtools::UniqueStringHashPolicy::match for strings with the same prefix; r=jimb (1843cec175)
- Bug 1206290 - Part 0: Move js/UbiNodeTraverse.h to js/UbiNodeBreadthFirst.h; r=sfink (c22e008995)
- Bug 1199843 - Part 1: Prefer T::traceChildren over tag dispatched TraceChildren; r=jonco (d935bb1c1c)
- Bug 1199843 - Part 2: Use js::TraceChildren everywhere we don't need external linkage; r=jonco (de8cd29a01)
- Bug 1199843 - Part 3: Strongly type JS::TraceChildren; r=jonco r=mccr8 (2cdd931159)
- Bug 1178961 - Restore the std::string fix from bug 1167230 r=BenWa (4251402fce)
- Bug 1206288 - Remove JS::ubi::SimpleEdge and make JS::ubi::Edge a concrete class; r=shu (d995efed2d)
- Bug 1182653 - Use JSRuntime* instead of JSContext* in ubi::Node infrastructure; r=sfink (e11e0bd0ba)
- Bug 1207236 - ARM64: Build errors with --enable-simulator=arm64. r=h4writer (cc76d43493)
- Bug 1207793 - Fix unified bustage from the TaggedPointer split; r=jolesen (e05b300406)
- Bug 1204866 - IonMonkey: Crash when failing to apand to parse finished list, r=bhackett (efab1b4a1f)
- Bug 1209911 - Use a Variant type to represent HelperThread data r=jandem (ea21131f21)
- Bug 1209911 - Make AutoEnterOOMUnsafeRegion ignore threads that are not simulating OOM r=terrence (769f06a4dc)
- Bug 1203814 - "Adding a testing function causes intermittent orange in oomInFormatStackDump.js on Win32 debug SM(p)." r=jcoppeard (da95054606)
- Bug 1209911 - Add oomThreadTypes() test function to report the number of thread types we can simulate OOM on r=terrence (1d56ca0b74)
- Bug 1209911 - Limit the number of helper threads of a particular type when simulating OOM r=jandem (ceafa83794)
- Bug 1209911 - Remove option to simulate OOM on all threads r=terrence (b43fcf3959)
- Bug 1201057 - Update shell args for OOM tests now we don't have to worry about unhandlable OOMs r=terrence (843c1fc6e3)
- Bug 1208994 - ToAtom<NoGC> should not throw an exception on failure r=terrence (ad57246c1e)
- Bug 1210760 - Don't simulate OOM in ExceptionHandlerBailout() r=terrence (89bab8d51b)
- Bug 1209911 - Enable threads for existing OOM tests r=terrence (a6f94e1f2f)
- Bug 1169974 - Tolerate inconsistent-missing-override warnings for MOCK_METHOD2 macro from gtests. r=fitzgen. (96d613239d)
- Bug 1206290 - Part 1: Implement a JS::ubi::PostOrder depth first traversal; r=sfink (d4de3aa8bc)
- Bug 1196461 - De-duplicate strings in heap snapshot core dumps; r=shu,jimb (24080971ae)
- missing bit of 1101561 (d4b61c9688)
- Bug 1199215 - Implement JS::ubi::Node::size for JS::Symbol referents;S::ubi::Node::size for JS::Symbol referents; r=sfink (929fceb199)
- Bug 1200345: Add comment to js/public/UbiNode.h warning about operating on graphs constructed by hostile code. DONTBUILD r=fitzgen (b83c2d0aad)
- Bug 1199216 - Implement JS::ubi::Node::size for JSScript referents; r=sfink (5a134ffa8e)
- Bug 1205744 - Removed redundant method IsContextRunningJS. r=h4writer (a7e90bbead)
- Bug 1203920 - Get rid of JS_SetStructuredCloneCallbacks, r=sfink (197118cf95)
- Bug 1204554 part 1 - Remove unused JSContext from LcovWriteScript. r=bhackett (12fa4dcc99)
- Bug 1209263 - Allow embedders to tell SpiderMonkey how to structured clone principals; r=bz (c4e929e50f)
- Bug 1191098 - Replace AutoHashableValueRooter with Rooted<HashableValue>; r=jonco (99e23cf3a4)
- Bug 1190628 - Replace AutoScriptVector with normal Rooted usage; r=jimb (926d499edd)
- Bug 1188445 - Allow PersistentRooted to store StaticTraceable; r=sfink (eac1824298)
- Bug 1195957 - Implement a Swap for Heap<T> that does not put temporaries on the stack, r=terrence (26935b5efd)
- Bug 1203695 - GenerateLcovInfo: Check if JSScripts have associated bytecode before spewing their content. r=bhackett (71854b606a)
- Bug 1204554 part 2 - Split LCov functions to make the aggregation of results incremental. r=terrence,bhackett (3a6bd8719e)
- Bug 1204554 part 3.0 - Collect lcov output on the JSCompartment, and on the JSRuntime. r=terrence,bhackett (35544460b1)
- Bug 1204554 part 3.1 - Prevent lazy parsing if we have to spew lcov result. r=bhackett (b36775e171)
- Bug 1204554 part 3.2 - Collect the source files before any script, as they are swept first. r=terrence (4d841a641e)
- Bug 1204554 part 3.3 - Only collect inner JSScript if they have the same source. r=terrence (b38f45764e)
- Bug 1204554 part 3.4 - Ensure that scriptCountsMaps data are still alive until the destruction of compartments. r=terrence,bhackett (50d4217d20)
- Bug 1200642 - Fix OOM handling issues r=terrence (d8ba8b1714)
- Bug 1206247 - Do not collect coverage information if the source has n filename. r=bhackett (0602188d8e)
- pointer style (09cd14aec3)
- Bug 1207232: Let lockOwner be Atomic; r=terrence (e4aa1e635d)
- Bug 1192304 - Common up the checks when entering GC API; r=jonco (935c618bc4)
- Bug 1192306 - Use a function to check if IsShutdownGC rather than open-coding it; r=jonco (c14a96ba2d)
- Bug 1202865 - Split out Zone selection from stats collection and malloc bytes reset; r=jonco (89d5e9def1)
- Bug 1193428 - Rename the incremental parameter to be more meaningful; r=jonco (5d5f38b39d)
- Bug 1209704 - Part 1: Rename BarrieredBase to WriteBarrieredBase; r=jonco (4559ae15aa)
- Bug 1209704 - Part 2: Share storage and mixins between Read and Write barriers; r=jonco (eddc9ff80c)
- Bug 1177515 - Skip tracing object elements if type information shows they don't contain any GC pointers r=terrence (94e2c1ee71)
- Bug 1209704 - Part 3: Share tracing accessors between all barrier classes; r=jonco (1e30d0f16d)
- Bug 1209704 - Part 4: Add a post-barrier to ReadBarriered; r=jonco (22bb316d70)
- Bug 1211022 - Add a type specialization for weak C++ GC thing references; r=sfink (d3d5e88ba8)
- Bug 1204169 - Push SPS pseudo frame entries when GCing; r=terrence (61501f7597)
- Bug 1211031 - Use WeakRef to manage the LazyScript to JSScript back-reference; r=jandem (7c48b04d35)
- Bug 1204167 - Create the js::AutoSPSEntry RAII class for defining psuedo frame entries; r=djvj (519342668f)
- Bug 1204584 - Ensure that entries created by AutoSPSEntry propogate their category information; r=djvj (bd5d96e8b6)
- Bug 1011786 - Diagnostic patch to detect cyclic ropes, r=terrence (c2ece1d49d)
- fix comment (619a5bff31)
2022-08-15 10:15:32 +08:00

945 lines
28 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:set ts=4 sw=4 sts=4 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsViewSourceChannel.h"
#include "nsIIOService.h"
#include "nsMimeTypes.h"
#include "nsNetUtil.h"
#include "nsContentUtils.h"
#include "nsIHttpHeaderVisitor.h"
#include "nsContentSecurityManager.h"
#include "nsNullPrincipal.h"
#include "nsServiceManagerUtils.h"
#include "nsIInputStreamChannel.h"
#include "mozilla/DebugOnly.h"
NS_IMPL_ADDREF(nsViewSourceChannel)
NS_IMPL_RELEASE(nsViewSourceChannel)
/*
This QI uses NS_INTERFACE_MAP_ENTRY_CONDITIONAL to check for
non-nullness of mHttpChannel, mCachingChannel, and mUploadChannel.
*/
NS_INTERFACE_MAP_BEGIN(nsViewSourceChannel)
NS_INTERFACE_MAP_ENTRY(nsIViewSourceChannel)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIHttpChannel, mHttpChannel)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIHttpChannelInternal, mHttpChannelInternal)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICachingChannel, mCachingChannel)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICacheInfoChannel, mCacheInfoChannel)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIApplicationCacheChannel, mApplicationCacheChannel)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIUploadChannel, mUploadChannel)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIRequest, nsIViewSourceChannel)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIChannel, nsIViewSourceChannel)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIViewSourceChannel)
NS_INTERFACE_MAP_END
nsresult
nsViewSourceChannel::Init(nsIURI* uri)
{
mOriginalURI = uri;
nsAutoCString path;
nsresult rv = uri->GetPath(path);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIIOService> pService(do_GetIOService(&rv));
if (NS_FAILED(rv)) return rv;
nsAutoCString scheme;
rv = pService->ExtractScheme(path, scheme);
if (NS_FAILED(rv))
return rv;
// prevent viewing source of javascript URIs (see bug 204779)
if (scheme.LowerCaseEqualsLiteral("javascript")) {
NS_WARNING("blocking view-source:javascript:");
return NS_ERROR_INVALID_ARG;
}
// This function is called from within nsViewSourceHandler::NewChannel2
// and sets the right loadInfo right after returning from this function.
// Until then we follow the principal of least privilege and use
// nullPrincipal as the loadingPrincipal.
nsCOMPtr<nsIPrincipal> nullPrincipal = nsNullPrincipal::Create();
NS_ENSURE_TRUE(nullPrincipal, NS_ERROR_FAILURE);
rv = pService->NewChannel2(path,
nullptr, // aOriginCharset
nullptr, // aCharSet
nullptr, // aLoadingNode
nullPrincipal,
nullptr, // aTriggeringPrincipal
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER,
getter_AddRefs(mChannel));
NS_ENSURE_SUCCESS(rv, rv);
mIsSrcdocChannel = false;
mChannel->SetOriginalURI(mOriginalURI);
mHttpChannel = do_QueryInterface(mChannel);
mHttpChannelInternal = do_QueryInterface(mChannel);
mCachingChannel = do_QueryInterface(mChannel);
mCacheInfoChannel = do_QueryInterface(mChannel);
mApplicationCacheChannel = do_QueryInterface(mChannel);
mUploadChannel = do_QueryInterface(mChannel);
return NS_OK;
}
nsresult
nsViewSourceChannel::InitSrcdoc(nsIURI* aURI,
nsIURI* aBaseURI,
const nsAString &aSrcdoc,
nsINode *aLoadingNode,
nsIPrincipal *aLoadingPrincipal,
nsIPrincipal *aTriggeringPrincipal,
nsSecurityFlags aSecurityFlags,
nsContentPolicyType aContentPolicyType)
{
nsresult rv;
nsCOMPtr<nsIURI> inStreamURI;
// Need to strip view-source: from the URI. Hardcoded to
// about:srcdoc as this is the only permissible URI for srcdoc
// loads
rv = NS_NewURI(getter_AddRefs(inStreamURI),
NS_LITERAL_STRING("about:srcdoc"));
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewInputStreamChannelInternal(getter_AddRefs(mChannel),
inStreamURI,
aSrcdoc,
NS_LITERAL_CSTRING("text/html"),
aLoadingNode,
aLoadingPrincipal,
aTriggeringPrincipal,
aSecurityFlags,
aContentPolicyType,
true);
NS_ENSURE_SUCCESS(rv, rv);
mOriginalURI = aURI;
mIsSrcdocChannel = true;
mChannel->SetOriginalURI(mOriginalURI);
mHttpChannel = do_QueryInterface(mChannel);
mHttpChannelInternal = do_QueryInterface(mChannel);
mCachingChannel = do_QueryInterface(mChannel);
mCacheInfoChannel = do_QueryInterface(mChannel);
mApplicationCacheChannel = do_QueryInterface(mChannel);
mUploadChannel = do_QueryInterface(mChannel);
nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(mChannel);
MOZ_ASSERT(isc);
isc->SetBaseURI(aBaseURI);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsIRequest methods:
NS_IMETHODIMP
nsViewSourceChannel::GetName(nsACString &result)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsViewSourceChannel::IsPending(bool *result)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->IsPending(result);
}
NS_IMETHODIMP
nsViewSourceChannel::GetStatus(nsresult *status)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->GetStatus(status);
}
NS_IMETHODIMP
nsViewSourceChannel::Cancel(nsresult status)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->Cancel(status);
}
NS_IMETHODIMP
nsViewSourceChannel::Suspend(void)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->Suspend();
}
NS_IMETHODIMP
nsViewSourceChannel::Resume(void)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->Resume();
}
////////////////////////////////////////////////////////////////////////////////
// nsIChannel methods:
NS_IMETHODIMP
nsViewSourceChannel::GetOriginalURI(nsIURI* *aURI)
{
NS_ASSERTION(aURI, "Null out param!");
*aURI = mOriginalURI;
NS_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP
nsViewSourceChannel::SetOriginalURI(nsIURI* aURI)
{
NS_ENSURE_ARG_POINTER(aURI);
mOriginalURI = aURI;
return NS_OK;
}
NS_IMETHODIMP
nsViewSourceChannel::GetURI(nsIURI* *aURI)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
nsCOMPtr<nsIURI> uri;
nsresult rv = mChannel->GetURI(getter_AddRefs(uri));
if (NS_FAILED(rv))
return rv;
// protect ourselves against broken channel implementations
if (!uri) {
NS_ERROR("inner channel returned NS_OK and a null URI");
return NS_ERROR_UNEXPECTED;
}
nsAutoCString spec;
uri->GetSpec(spec);
/* XXX Gross hack -- NS_NewURI goes into an infinite loop on
non-flat specs. See bug 136980 */
return NS_NewURI(aURI, nsAutoCString(NS_LITERAL_CSTRING("view-source:")+spec), nullptr);
}
NS_IMETHODIMP
nsViewSourceChannel::Open(nsIInputStream **_retval)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
nsresult rv = NS_OK;
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
if (loadInfo && loadInfo->GetEnforceSecurity()) {
mChannel->Open2(_retval);
}
else {
mChannel->Open(_retval);
}
if (NS_SUCCEEDED(rv)) {
mOpened = true;
}
return rv;
}
NS_IMETHODIMP
nsViewSourceChannel::Open2(nsIInputStream** aStream)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
if(!loadInfo) {
MOZ_ASSERT(loadInfo, "can not enforce security without loadInfo");
return NS_ERROR_UNEXPECTED;
}
// setting the flag on the loadInfo indicates that the underlying
// channel will be openend using Open2() and hence performs
// the necessary security checks.
loadInfo->SetEnforceSecurity(true);
return Open(aStream);
}
NS_IMETHODIMP
nsViewSourceChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
{
#ifdef DEBUG
{
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
MOZ_ASSERT(!loadInfo || loadInfo->GetSecurityMode() == 0 ||
loadInfo->GetEnforceSecurity(),
"security flags in loadInfo but asyncOpen2() not called");
}
#endif
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
mListener = aListener;
/*
* We want to add ourselves to the loadgroup before opening
* mChannel, since we want to make sure we're in the loadgroup
* when mChannel finishes and fires OnStopRequest()
*/
nsCOMPtr<nsILoadGroup> loadGroup;
mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
if (loadGroup)
loadGroup->AddRequest(static_cast<nsIViewSourceChannel*>
(this), nullptr);
nsresult rv = NS_OK;
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
if (loadInfo && loadInfo->GetEnforceSecurity()) {
rv = mChannel->AsyncOpen2(this);
}
else {
rv = mChannel->AsyncOpen(this, ctxt);
}
if (NS_FAILED(rv) && loadGroup)
loadGroup->RemoveRequest(static_cast<nsIViewSourceChannel*>
(this),
nullptr, rv);
if (NS_SUCCEEDED(rv)) {
mOpened = true;
}
return rv;
}
NS_IMETHODIMP
nsViewSourceChannel::AsyncOpen2(nsIStreamListener *aListener)
{
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
if(!loadInfo) {
MOZ_ASSERT(loadInfo, "can not enforce security without loadInfo");
return NS_ERROR_UNEXPECTED;
}
// setting the flag on the loadInfo indicates that the underlying
// channel will be openend using AsyncOpen2() and hence performs
// the necessary security checks.
loadInfo->SetEnforceSecurity(true);
return AsyncOpen(aListener, nullptr);
}
/*
* Both the view source channel and mChannel are added to the
* loadgroup. There should never be more than one request in the
* loadgroup that has LOAD_DOCUMENT_URI set. The one that has this
* flag set is the request whose URI is used to refetch the document,
* so it better be the viewsource channel.
*
* Therefore, we need to make sure that
* 1) The load flags on mChannel _never_ include LOAD_DOCUMENT_URI
* 2) The load flags on |this| include LOAD_DOCUMENT_URI when it was
* set via SetLoadFlags (mIsDocument keeps track of this flag).
*/
NS_IMETHODIMP
nsViewSourceChannel::GetLoadFlags(uint32_t *aLoadFlags)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
nsresult rv = mChannel->GetLoadFlags(aLoadFlags);
if (NS_FAILED(rv))
return rv;
// This should actually be just LOAD_DOCUMENT_URI but the win32 compiler
// fails to deal due to amiguous inheritance. nsIChannel::LOAD_DOCUMENT_URI
// also fails; the Win32 compiler thinks that's supposed to be a method.
if (mIsDocument)
*aLoadFlags |= ::nsIChannel::LOAD_DOCUMENT_URI;
return rv;
}
NS_IMETHODIMP
nsViewSourceChannel::SetLoadFlags(uint32_t aLoadFlags)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
// "View source" always wants the currently cached content.
// We also want to have _this_ channel, not mChannel to be the
// 'document' channel in the loadgroup.
// These should actually be just LOAD_FROM_CACHE and LOAD_DOCUMENT_URI but
// the win32 compiler fails to deal due to amiguous inheritance.
// nsIChannel::LOAD_DOCUMENT_URI/nsIRequest::LOAD_FROM_CACHE also fails; the
// Win32 compiler thinks that's supposed to be a method.
mIsDocument = (aLoadFlags & ::nsIChannel::LOAD_DOCUMENT_URI) ? true : false;
nsresult rv = mChannel->SetLoadFlags((aLoadFlags |
::nsIRequest::LOAD_FROM_CACHE) &
~::nsIChannel::LOAD_DOCUMENT_URI);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (mHttpChannel) {
rv = mHttpChannel->SetIsMainDocumentChannel(aLoadFlags & ::nsIChannel::LOAD_DOCUMENT_URI);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
return NS_OK;
}
NS_IMETHODIMP
nsViewSourceChannel::GetContentType(nsACString &aContentType)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
aContentType.Truncate();
if (mContentType.IsEmpty())
{
// Get the current content type
nsresult rv;
nsAutoCString contentType;
rv = mChannel->GetContentType(contentType);
if (NS_FAILED(rv)) return rv;
// If we don't know our type, just say so. The unknown
// content decoder will then kick in automatically, and it
// will call our SetOriginalContentType method instead of our
// SetContentType method to set the type it determines.
if (!contentType.Equals(UNKNOWN_CONTENT_TYPE)) {
contentType = VIEWSOURCE_CONTENT_TYPE;
}
mContentType = contentType;
}
aContentType = mContentType;
return NS_OK;
}
NS_IMETHODIMP
nsViewSourceChannel::SetContentType(const nsACString &aContentType)
{
// Our GetContentType() currently returns VIEWSOURCE_CONTENT_TYPE
//
// However, during the parsing phase the parser calls our
// channel's GetContentType(). Returning the string above trips up
// the parser. In order to avoid messy changes and not to have the
// parser depend on nsIViewSourceChannel Vidur proposed the
// following solution:
//
// The ViewSourceChannel initially returns a content type of
// VIEWSOURCE_CONTENT_TYPE. Based on this type decisions to
// create a viewer for doing a view source are made. After the
// viewer is created, nsLayoutDLF::CreateInstance() calls this
// SetContentType() with the original content type. When it's
// time for the parser to find out the content type it will call
// our channel's GetContentType() and it will get the original
// content type, such as, text/html and everything is kosher from
// then on.
if (!mOpened) {
// We do not take hints
return NS_ERROR_NOT_AVAILABLE;
}
mContentType = aContentType;
return NS_OK;
}
NS_IMETHODIMP
nsViewSourceChannel::GetContentCharset(nsACString &aContentCharset)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->GetContentCharset(aContentCharset);
}
NS_IMETHODIMP
nsViewSourceChannel::SetContentCharset(const nsACString &aContentCharset)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->SetContentCharset(aContentCharset);
}
// We don't forward these methods becacuse content-disposition isn't whitelisted
// (see GetResponseHeader/VisitResponseHeaders).
NS_IMETHODIMP
nsViewSourceChannel::GetContentDisposition(uint32_t *aContentDisposition)
{
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
nsViewSourceChannel::SetContentDisposition(uint32_t aContentDisposition)
{
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
nsViewSourceChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
{
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
nsViewSourceChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename)
{
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
nsViewSourceChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
{
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
nsViewSourceChannel::GetContentLength(int64_t *aContentLength)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->GetContentLength(aContentLength);
}
NS_IMETHODIMP
nsViewSourceChannel::SetContentLength(int64_t aContentLength)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->SetContentLength(aContentLength);
}
NS_IMETHODIMP
nsViewSourceChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->GetLoadGroup(aLoadGroup);
}
NS_IMETHODIMP
nsViewSourceChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->SetLoadGroup(aLoadGroup);
}
NS_IMETHODIMP
nsViewSourceChannel::GetOwner(nsISupports* *aOwner)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->GetOwner(aOwner);
}
NS_IMETHODIMP
nsViewSourceChannel::SetOwner(nsISupports* aOwner)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->SetOwner(aOwner);
}
NS_IMETHODIMP
nsViewSourceChannel::GetLoadInfo(nsILoadInfo* *aLoadInfo)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->GetLoadInfo(aLoadInfo);
}
NS_IMETHODIMP
nsViewSourceChannel::SetLoadInfo(nsILoadInfo* aLoadInfo)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->SetLoadInfo(aLoadInfo);
}
NS_IMETHODIMP
nsViewSourceChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->GetNotificationCallbacks(aNotificationCallbacks);
}
NS_IMETHODIMP
nsViewSourceChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->SetNotificationCallbacks(aNotificationCallbacks);
}
NS_IMETHODIMP
nsViewSourceChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->GetSecurityInfo(aSecurityInfo);
}
// nsIViewSourceChannel methods
NS_IMETHODIMP
nsViewSourceChannel::GetOriginalContentType(nsACString &aContentType)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
return mChannel->GetContentType(aContentType);
}
NS_IMETHODIMP
nsViewSourceChannel::SetOriginalContentType(const nsACString &aContentType)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
// clear our cached content-type value
mContentType.Truncate();
return mChannel->SetContentType(aContentType);
}
NS_IMETHODIMP
nsViewSourceChannel::GetIsSrcdocChannel(bool* aIsSrcdocChannel)
{
*aIsSrcdocChannel = mIsSrcdocChannel;
return NS_OK;
}
NS_IMETHODIMP
nsViewSourceChannel::GetBaseURI(nsIURI** aBaseURI)
{
if (mIsSrcdocChannel) {
nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(mChannel);
if (isc) {
return isc->GetBaseURI(aBaseURI);
}
}
*aBaseURI = mBaseURI;
NS_IF_ADDREF(*aBaseURI);
return NS_OK;
}
NS_IMETHODIMP
nsViewSourceChannel::SetBaseURI(nsIURI* aBaseURI)
{
mBaseURI = aBaseURI;
return NS_OK;
}
// nsIRequestObserver methods
NS_IMETHODIMP
nsViewSourceChannel::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
{
NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE);
// The channel may have gotten redirected... Time to update our info
mChannel = do_QueryInterface(aRequest);
mHttpChannel = do_QueryInterface(aRequest);
mCachingChannel = do_QueryInterface(aRequest);
mCacheInfoChannel = do_QueryInterface(mChannel);
mUploadChannel = do_QueryInterface(aRequest);
return mListener->OnStartRequest(static_cast<nsIViewSourceChannel*>
(this),
aContext);
}
NS_IMETHODIMP
nsViewSourceChannel::OnStopRequest(nsIRequest *aRequest, nsISupports* aContext,
nsresult aStatus)
{
NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE);
if (mChannel)
{
nsCOMPtr<nsILoadGroup> loadGroup;
mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
if (loadGroup)
{
loadGroup->RemoveRequest(static_cast<nsIViewSourceChannel*>
(this),
nullptr, aStatus);
}
}
return mListener->OnStopRequest(static_cast<nsIViewSourceChannel*>
(this),
aContext, aStatus);
}
// nsIStreamListener methods
NS_IMETHODIMP
nsViewSourceChannel::OnDataAvailable(nsIRequest *aRequest, nsISupports* aContext,
nsIInputStream *aInputStream,
uint64_t aSourceOffset,
uint32_t aLength)
{
NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE);
return mListener->OnDataAvailable(static_cast<nsIViewSourceChannel*>
(this),
aContext, aInputStream,
aSourceOffset, aLength);
}
// nsIHttpChannel methods
// We want to forward most of nsIHttpChannel over to mHttpChannel, but we want
// to override GetRequestHeader and VisitHeaders. The reason is that we don't
// want various headers like Link: and Refresh: applying to view-source.
NS_IMETHODIMP
nsViewSourceChannel::GetRequestMethod(nsACString & aRequestMethod)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetRequestMethod(aRequestMethod);
}
NS_IMETHODIMP
nsViewSourceChannel::SetRequestMethod(const nsACString & aRequestMethod)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->SetRequestMethod(aRequestMethod);
}
NS_IMETHODIMP
nsViewSourceChannel::GetReferrer(nsIURI * *aReferrer)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetReferrer(aReferrer);
}
NS_IMETHODIMP
nsViewSourceChannel::SetReferrer(nsIURI * aReferrer)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->SetReferrer(aReferrer);
}
NS_IMETHODIMP
nsViewSourceChannel::GetReferrerPolicy(uint32_t *aReferrerPolicy)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetReferrerPolicy(aReferrerPolicy);
}
NS_IMETHODIMP
nsViewSourceChannel::SetReferrerWithPolicy(nsIURI * aReferrer,
uint32_t aReferrerPolicy)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->SetReferrerWithPolicy(aReferrer, aReferrerPolicy);
}
NS_IMETHODIMP
nsViewSourceChannel::GetRequestHeader(const nsACString & aHeader,
nsACString & aValue)
{
aValue.Truncate();
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetRequestHeader(aHeader, aValue);
}
NS_IMETHODIMP
nsViewSourceChannel::SetRequestHeader(const nsACString & aHeader,
const nsACString & aValue,
bool aMerge)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->SetRequestHeader(aHeader, aValue, aMerge);
}
NS_IMETHODIMP
nsViewSourceChannel::SetEmptyRequestHeader(const nsACString & aHeader)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->SetEmptyRequestHeader(aHeader);
}
NS_IMETHODIMP
nsViewSourceChannel::VisitRequestHeaders(nsIHttpHeaderVisitor *aVisitor)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->VisitRequestHeaders(aVisitor);
}
NS_IMETHODIMP
nsViewSourceChannel::VisitNonDefaultRequestHeaders(nsIHttpHeaderVisitor *aVisitor)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->VisitNonDefaultRequestHeaders(aVisitor);
}
NS_IMETHODIMP
nsViewSourceChannel::GetAllowPipelining(bool *aAllowPipelining)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetAllowPipelining(aAllowPipelining);
}
NS_IMETHODIMP
nsViewSourceChannel::SetAllowPipelining(bool aAllowPipelining)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->SetAllowPipelining(aAllowPipelining);
}
NS_IMETHODIMP
nsViewSourceChannel::GetAllowSTS(bool *aAllowSTS)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetAllowSTS(aAllowSTS);
}
NS_IMETHODIMP
nsViewSourceChannel::SetAllowSTS(bool aAllowSTS)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->SetAllowSTS(aAllowSTS);
}
NS_IMETHODIMP
nsViewSourceChannel::GetRedirectionLimit(uint32_t *aRedirectionLimit)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetRedirectionLimit(aRedirectionLimit);
}
NS_IMETHODIMP
nsViewSourceChannel::SetRedirectionLimit(uint32_t aRedirectionLimit)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->SetRedirectionLimit(aRedirectionLimit);
}
NS_IMETHODIMP
nsViewSourceChannel::GetResponseStatus(uint32_t *aResponseStatus)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetResponseStatus(aResponseStatus);
}
NS_IMETHODIMP
nsViewSourceChannel::GetResponseStatusText(nsACString & aResponseStatusText)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetResponseStatusText(aResponseStatusText);
}
NS_IMETHODIMP
nsViewSourceChannel::GetRequestSucceeded(bool *aRequestSucceeded)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetRequestSucceeded(aRequestSucceeded);
}
NS_IMETHODIMP
nsViewSourceChannel::GetResponseHeader(const nsACString & aHeader,
nsACString & aValue)
{
aValue.Truncate();
if (!mHttpChannel)
return NS_ERROR_NULL_POINTER;
if (!aHeader.Equals(NS_LITERAL_CSTRING("Content-Type"),
nsCaseInsensitiveCStringComparator()) &&
!aHeader.Equals(NS_LITERAL_CSTRING("Content-Security-Policy"),
nsCaseInsensitiveCStringComparator()) &&
!aHeader.Equals(NS_LITERAL_CSTRING("Content-Security-Policy-Report-Only"),
nsCaseInsensitiveCStringComparator()) &&
!aHeader.Equals(NS_LITERAL_CSTRING("X-Frame-Options"),
nsCaseInsensitiveCStringComparator())) {
return NS_OK;
}
return mHttpChannel->GetResponseHeader(aHeader, aValue);
}
NS_IMETHODIMP
nsViewSourceChannel::SetResponseHeader(const nsACString & header,
const nsACString & value, bool merge)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->SetResponseHeader(header, value, merge);
}
NS_IMETHODIMP
nsViewSourceChannel::VisitResponseHeaders(nsIHttpHeaderVisitor *aVisitor)
{
if (!mHttpChannel)
return NS_ERROR_NULL_POINTER;
NS_NAMED_LITERAL_CSTRING(contentTypeStr, "Content-Type");
nsAutoCString contentType;
nsresult rv =
mHttpChannel->GetResponseHeader(contentTypeStr, contentType);
if (NS_SUCCEEDED(rv))
aVisitor->VisitHeader(contentTypeStr, contentType);
return NS_OK;
}
NS_IMETHODIMP
nsViewSourceChannel::IsNoStoreResponse(bool *_retval)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->IsNoStoreResponse(_retval);
}
NS_IMETHODIMP
nsViewSourceChannel::IsNoCacheResponse(bool *_retval)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->IsNoCacheResponse(_retval);
}
NS_IMETHODIMP
nsViewSourceChannel::IsPrivateResponse(bool *_retval)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->IsPrivateResponse(_retval);
}
NS_IMETHODIMP
nsViewSourceChannel::RedirectTo(nsIURI *uri)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->RedirectTo(uri);
}
NS_IMETHODIMP
nsViewSourceChannel::GetSchedulingContextID(nsID *_retval)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetSchedulingContextID(_retval);
}
NS_IMETHODIMP
nsViewSourceChannel::SetSchedulingContextID(const nsID scid)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->SetSchedulingContextID(scid);
}
NS_IMETHODIMP
nsViewSourceChannel::GetIsMainDocumentChannel(bool* aValue)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetIsMainDocumentChannel(aValue);
}
NS_IMETHODIMP
nsViewSourceChannel::SetIsMainDocumentChannel(bool aValue)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->SetIsMainDocumentChannel(aValue);
}