Backed out 9 changesets (bug 1574372) for bustage and wpt failures. on a CLOSED TREE

Backed out changeset b0183a606fec (bug 1574372)
Backed out changeset b7c96254826e (bug 1574372)
Backed out changeset 196d61adc272 (bug 1574372)
Backed out changeset 419b94b1210e (bug 1574372)
Backed out changeset c192e499eb47 (bug 1574372)
Backed out changeset 4e57038c3518 (bug 1574372)
Backed out changeset 6ec2aa542b59 (bug 1574372)
Backed out changeset d71b4c0aac1a (bug 1574372)
Backed out changeset a05c3b113ac1 (bug 1574372)
This commit is contained in:
Oana Pop Rus 2019-12-17 03:26:38 +02:00
Родитель 8a824d68b2
Коммит 5545e5a016
35 изменённых файлов: 277 добавлений и 664 удалений

Просмотреть файл

@ -1008,10 +1008,6 @@ PdfStreamConverter.prototype = {
this.listener = aListener;
},
getConvertedType(aFromType) {
return "text/html";
},
// nsIStreamListener::onDataAvailable
onDataAvailable(aRequest, aInputStream, aOffset, aCount) {
if (!this.dataListener) {

Просмотреть файл

@ -75,9 +75,6 @@ Converter.prototype = {
asyncConvertData: function(fromType, toType, listener, ctx) {
this.listener = listener;
},
getConvertedType: function(fromType) {
return "text/html";
},
onDataAvailable: function(request, inputStream, offset, count) {
// Decode and insert data.

Просмотреть файл

@ -61,7 +61,6 @@ EXPORTS += [
'nsDocShellLoadTypes.h',
'nsDocShellTreeOwner.h',
'nsIScrollObserver.h',
'nsWebNavigationInfo.h',
'SerializedLoadContext.h',
]

Просмотреть файл

@ -17,7 +17,6 @@
#include "nsGlobalWindowOuter.h"
#include "nsIInterfaceRequestor.h"
#include "nsIMultiPartChannel.h"
#include "nsWebNavigationInfo.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -78,6 +77,13 @@ nsDSURIContentListener::nsDSURIContentListener(nsDocShell* aDocShell)
nsDSURIContentListener::~nsDSURIContentListener() {}
nsresult nsDSURIContentListener::Init() {
nsresult rv;
mNavInfo = do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get webnav info");
return rv;
}
NS_IMPL_ADDREF(nsDSURIContentListener)
NS_IMPL_RELEASE(nsDSURIContentListener)
@ -236,13 +242,15 @@ nsDSURIContentListener::CanHandleContent(const char* aContentType,
*aCanHandleContent = false;
*aDesiredContentType = nullptr;
nsresult rv = NS_OK;
if (aContentType) {
uint32_t canHandle = nsWebNavigationInfo::IsTypeSupported(
nsDependentCString(aContentType), mDocShell);
uint32_t canHandle = nsIWebNavigationInfo::UNSUPPORTED;
rv = mNavInfo->IsTypeSupported(nsDependentCString(aContentType), mDocShell,
&canHandle);
*aCanHandleContent = (canHandle != nsIWebNavigationInfo::UNSUPPORTED);
}
return NS_OK;
return rv;
}
NS_IMETHODIMP

Просмотреть файл

@ -67,6 +67,8 @@ class nsDSURIContentListener final : public nsIURIContentListener,
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIURICONTENTLISTENER
nsresult Init();
protected:
explicit nsDSURIContentListener(nsDocShell* aDocShell);
virtual ~nsDSURIContentListener();
@ -88,6 +90,8 @@ class nsDSURIContentListener final : public nsIURIContentListener,
// preferred and encouraged!
nsWeakPtr mWeakParentContentListener;
nsIURIContentListener* mParentContentListener;
nsCOMPtr<nsIWebNavigationInfo> mNavInfo;
};
#endif /* nsDSURIContentListener_h__ */

Просмотреть файл

@ -466,6 +466,10 @@ already_AddRefed<nsDocShell> nsDocShell::Create(
// Create our ContentListener
ds->mContentListener = new nsDSURIContentListener(ds);
rv = ds->mContentListener->Init();
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
// If parent intercept is not enabled then we must forward to
// the network controller from docshell. We also enable if we're
@ -10244,15 +10248,6 @@ nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
// Let the client channel helper know if we are using DocumentChannel,
// since redirects get handled in the parent process in that case.
RefPtr<net::DocumentChannelChild> docChannel = do_QueryObject(aChannel);
if (docChannel) {
bool pluginsAllowed = true;
GetAllowPlugins(&pluginsAllowed);
docChannel->SetDocumentOpenFlags(aOpenFlags, pluginsAllowed);
// Now that we've sent the real flags across to be run on the parent,
// tell the content process nsDocumentOpenInfo to not try to do
// any sort of targeting.
aOpenFlags |= nsIURILoader::DONT_RETARGET;
}
// Since we are loading a document we need to make sure the proper reserved
// and initial client data is stored on the nsILoadInfo. The

Просмотреть файл

@ -16,56 +16,56 @@
NS_IMPL_ISUPPORTS(nsWebNavigationInfo, nsIWebNavigationInfo)
nsresult nsWebNavigationInfo::Init() {
nsresult rv;
mCategoryManager = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
nsWebNavigationInfo::IsTypeSupported(const nsACString& aType,
nsIWebNavigation* aWebNav,
uint32_t* aIsTypeSupported) {
MOZ_ASSERT(aIsTypeSupported, "null out param?");
*aIsTypeSupported = IsTypeSupported(aType, aWebNav);
return NS_OK;
}
uint32_t nsWebNavigationInfo::IsTypeSupported(const nsACString& aType,
nsIWebNavigation* aWebNav) {
// Note to self: aWebNav could be an nsWebBrowser or an nsDocShell here (or
// an nsSHistory, but not much we can do with that). So if we start using
// it here, we need to be careful to get to the docshell correctly.
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aWebNav));
bool pluginsAllowed = true;
if (docShell) {
docShell->GetAllowPlugins(&pluginsAllowed);
}
return IsTypeSupported(aType, pluginsAllowed);
}
// For now just report what the Gecko-Content-Viewers category has
// to say for itself.
*aIsTypeSupported = nsIWebNavigationInfo::UNSUPPORTED;
uint32_t nsWebNavigationInfo::IsTypeSupported(const nsACString& aType,
bool aPluginsAllowed) {
// We want to claim that the type for PDF documents is unsupported,
// so that the internal PDF viewer's stream converted will get used.
if (aType.LowerCaseEqualsLiteral("application/pdf") &&
nsContentUtils::IsPDFJSEnabled()) {
return nsIWebNavigationInfo::UNSUPPORTED;
;
return NS_OK;
}
const nsCString& flatType = PromiseFlatCString(aType);
uint32_t result = IsTypeSupportedInternal(flatType);
if (result != nsIWebNavigationInfo::UNSUPPORTED) {
return result;
nsresult rv = IsTypeSupportedInternal(flatType, aIsTypeSupported);
NS_ENSURE_SUCCESS(rv, rv);
if (*aIsTypeSupported) {
return rv;
}
// As of FF 52, we only support flash and test plugins, so if the mime types
// don't match for that, exit before we start loading plugins.
if (!nsPluginHost::CanUsePluginForMIMEType(aType)) {
return nsIWebNavigationInfo::UNSUPPORTED;
return NS_OK;
}
// If this request is for a docShell that isn't going to allow plugins,
// there's no need to try and find a plugin to handle it.
if (!aPluginsAllowed) {
return nsIWebNavigationInfo::UNSUPPORTED;
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aWebNav));
bool allowed;
if (docShell && NS_SUCCEEDED(docShell->GetAllowPlugins(&allowed)) &&
!allowed) {
return NS_OK;
}
// Try reloading plugins in case they've changed.
@ -74,20 +74,23 @@ uint32_t nsWebNavigationInfo::IsTypeSupported(const nsACString& aType,
if (pluginHost) {
// false will ensure that currently running plugins will not
// be shut down
nsresult rv = pluginHost->ReloadPlugins();
rv = pluginHost->ReloadPlugins();
if (NS_SUCCEEDED(rv)) {
// OK, we reloaded plugins and there were new ones
// (otherwise NS_ERROR_PLUGINS_PLUGINSNOTCHANGED would have
// been returned). Try checking whether we can handle the
// content now.
return IsTypeSupportedInternal(flatType);
return IsTypeSupportedInternal(flatType, aIsTypeSupported);
}
}
return nsIWebNavigationInfo::UNSUPPORTED;
return NS_OK;
}
uint32_t nsWebNavigationInfo::IsTypeSupportedInternal(const nsCString& aType) {
nsresult nsWebNavigationInfo::IsTypeSupportedInternal(const nsCString& aType,
uint32_t* aIsSupported) {
MOZ_ASSERT(aIsSupported, "Null out param?");
nsContentUtils::ContentViewerType vtype = nsContentUtils::TYPE_UNSUPPORTED;
nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
@ -95,24 +98,28 @@ uint32_t nsWebNavigationInfo::IsTypeSupportedInternal(const nsCString& aType) {
switch (vtype) {
case nsContentUtils::TYPE_UNSUPPORTED:
return nsIWebNavigationInfo::UNSUPPORTED;
*aIsSupported = nsIWebNavigationInfo::UNSUPPORTED;
break;
case nsContentUtils::TYPE_PLUGIN:
return nsIWebNavigationInfo::PLUGIN;
*aIsSupported = nsIWebNavigationInfo::PLUGIN;
break;
case nsContentUtils::TYPE_UNKNOWN:
return nsIWebNavigationInfo::OTHER;
*aIsSupported = nsIWebNavigationInfo::OTHER;
break;
case nsContentUtils::TYPE_CONTENT:
// XXXbz we only need this because images register for the same
// contractid as documents, so we can't tell them apart based on
// contractid.
if (imgLoader::SupportImageWithMimeType(aType.get())) {
return nsIWebNavigationInfo::IMAGE;
*aIsSupported = nsIWebNavigationInfo::IMAGE;
} else {
return nsIWebNavigationInfo::OTHER;
*aIsSupported = nsIWebNavigationInfo::OTHER;
}
break;
}
return nsIWebNavigationInfo::UNSUPPORTED;
return NS_OK;
}

Просмотреть файл

@ -21,17 +21,17 @@ class nsWebNavigationInfo final : public nsIWebNavigationInfo {
NS_DECL_NSIWEBNAVIGATIONINFO
static uint32_t IsTypeSupported(const nsACString& aType,
nsIWebNavigation* aWebNav);
static uint32_t IsTypeSupported(const nsACString& aType,
bool aPluginsAllowed);
nsresult Init();
private:
~nsWebNavigationInfo() {}
// Check whether aType is supported, and returns an nsIWebNavigationInfo
// constant.
static uint32_t IsTypeSupportedInternal(const nsCString& aType);
// Check whether aType is supported. If this method throws, the
// value of aIsSupported is not changed.
nsresult IsTypeSupportedInternal(const nsCString& aType,
uint32_t* aIsSupported);
nsCOMPtr<nsICategoryManager> mCategoryManager;
};
#endif // nsWebNavigationInfo_h__

Просмотреть файл

@ -137,6 +137,7 @@ Classes = [
'contract_ids': ['@mozilla.org/webnavigation-info;1'],
'type': 'nsWebNavigationInfo',
'headers': ['/docshell/base/nsWebNavigationInfo.h'],
'init_method': 'Init',
},
]

Просмотреть файл

@ -91,12 +91,6 @@ NS_IMETHODIMP nsDeflateConverter::AsyncConvertData(const char* aFromType,
return rv;
}
NS_IMETHODIMP
nsDeflateConverter::GetConvertedType(const nsACString& aFromType,
nsACString& aToType) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsDeflateConverter::OnDataAvailable(nsIRequest* aRequest,
nsIInputStream* aInputStream,
uint64_t aOffset,

Просмотреть файл

@ -26,13 +26,7 @@ class ADocumentChannelBridge {
// process).
// This should remove the nsIChannel from the loadgroup, and
// fire OnStart/StopRequest with aStatus.
// aLoadGroupStatus is used as mStatus when we remove the child channel
// from the loadgroup (but aStatus is passed as the parameter to
// RemoveRequest).
// We do this so we can remove using NS_BINDING_RETARGETED, but still have
// the channel not be in an error state.
virtual void DisconnectChildListeners(nsresult aStatus,
nsresult aLoadGroupStatus) = 0;
virtual void DisconnectChildListeners(nsresult aStatus) = 0;
// Delete the bridge, and drop any refs to the DocumentLoadListener
virtual void Delete() = 0;

Просмотреть файл

@ -190,8 +190,6 @@ DocumentChannelChild::AsyncOpen(nsIStreamListener* aListener) {
args.hasNonEmptySandboxingFlags() = mHasNonEmptySandboxingFlags;
args.channelId() = mChannelId;
args.asyncOpenTime() = mAsyncOpenTime;
args.documentOpenFlags() = mDocumentOpenFlags;
args.pluginsAllowed() = mPluginsAllowed;
nsDocShell* docshell = GetDocShell();
if (docshell) {
@ -203,7 +201,7 @@ DocumentChannelChild::AsyncOpen(nsIStreamListener* aListener) {
NS_GET_TEMPLATE_IID(nsIBrowserChild),
getter_AddRefs(iBrowserChild));
BrowserChild* browserChild = static_cast<BrowserChild*>(iBrowserChild.get());
if (MissingRequiredBrowserChild(browserChild, "documentchannel")) {
if (MissingRequiredBrowserChild(browserChild, "ftp")) {
return NS_ERROR_ILLEGAL_VALUE;
}
@ -272,9 +270,8 @@ void DocumentChannelChild::ShutdownListeners(nsresult aStatusCode) {
}
IPCResult DocumentChannelChild::RecvDisconnectChildListeners(
const nsresult& aStatus, const nsresult& aLoadGroupStatus) {
const nsresult& aStatus) {
MOZ_ASSERT(NS_FAILED(aStatus));
mStatus = aLoadGroupStatus;
// Make sure we remove from the load group before
// setting mStatus, as existing tests expect the
// status to be successful when we disconnect.

Просмотреть файл

@ -46,8 +46,7 @@ class DocumentChannelChild final : public nsIIdentChannel,
mozilla::ipc::IPCResult RecvFailedAsyncOpen(const nsresult& aStatusCode);
mozilla::ipc::IPCResult RecvDisconnectChildListeners(
const nsresult& aStatus, const nsresult& aLoadGroupStatus);
mozilla::ipc::IPCResult RecvDisconnectChildListeners(const nsresult& aStatus);
mozilla::ipc::IPCResult RecvDeleteSelf();
@ -71,11 +70,6 @@ class DocumentChannelChild final : public nsIIdentChannel,
*aChannelRedirectFlags = mLastVisitInfo.previousFlags();
}
void SetDocumentOpenFlags(uint32_t aFlags, bool aPluginsAllowed) {
mDocumentOpenFlags = Some(aFlags);
mPluginsAllowed = aPluginsAllowed;
}
private:
void ShutdownListeners(nsresult aStatusCode);
nsDocShell* GetDocShell();
@ -99,7 +93,6 @@ class DocumentChannelChild final : public nsIIdentChannel,
nsresult mStatus = NS_OK;
bool mCanceled = false;
Maybe<uint32_t> mDocumentOpenFlags;
bool mIsPending = false;
bool mWasOpened = false;
uint64_t mChannelId;
@ -110,7 +103,6 @@ class DocumentChannelChild final : public nsIIdentChannel,
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsISupports> mOwner;
bool mPluginsAllowed = false;
};
NS_DEFINE_STATIC_IID_ACCESSOR(DocumentChannelChild, DOCUMENT_CHANNEL_CHILD_IID)

Просмотреть файл

@ -13,20 +13,19 @@ extern mozilla::LazyLogModule gDocumentChannelLog;
namespace mozilla {
namespace net {
DocumentChannelParent::DocumentChannelParent(BrowserParent* aBrowser,
nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus) {
DocumentChannelParent::DocumentChannelParent(
const dom::PBrowserOrId& aIframeEmbedding, nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus) {
LOG(("DocumentChannelParent ctor [this=%p]", this));
mParent =
new DocumentLoadListener(aBrowser, aLoadContext, aOverrideStatus, this);
mParent = new DocumentLoadListener(aIframeEmbedding, aLoadContext,
aOverrideStatus, this);
}
DocumentChannelParent::~DocumentChannelParent() {
LOG(("DocumentChannelParent dtor [this=%p]", this));
}
bool DocumentChannelParent::Init(BrowserParent* aBrowser,
const DocumentChannelCreationArgs& aArgs) {
bool DocumentChannelParent::Init(const DocumentChannelCreationArgs& aArgs) {
RefPtr<nsDocShellLoadState> loadState =
new nsDocShellLoadState(aArgs.loadState());
LOG(("DocumentChannelParent Init [this=%p, uri=%s]", this,
@ -38,14 +37,13 @@ bool DocumentChannelParent::Init(BrowserParent* aBrowser,
MOZ_ASSERT(NS_SUCCEEDED(rv));
rv = NS_ERROR_UNEXPECTED;
if (!mParent->Open(
aBrowser, loadState, loadInfo, aArgs.initiatorType().ptrOr(nullptr),
aArgs.loadFlags(), aArgs.loadType(), aArgs.cacheKey(),
aArgs.isActive(), aArgs.isTopLevelDoc(),
aArgs.hasNonEmptySandboxingFlags(), aArgs.topWindowURI(),
aArgs.contentBlockingAllowListPrincipal(), aArgs.customUserAgent(),
aArgs.channelId(), aArgs.asyncOpenTime(), aArgs.documentOpenFlags(),
aArgs.pluginsAllowed(), &rv)) {
if (!mParent->Open(loadState, loadInfo, aArgs.initiatorType().ptrOr(nullptr),
aArgs.loadFlags(), aArgs.loadType(), aArgs.cacheKey(),
aArgs.isActive(), aArgs.isTopLevelDoc(),
aArgs.hasNonEmptySandboxingFlags(), aArgs.topWindowURI(),
aArgs.contentBlockingAllowListPrincipal(),
aArgs.customUserAgent(), aArgs.channelId(),
aArgs.asyncOpenTime(), &rv)) {
return SendFailedAsyncOpen(rv);
}

Просмотреть файл

@ -23,12 +23,11 @@ class DocumentChannelParent final : public ADocumentChannelBridge,
public:
NS_INLINE_DECL_REFCOUNTING(DocumentChannelParent, override);
explicit DocumentChannelParent(dom::BrowserParent* aBrowser,
explicit DocumentChannelParent(const dom::PBrowserOrId& aIframeEmbedding,
nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus);
bool Init(dom::BrowserParent* aBrowser,
const DocumentChannelCreationArgs& aArgs);
bool Init(const DocumentChannelCreationArgs& aArgs);
// PDocumentChannelParent
bool RecvCancel(const nsresult& aStatus) {
@ -42,10 +41,9 @@ class DocumentChannelParent final : public ADocumentChannelBridge,
private:
// DocumentChannelListener
void DisconnectChildListeners(nsresult aStatus,
nsresult aLoadGroupStatus) override {
void DisconnectChildListeners(nsresult aStatus) override {
if (CanSend()) {
Unused << SendDisconnectChildListeners(aStatus, aLoadGroupStatus);
Unused << SendDisconnectChildListeners(aStatus);
}
}

Просмотреть файл

@ -10,7 +10,6 @@
#include "mozilla/LoadInfo.h"
#include "mozilla/MozPromiseInlines.h" // For MozPromise::FromDomPromise
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/ClientChannelHelper.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ContentProcessManager.h"
@ -26,13 +25,6 @@
#include "nsSerializationHelper.h"
#include "nsIPrompt.h"
#include "nsIWindowWatcher.h"
#include "nsIURIContentListener.h"
#include "nsWebNavigationInfo.h"
#include "nsURILoader.h"
#include "nsIStreamConverterService.h"
#include "nsExternalHelperAppService.h"
#include "nsCExternalHandlerService.h"
#include "nsMimeTypes.h"
mozilla::LazyLogModule gDocumentChannelLog("DocumentChannel");
#define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt)
@ -42,179 +34,6 @@ using namespace mozilla::dom;
namespace mozilla {
namespace net {
/**
* An extension to nsDocumentOpenInfo that we run in the parent process, so
* that we can make the decision to retarget to content handlers or the external
* helper app, before we make process switching decisions.
*
* This modifies the behaviour of nsDocumentOpenInfo so that it can do
* retargeting, but doesn't do stream conversion (but confirms that we will be
* able to do so later).
*
* We still run nsDocumentOpenInfo in the content process, but disable
* retargeting, so that it can only apply stream conversion, and then send data
* to the docshell.
*/
class ParentProcessDocumentOpenInfo final : public nsDocumentOpenInfo,
public nsIMultiPartChannelListener {
public:
ParentProcessDocumentOpenInfo(ParentChannelListener* aListener,
bool aPluginsAllowed, uint32_t aFlags,
mozilla::dom::BrowsingContext* aBrowsingContext)
: nsDocumentOpenInfo(aFlags, false),
mBrowsingContext(aBrowsingContext),
mListener(aListener),
mPluginsAllowed(aPluginsAllowed) {}
NS_DECL_ISUPPORTS_INHERITED
// The default content listener is always a docshell, so this manually
// implements the same checks, and if it succeeds, uses the parent
// channel listener so that we forward onto DocumentLoadListener.
bool TryDefaultContentListener(nsIChannel* aChannel,
const nsCString& aContentType) {
uint32_t canHandle =
nsWebNavigationInfo::IsTypeSupported(aContentType, mPluginsAllowed);
if (canHandle != nsIWebNavigationInfo::UNSUPPORTED) {
m_targetStreamListener = mListener;
nsLoadFlags loadFlags = 0;
aChannel->GetLoadFlags(&loadFlags);
aChannel->SetLoadFlags(loadFlags | nsIChannel::LOAD_TARGETED);
return true;
}
return false;
}
bool TryDefaultContentListener(nsIChannel* aChannel) override {
return TryDefaultContentListener(aChannel, mContentType);
}
// Generally we only support stream converters that can tell
// use exactly what type they'll output. If we find one, then
// we just target to our default listener directly (without
// conversion), and the content process nsDocumentOpenInfo will
// run and do the actual conversion.
bool TryStreamConversion(nsIChannel* aChannel) override {
// The one exception is nsUnknownDecoder, which works in the parent
// (and we need to know what the content type is before we can
// decide if it will be handled in the parent), so we run that here.
if (mContentType.LowerCaseEqualsASCII(UNKNOWN_CONTENT_TYPE)) {
return nsDocumentOpenInfo::TryStreamConversion(aChannel);
}
nsresult rv;
nsCOMPtr<nsIStreamConverterService> streamConvService =
do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
nsAutoCString str;
if (NS_SUCCEEDED(streamConvService->ConvertedType(mContentType, str))) {
// We only support passing data to the default content listener
// (docshell), and we don't supported chaining converters.
if (TryDefaultContentListener(aChannel, str)) {
mContentType = str;
return true;
}
}
return false;
}
bool TryExternalHelperApp(nsIExternalHelperAppService* aHelperAppService,
nsIChannel* aChannel) override {
RefPtr<nsExternalAppHandler> handler;
nsresult rv = aHelperAppService->CreateListener(
mContentType, aChannel, mBrowsingContext, false, nullptr,
getter_AddRefs(handler));
if (NS_SUCCEEDED(rv)) {
m_targetStreamListener = handler;
return true;
}
return false;
}
nsDocumentOpenInfo* Clone() override {
mCloned = true;
return new ParentProcessDocumentOpenInfo(mListener, mPluginsAllowed, mFlags,
mBrowsingContext);
}
NS_IMETHOD OnStartRequest(nsIRequest* request) override {
nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(request);
if (multiPartChannel) {
mExpectingOnAfterLastPart = true;
}
nsresult rv = nsDocumentOpenInfo::OnStartRequest(request);
// If we didn't find a content handler,
// and we don't have a listener, then just forward to our
// default listener. This happens when the channel is in
// an error state, and we want to just forward that on to be
// handled in the content process.
if (!mUsedContentHandler && !m_targetStreamListener) {
m_targetStreamListener = mListener;
return m_targetStreamListener->OnStartRequest(request);
}
return rv;
}
NS_IMETHOD OnStopRequest(nsIRequest* request, nsresult aStatus) override {
// If we're not a multipart stream (and thus not expecting OnAfterLastPart),
// then this is the final OnStopRequest we'll get. If we haven't been
// targeting our default listener, then we need to manually notify it that
// we're done, and nothing further will be arriving. If we got cloned, then
// we don't need to do this, as only the last link needs to do it.
bool needToNotifyListener = false;
if (!mExpectingOnAfterLastPart && m_targetStreamListener != mListener &&
!mCloned) {
needToNotifyListener = true;
}
nsresult rv = nsDocumentOpenInfo::OnStopRequest(request, aStatus);
if (needToNotifyListener) {
// Tell the DocumentLoadListener to notify the content process that it's
// been entirely retargeted, and to stop waiting.
// Clear mListener's pointer to the DocumentLoadListener to break the
// reference cycle.
RefPtr<DocumentLoadListener> doc = do_GetInterface(ToSupports(mListener));
MOZ_ASSERT(doc);
doc->DisconnectChildListeners(NS_BINDING_RETARGETED, NS_OK);
mListener->SetListenerAfterRedirect(nullptr);
}
return rv;
}
NS_IMETHOD OnAfterLastPart(nsresult aStatus) override {
mListener->OnAfterLastPart(aStatus);
return NS_OK;
}
private:
virtual ~ParentProcessDocumentOpenInfo() = default;
RefPtr<mozilla::dom::BrowsingContext> mBrowsingContext;
RefPtr<ParentChannelListener> mListener;
bool mPluginsAllowed;
/**
* Set to true if we got OnStartRequest called with a multipart
* channel, and thus expect OnAfterLastPart to be called when
* the channel is complete.
*/
bool mExpectingOnAfterLastPart = false;
/**
* Set to true if we got cloned to create a chained listener.
*/
bool mCloned = false;
};
NS_IMPL_ADDREF_INHERITED(ParentProcessDocumentOpenInfo, nsDocumentOpenInfo)
NS_IMPL_RELEASE_INHERITED(ParentProcessDocumentOpenInfo, nsDocumentOpenInfo)
NS_INTERFACE_MAP_BEGIN(ParentProcessDocumentOpenInfo)
NS_INTERFACE_MAP_ENTRY(nsIMultiPartChannelListener)
NS_INTERFACE_MAP_END_INHERITING(nsDocumentOpenInfo)
NS_IMPL_ADDREF(DocumentLoadListener)
NS_IMPL_RELEASE(DocumentLoadListener)
@ -231,13 +50,18 @@ NS_INTERFACE_MAP_BEGIN(DocumentLoadListener)
NS_INTERFACE_MAP_ENTRY_CONCRETE(DocumentLoadListener)
NS_INTERFACE_MAP_END
DocumentLoadListener::DocumentLoadListener(BrowserParent* aBrowser,
DocumentLoadListener::DocumentLoadListener(const PBrowserOrId& aIframeEmbedding,
nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus,
ADocumentChannelBridge* aBridge)
: mLoadContext(aLoadContext), mPBOverride(aOverrideStatus) {
LOG(("DocumentLoadListener ctor [this=%p]", this));
mParentChannelListener = new ParentChannelListener(this, aBrowser);
RefPtr<dom::BrowserParent> parent;
if (aIframeEmbedding.type() == PBrowserOrId::TPBrowserParent) {
parent =
static_cast<dom::BrowserParent*>(aIframeEmbedding.get_PBrowserParent());
}
mParentChannelListener = new ParentChannelListener(this, parent);
mDocumentChannelBridge = aBridge;
}
@ -246,15 +70,13 @@ DocumentLoadListener::~DocumentLoadListener() {
}
bool DocumentLoadListener::Open(
BrowserParent* aBrowser, nsDocShellLoadState* aLoadState,
class LoadInfo* aLoadInfo, const nsString* aInitiatorType,
nsLoadFlags aLoadFlags, uint32_t aLoadType, uint32_t aCacheKey,
bool aIsActive, bool aIsTopLevelDoc, bool aHasNonEmptySandboxingFlags,
const Maybe<URIParams>& aTopWindowURI,
nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
const nsString* aInitiatorType, nsLoadFlags aLoadFlags, uint32_t aLoadType,
uint32_t aCacheKey, bool aIsActive, bool aIsTopLevelDoc,
bool aHasNonEmptySandboxingFlags, const Maybe<URIParams>& aTopWindowURI,
const Maybe<PrincipalInfo>& aContentBlockingAllowListPrincipal,
const nsString& aCustomUserAgent, const uint64_t& aChannelId,
const TimeStamp& aAsyncOpenTime, const Maybe<uint32_t>& aDocumentOpenFlags,
bool aPluginsAllowed, nsresult* aRv) {
const TimeStamp& aAsyncOpenTime, nsresult* aRv) {
LOG(("DocumentLoadListener Open [this=%p, uri=%s]", this,
aLoadState->URI()->GetSpecOrDefault().get()));
if (!nsDocShell::CreateChannelForLoadState(
@ -320,17 +142,7 @@ bool DocumentLoadListener::Open(
// across any serviceworker related data between channels as needed.
AddClientChannelHelperInParent(mChannel, GetMainThreadSerialEventTarget());
if (aDocumentOpenFlags) {
RefPtr<ParentProcessDocumentOpenInfo> openInfo =
new ParentProcessDocumentOpenInfo(mParentChannelListener,
aPluginsAllowed, *aDocumentOpenFlags,
aBrowser->GetBrowsingContext());
openInfo->Prepare();
*aRv = mChannel->AsyncOpen(openInfo);
} else {
*aRv = mChannel->AsyncOpen(mParentChannelListener);
}
*aRv = mChannel->AsyncOpen(mParentChannelListener);
if (NS_FAILED(*aRv)) {
mParentChannelListener = nullptr;
return false;
@ -418,8 +230,7 @@ void DocumentLoadListener::FinishReplacementChannelSetup(bool aSucceeded) {
nsresult rv;
if (mDoingProcessSwitch && mDocumentChannelBridge) {
mDocumentChannelBridge->DisconnectChildListeners(NS_BINDING_ABORTED,
NS_BINDING_ABORTED);
mDocumentChannelBridge->DisconnectChildListeners(NS_BINDING_ABORTED);
}
nsCOMPtr<nsIParentChannel> redirectChannel;
@ -876,7 +687,7 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
nsresult status = NS_OK;
aRequest->GetStatus(&status);
if (status == NS_ERROR_NO_CONTENT) {
mDocumentChannelBridge->DisconnectChildListeners(status, status);
mDocumentChannelBridge->DisconnectChildListeners(NS_ERROR_NO_CONTENT);
return NS_OK;
}
@ -968,15 +779,6 @@ DocumentLoadListener::OnDataAvailable(nsIRequest* aRequest,
NS_IMETHODIMP
DocumentLoadListener::OnAfterLastPart(nsresult aStatus) {
LOG(("DocumentLoadListener OnAfterLastPart [this=%p]", this));
if (!mInitiatedRedirectToRealChannel) {
// if we get here, and we haven't initiated a redirect to a real
// channel, then it means we never got OnStartRequest (maybe a problem?)
// and we retargeted everything.
LOG(("DocumentLoadListener Disconnecting child"));
DisconnectChildListeners(NS_BINDING_RETARGETED, NS_OK);
return NS_OK;
}
mStreamListenerFunctions.AppendElement(StreamListenerFunction{
VariantIndex<3>{}, OnAfterLastPartParams{aStatus}});
mIsFinished = true;

Просмотреть файл

@ -14,7 +14,6 @@
#include "mozilla/net/PDocumentChannelParent.h"
#include "mozilla/net/ParentChannelListener.h"
#include "mozilla/net/ADocumentChannelBridge.h"
#include "mozilla/dom/BrowserParent.h"
#include "nsIInterfaceRequestor.h"
#include "nsIObserver.h"
#include "nsIParentChannel.h"
@ -60,26 +59,20 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
public nsIProcessSwitchRequestor,
public nsIMultiPartChannelListener {
public:
explicit DocumentLoadListener(dom::BrowserParent* aBrowser,
explicit DocumentLoadListener(const dom::PBrowserOrId& aIframeEmbedding,
nsILoadContext* aLoadContext,
PBOverrideStatus aOverrideStatus,
ADocumentChannelBridge* aBridge);
// Creates the channel, and then calls AsyncOpen on it.
// Must be the same BrowserParent as was passed to the constructor, we
// expect Necko to pass it again so that we don't need a member var for
// it.
bool Open(dom::BrowserParent* aBrowser, nsDocShellLoadState* aLoadState,
class LoadInfo* aLoadInfo, const nsString* aInitiatorType,
nsLoadFlags aLoadFlags, uint32_t aLoadType, uint32_t aCacheKey,
bool aIsActive, bool aIsTopLevelDoc,
bool aHasNonEmptySandboxingFlags,
bool Open(nsDocShellLoadState* aLoadState, class LoadInfo* aLoadInfo,
const nsString* aInitiatorType, nsLoadFlags aLoadFlags,
uint32_t aLoadType, uint32_t aCacheKey, bool aIsActive,
bool aIsTopLevelDoc, bool aHasNonEmptySandboxingFlags,
const Maybe<ipc::URIParams>& aTopWindowURI,
const Maybe<ipc::PrincipalInfo>& aContentBlockingAllowListPrincipal,
const nsString& aCustomUserAgent, const uint64_t& aChannelId,
const TimeStamp& aAsyncOpenTime,
const Maybe<uint32_t>& aDocumentOpenFlags, bool aPluginsAllowed,
nsresult* aRv);
const TimeStamp& aAsyncOpenTime, nsresult* aRv);
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
@ -141,13 +134,6 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
// our reference to it.
void DocumentChannelBridgeDisconnected();
void DisconnectChildListeners(nsresult aStatus, nsresult aLoadGroupStatus) {
if (mDocumentChannelBridge) {
mDocumentChannelBridge->DisconnectChildListeners(aStatus,
aLoadGroupStatus);
}
}
base::ProcessId OtherPid() const {
if (mDocumentChannelBridge) {
return mDocumentChannelBridge->OtherPid();

Просмотреть файл

@ -405,11 +405,9 @@ struct DocumentChannelCreationArgs {
uint32_t loadFlags;
uint32_t loadType;
uint32_t cacheKey;
uint32_t? documentOpenFlags;
bool isActive;
bool isTopLevelDoc;
bool hasNonEmptySandboxingFlags;
bool pluginsAllowed;
};
struct DocumentChannelRedirect {

Просмотреть файл

@ -409,7 +409,7 @@ mozilla::ipc::IPCResult NeckoParent::RecvPFTPChannelConstructor(
already_AddRefed<PDocumentChannelParent>
NeckoParent::AllocPDocumentChannelParent(
PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized,
const PBrowserOrId& aBrowser, const SerializedLoadContext& aSerialized,
const DocumentChannelCreationArgs& args) {
nsCOMPtr<nsIPrincipal> requestingPrincipal =
GetRequestingPrincipal(Some(args.loadInfo()));
@ -422,21 +422,17 @@ NeckoParent::AllocPDocumentChannelParent(
}
PBOverrideStatus overrideStatus =
PBOverrideStatusFromLoadContext(aSerialized);
RefPtr<dom::BrowserParent> browser =
static_cast<dom::BrowserParent*>(aBrowser);
RefPtr<DocumentChannelParent> p =
new DocumentChannelParent(browser, loadContext, overrideStatus);
new DocumentChannelParent(aBrowser, loadContext, overrideStatus);
return p.forget();
}
mozilla::ipc::IPCResult NeckoParent::RecvPDocumentChannelConstructor(
PDocumentChannelParent* aActor, PBrowserParent* aBrowser,
PDocumentChannelParent* aActor, const PBrowserOrId& aBrowser,
const SerializedLoadContext& aSerialized,
const DocumentChannelCreationArgs& aArgs) {
DocumentChannelParent* p = static_cast<DocumentChannelParent*>(aActor);
RefPtr<dom::BrowserParent> browser =
static_cast<dom::BrowserParent*>(aBrowser);
if (!p->Init(browser, aArgs)) {
if (!p->Init(aArgs)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();

Просмотреть файл

@ -128,10 +128,10 @@ class NeckoParent : public PNeckoParent {
const uint16_t& port);
already_AddRefed<PDocumentChannelParent> AllocPDocumentChannelParent(
PBrowserParent* aBrowser, const SerializedLoadContext& aSerialized,
const PBrowserOrId& aBrowser, const SerializedLoadContext& aSerialized,
const DocumentChannelCreationArgs& args);
virtual mozilla::ipc::IPCResult RecvPDocumentChannelConstructor(
PDocumentChannelParent* aActor, PBrowserParent* aBrowser,
PDocumentChannelParent* aActor, const PBrowserOrId& aBrowser,
const SerializedLoadContext& aSerialized,
const DocumentChannelCreationArgs& aArgs) override;
bool DeallocPDocumentChannelParent(PDocumentChannelParent* channel);

Просмотреть файл

@ -45,11 +45,7 @@ child:
// As a consequence, it should cleanup the channel listeners and remove the
// request from the loadGroup.
// aStatus must be an error result.
// aLoadGroupReason is used as mStatus when we remove the child channel from
// the loadgroup (but aStatus is passed as the parameter to RemoveRequest).
// We do this so we can remove using NS_BINDING_RETARGETED, but still have the
// channel not be in an error state.
async DisconnectChildListeners(nsresult aStatus, nsresult aLoadGroupReason);
async DisconnectChildListeners(nsresult aStatus);
// Triggers replacing this DocumentChannel with a 'real' channel (like PHttpChannel),
// and notifies the listener via a redirect to the new channel.

Просмотреть файл

@ -88,7 +88,7 @@ parent:
async PDNSRequest(nsCString hostName, OriginAttributes originAttributes,
uint32_t flags);
async PDocumentChannel(PBrowser browser,
async PDocumentChannel(PBrowserOrId browser,
SerializedLoadContext loadContext,
DocumentChannelCreationArgs args);

Просмотреть файл

@ -98,10 +98,6 @@ class ParentChannelListener final : public nsIInterfaceRequestor,
NS_DEFINE_STATIC_IID_ACCESSOR(ParentChannelListener, PARENT_CHANNEL_LISTENER)
inline nsISupports* ToSupports(ParentChannelListener* aDoc) {
return static_cast<nsIInterfaceRequestor*>(aDoc);
}
} // namespace net
} // namespace mozilla

Просмотреть файл

@ -1217,12 +1217,6 @@ mozTXTToHTMLConv::AsyncConvertData(const char* aFromType, const char* aToType,
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
mozTXTToHTMLConv::GetConvertedType(const nsACString& aFromType,
nsACString& aToType) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
mozTXTToHTMLConv::OnDataAvailable(nsIRequest* request, nsIInputStream* inStr,
uint64_t sourceOffset, uint32_t count) {

Просмотреть файл

@ -70,12 +70,6 @@ nsFTPDirListingConv::AsyncConvertData(const char* aFromType,
return NS_OK;
}
NS_IMETHODIMP
nsFTPDirListingConv::GetConvertedType(const nsACString& aFromType,
nsACString& aToType) {
return NS_ERROR_NOT_IMPLEMENTED;
}
// nsIStreamListener implementation
NS_IMETHODIMP
nsFTPDirListingConv::OnDataAvailable(nsIRequest* request, nsIInputStream* inStr,

Просмотреть файл

@ -115,12 +115,6 @@ nsHTTPCompressConv::AsyncConvertData(const char* aFromType, const char* aToType,
return NS_OK;
}
NS_IMETHODIMP
nsHTTPCompressConv::GetConvertedType(const nsACString& aFromType,
nsACString& aToType) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsHTTPCompressConv::OnStartRequest(nsIRequest* request) {
LOG(("nsHttpCompresssConv %p onstart\n", this));

Просмотреть файл

@ -90,12 +90,6 @@ nsIndexedToHTML::AsyncConvertData(const char* aFromType, const char* aToType,
return Init(aListener);
}
NS_IMETHODIMP
nsIndexedToHTML::GetConvertedType(const nsACString& aFromType,
nsACString& aToType) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsIndexedToHTML::OnStartRequest(nsIRequest* request) {
nsCString buffer;

Просмотреть файл

@ -406,12 +406,6 @@ nsMultiMixedConv::AsyncConvertData(const char* aFromType, const char* aToType,
return NS_OK;
}
NS_IMETHODIMP
nsMultiMixedConv::GetConvertedType(const nsACString& aFromType,
nsACString& aToType) {
return NS_ERROR_NOT_IMPLEMENTED;
}
// nsIRequestObserver implementation
NS_IMETHODIMP
nsMultiMixedConv::OnStartRequest(nsIRequest* request) {

Просмотреть файл

@ -143,12 +143,6 @@ nsUnknownDecoder::AsyncConvertData(const char* aFromType, const char* aToType,
return (aListener) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsUnknownDecoder::GetConvertedType(const nsACString& aFromType,
nsACString& aToType) {
return NS_ERROR_NOT_IMPLEMENTED;
}
// ----
//
// nsIStreamListener methods...

Просмотреть файл

@ -93,15 +93,6 @@ interface nsIStreamConverter : nsIStreamListener {
in string aToType,
in nsIStreamListener aListener,
in nsISupports aCtxt);
/**
* Returns the content type that the stream listener passed to asyncConvertData will
* see on the channel if the conversion is being done from aFromType to * /*.
*
* @throws if the converter does not support conversion to * /* or if it doesn't know
* the type in advance.
*/
ACString getConvertedType(in ACString aFromType);
};
%{C++

Просмотреть файл

@ -34,14 +34,6 @@ interface nsIStreamConverterService : nsISupports {
*/
boolean canConvert(in string aFromType, in string aToType);
/**
* Returns the content type that will be returned from a converter
* created with aFromType and * /*.
* Can fail if no converters support this conversion, or if the
* output type isn't known in advance.
*/
ACString convertedType(in ACString aFromType);
/**
* <b>SYNCHRONOUS VERSION</b>
* Converts a stream of one type, to a stream of another type.

Просмотреть файл

@ -352,25 +352,6 @@ nsStreamConverterService::CanConvert(const char* aFromType, const char* aToType,
return NS_OK;
}
NS_IMETHODIMP
nsStreamConverterService::ConvertedType(const nsACString& aFromType,
nsACString& aOutToType) {
// first determine whether we can even handle this conversion
// build a CONTRACTID
nsAutoCString contractID;
contractID.AssignLiteral(NS_ISTREAMCONVERTER_KEY "?from=");
contractID.Append(aFromType);
contractID.AppendLiteral("&to=*/*");
const char* cContractID = contractID.get();
nsresult rv;
nsCOMPtr<nsIStreamConverter> converter(do_CreateInstance(cContractID, &rv));
if (NS_SUCCEEDED(rv)) {
return converter->GetConvertedType(aFromType, aOutToType);
}
return rv;
}
NS_IMETHODIMP
nsStreamConverterService::Convert(nsIInputStream* aFromStream,
const char* aFromType, const char* aToType,

Просмотреть файл

@ -1,3 +1,4 @@
[a-download-click-404.html]
[Do not navigate to 404 for anchor with download]
if (os == "android"): FAIL
expected: FAIL

Просмотреть файл

@ -24,7 +24,6 @@
#include "nsIDocShell.h"
#include "nsIThreadRetargetableStreamListener.h"
#include "nsIChildChannel.h"
#include "nsExternalHelperAppService.h"
#include "nsString.h"
#include "nsThreadUtils.h"
@ -53,6 +52,9 @@ mozilla::LazyLogModule nsURILoader::mLog("URILoader");
MOZ_LOG(nsURILoader::mLog, mozilla::LogLevel::Error, args)
#define LOG_ENABLED() MOZ_LOG_TEST(nsURILoader::mLog, mozilla::LogLevel::Debug)
#define NS_PREF_DISABLE_BACKGROUND_HANDLING \
"security.exthelperapp.disable_background_handling"
static uint32_t sConvertDataLimit = 20;
static bool InitPreferences() {
@ -61,6 +63,104 @@ static bool InitPreferences() {
return true;
}
/**
* The nsDocumentOpenInfo contains the state required when a single
* document is being opened in order to discover the content type...
* Each instance remains alive until its target URL has been loaded
* (or aborted).
*/
class nsDocumentOpenInfo final : public nsIStreamListener,
public nsIThreadRetargetableStreamListener {
public:
// Real constructor
// aFlags is a combination of the flags on nsIURILoader
nsDocumentOpenInfo(nsIInterfaceRequestor* aWindowContext, uint32_t aFlags,
nsURILoader* aURILoader);
NS_DECL_THREADSAFE_ISUPPORTS
/**
* Prepares this object for receiving data. The stream
* listener methods of this class must not be called before calling this
* method.
*/
nsresult Prepare();
// Call this (from OnStartRequest) to attempt to find an nsIStreamListener to
// take the data off our hands.
nsresult DispatchContent(nsIRequest* request, nsISupports* aCtxt);
// Call this if we need to insert a stream converter from aSrcContentType to
// aOutContentType into the StreamListener chain. DO NOT call it if the two
// types are the same, since no conversion is needed in that case.
nsresult ConvertData(nsIRequest* request, nsIURIContentListener* aListener,
const nsACString& aSrcContentType,
const nsACString& aOutContentType);
/**
* Function to attempt to use aListener to handle the load. If
* true is returned, nothing else needs to be done; if false
* is returned, then a different way of handling the load should be
* tried.
*/
bool TryContentListener(nsIURIContentListener* aListener,
nsIChannel* aChannel);
// nsIRequestObserver methods:
NS_DECL_NSIREQUESTOBSERVER
// nsIStreamListener methods:
NS_DECL_NSISTREAMLISTENER
// nsIThreadRetargetableStreamListener
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
protected:
~nsDocumentOpenInfo();
protected:
/**
* The first content listener to try dispatching data to. Typically
* the listener associated with the entity that originated the load.
*/
nsCOMPtr<nsIURIContentListener> m_contentListener;
/**
* The stream listener to forward nsIStreamListener notifications
* to. This is set once the load is dispatched.
*/
nsCOMPtr<nsIStreamListener> m_targetStreamListener;
/**
* A pointer to the entity that originated the load. We depend on getting
* things like nsIURIContentListeners, nsIDOMWindows, etc off of it.
*/
nsCOMPtr<nsIInterfaceRequestor> m_originalContext;
/**
* IS_CONTENT_PREFERRED is used for the boolean to pass to CanHandleContent
* (also determines whether we use CanHandleContent or IsPreferred).
* DONT_RETARGET means that we will only try m_originalContext, no other
* listeners.
*/
uint32_t mFlags;
/**
* The type of the data we will be trying to dispatch.
*/
nsCString mContentType;
/**
* Reference to the URILoader service so we can access its list of
* nsIURIContentListeners.
*/
RefPtr<nsURILoader> mURILoader;
/**
* Limit of data conversion depth to prevent infinite conversion loops
*/
uint32_t mDataConversionDepthLimit;
};
NS_IMPL_ADDREF(nsDocumentOpenInfo)
NS_IMPL_RELEASE(nsDocumentOpenInfo)
@ -78,14 +178,6 @@ nsDocumentOpenInfo::nsDocumentOpenInfo(nsIInterfaceRequestor* aWindowContext,
mURILoader(aURILoader),
mDataConversionDepthLimit(sConvertDataLimit) {}
nsDocumentOpenInfo::nsDocumentOpenInfo(uint32_t aFlags,
bool aAllowListenerConversions)
: m_originalContext(nullptr),
mFlags(aFlags),
mURILoader(nullptr),
mDataConversionDepthLimit(sConvertDataLimit),
mAllowListenerConversions(aAllowListenerConversions) {}
nsDocumentOpenInfo::~nsDocumentOpenInfo() {}
nsresult nsDocumentOpenInfo::Prepare() {
@ -178,8 +270,8 @@ NS_IMETHODIMP nsDocumentOpenInfo::OnStartRequest(nsIRequest* request) {
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(status)) {
LOG_ERROR((" Request failed, status: 0x%08" PRIX32,
static_cast<uint32_t>(status)));
LOG_ERROR(
(" Request failed, status: 0x%08" PRIX32, static_cast<uint32_t>(rv)));
//
// The transaction has already reported an error - so it will be torn
@ -251,7 +343,6 @@ NS_IMETHODIMP nsDocumentOpenInfo::OnStopRequest(nsIRequest* request,
mContentType.Truncate();
listener->OnStopRequest(request, aStatus);
}
mUsedContentHandler = false;
// Remember...
// In the case of multiplexed streams (such as multipart/x-mixed-replace)
@ -310,7 +401,7 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest* request,
// First step: See whether m_contentListener wants to handle this
// content type.
//
if (TryDefaultContentListener(aChannel)) {
if (m_contentListener && TryContentListener(m_contentListener, aChannel)) {
LOG((" Success! Our default listener likes this type"));
// All done here
return NS_OK;
@ -323,7 +414,7 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest* request,
// Second step: See whether some other registered listener wants
// to handle this content type.
//
int32_t count = mURILoader ? mURILoader->m_listeners.Count() : 0;
int32_t count = mURILoader->m_listeners.Count();
nsCOMPtr<nsIURIContentListener> listener;
for (int32_t i = 0; i < count; i++) {
listener = do_QueryReferent(mURILoader->m_listeners[i]);
@ -374,10 +465,6 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest* request,
do_CreateInstance(handlerContractID.get());
if (contentHandler) {
LOG((" Content handler found"));
// Note that m_originalContext can be nullptr when running this in
// the parent process on behalf on a docshell in the content process,
// and in that case we only support content handlers that don't need
// the context.
rv = contentHandler->HandleContent(mContentType.get(),
m_originalContext, request);
// XXXbz returning an error code to represent handling the
@ -390,7 +477,6 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest* request,
request->Cancel(rv);
} else {
LOG((" Content handler taking over load"));
mUsedContentHandler = true;
}
return rv;
@ -412,7 +498,13 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest* request,
// XXXbz have to be careful here; may end up in some sort of bizarre
// infinite decoding loop.
if (mContentType != anyType) {
if (TryStreamConversion(aChannel)) {
rv = ConvertData(request, m_contentListener, mContentType, anyType);
if (NS_FAILED(rv)) {
m_targetStreamListener = nullptr;
} else if (m_targetStreamListener) {
// We found a converter for this MIME type. We'll just pump data into
// it and let the downstream nsDocumentOpenInfo handle things.
LOG((" Converter taking over now"));
return NS_OK;
}
}
@ -447,6 +539,36 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest* request,
// the helper app service.
//
//
// Optionally, we may want to disable background handling by the external
// helper application service.
//
if (mozilla::Preferences::GetBool(NS_PREF_DISABLE_BACKGROUND_HANDLING,
false)) {
// First, we will ensure that the parent docshell is in an active
// state as we will disallow all external application handling unless it is
// in the foreground.
nsCOMPtr<nsIDocShell> docShell(do_GetInterface(m_originalContext));
if (!docShell) {
// If we can't perform our security check we definitely don't want to go
// any further!
LOG(
("Failed to get DocShell to ensure it is active before anding off to "
"helper app service. Aborting."));
return NS_ERROR_FAILURE;
}
// Ensure the DocShell is active before continuing.
bool isActive = false;
docShell->GetIsActive(&isActive);
if (!isActive) {
LOG(
(" Check for active DocShell returned false. Aborting hand off to "
"helper app service."));
return NS_ERROR_DOM_SECURITY_ERR;
}
}
nsCOMPtr<nsIExternalHelperAppService> helperAppService =
do_GetService(NS_EXTERNALHELPERAPPSERVICE_CONTRACTID, &rv);
if (helperAppService) {
@ -464,7 +586,10 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest* request,
aChannel->SetContentType(NS_LITERAL_CSTRING(APPLICATION_GUESS_FROM_EXT));
}
if (!TryExternalHelperApp(helperAppService, aChannel)) {
rv = helperAppService->DoContent(mContentType, request, m_originalContext,
false, nullptr,
getter_AddRefs(m_targetStreamListener));
if (NS_FAILED(rv)) {
request->SetLoadFlags(loadFlags);
m_targetStreamListener = nullptr;
}
@ -476,14 +601,6 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest* request,
return rv;
}
bool nsDocumentOpenInfo::TryExternalHelperApp(
nsIExternalHelperAppService* aHelperAppService, nsIChannel* aChannel) {
nsresult rv = aHelperAppService->DoContent(
mContentType, aChannel, m_originalContext, false, nullptr,
getter_AddRefs(m_targetStreamListener));
return NS_SUCCEEDED(rv);
}
nsresult nsDocumentOpenInfo::ConvertData(nsIRequest* request,
nsIURIContentListener* aListener,
const nsACString& aSrcContentType,
@ -493,10 +610,9 @@ nsresult nsDocumentOpenInfo::ConvertData(nsIRequest* request,
PromiseFlatCString(aOutContentType).get()));
if (mDataConversionDepthLimit == 0) {
LOG(
("[0x%p] nsDocumentOpenInfo::ConvertData - reached the recursion "
"limit!",
this));
LOG((
"[0x%p] nsDocumentOpenInfo::ConvertData - reached the recursion limit!",
this));
// This will fall back to external helper app handling.
return NS_ERROR_ABORT;
}
@ -520,15 +636,16 @@ nsresult nsDocumentOpenInfo::ConvertData(nsIRequest* request,
// stream is split up into multiple destination streams. This
// intermediate instance is used to target these "decoded" streams...
//
RefPtr<nsDocumentOpenInfo> nextLink = Clone();
RefPtr<nsDocumentOpenInfo> nextLink =
new nsDocumentOpenInfo(m_originalContext, mFlags, mURILoader);
LOG((" Downstream DocumentOpenInfo would be: 0x%p", nextLink.get()));
// Decrease the conversion recursion limit by one to prevent infinite loops.
nextLink->mDataConversionDepthLimit = mDataConversionDepthLimit - 1;
// Make sure nextLink starts with the contentListener that said it wanted
// the results of this decode.
// Make sure nextLink starts with the contentListener that said it wanted the
// results of this decode.
nextLink->m_contentListener = aListener;
// Also make sure it has to look for a stream listener to pump data into.
nextLink->m_targetStreamListener = nullptr;
@ -550,20 +667,6 @@ nsresult nsDocumentOpenInfo::ConvertData(nsIRequest* request,
getter_AddRefs(m_targetStreamListener));
}
bool nsDocumentOpenInfo::TryStreamConversion(nsIChannel* aChannel) {
NS_NAMED_LITERAL_CSTRING(anyType, "*/*");
nsresult rv = ConvertData(aChannel, m_contentListener, mContentType, anyType);
if (NS_FAILED(rv)) {
m_targetStreamListener = nullptr;
} else if (m_targetStreamListener) {
// We found a converter for this MIME type. We'll just pump data into
// it and let the downstream nsDocumentOpenInfo handle things.
LOG((" Converter taking over now"));
return true;
}
return false;
}
bool nsDocumentOpenInfo::TryContentListener(nsIURIContentListener* aListener,
nsIChannel* aChannel) {
LOG(("[0x%p] nsDocumentOpenInfo::TryContentListener; mFlags = 0x%x", this,
@ -591,10 +694,7 @@ bool nsDocumentOpenInfo::TryContentListener(nsIURIContentListener* aListener,
if (!typeToUse.IsEmpty() && typeToUse != mContentType) {
// Need to do a conversion here.
nsresult rv = NS_ERROR_NOT_AVAILABLE;
if (mAllowListenerConversions) {
rv = ConvertData(aChannel, aListener, mContentType, typeToUse);
}
nsresult rv = ConvertData(aChannel, aListener, mContentType, typeToUse);
if (NS_FAILED(rv)) {
// No conversion path -- we don't want this listener, if we got one
@ -656,13 +756,6 @@ bool nsDocumentOpenInfo::TryContentListener(nsIURIContentListener* aListener,
return true;
}
bool nsDocumentOpenInfo::TryDefaultContentListener(nsIChannel* aChannel) {
if (m_contentListener) {
return TryContentListener(m_contentListener, aChannel);
}
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Implementation of nsURILoader
///////////////////////////////////////////////////////////////////////////////////////////////
@ -718,9 +811,8 @@ NS_IMETHODIMP nsURILoader::OpenURI(nsIChannel* channel, uint32_t aFlags,
if (NS_SUCCEEDED(rv)) {
if (aFlags & nsIURILoader::REDIRECTED_CHANNEL) {
// Our channel was redirected from another process, so doesn't need to
// be opened again. However, it does need its listener hooked up
// correctly.
// Our channel was redirected from another process, so doesn't need to be
// opened again. However, it does need its listener hooked up correctly.
nsCOMPtr<nsIChildChannel> childChannel = do_QueryInterface(channel);
MOZ_ASSERT(childChannel);
if (!childChannel) {
@ -765,7 +857,7 @@ nsresult nsURILoader::OpenChannel(nsIChannel* channel, uint32_t aFlags,
LOG(("nsURILoader::OpenChannel for %s", spec.get()));
}
// Let the window context's uriListener know that the open is starting. This
// Let the window context's uriListener know that the open is starting. This
// gives that window a chance to abort the load process.
nsCOMPtr<nsIURIContentListener> winContextListener(
do_GetInterface(aWindowContext));

Просмотреть файл

@ -15,9 +15,6 @@
#include "nsString.h"
#include "nsIWeakReference.h"
#include "mozilla/Attributes.h"
#include "nsIStreamListener.h"
#include "nsIThreadRetargetableStreamListener.h"
#include "nsIExternalHelperAppService.h"
#include "mozilla/Logging.h"
@ -57,163 +54,4 @@ class nsURILoader final : public nsIURILoader {
friend class nsDocumentOpenInfo;
};
/**
* The nsDocumentOpenInfo contains the state required when a single
* document is being opened in order to discover the content type...
* Each instance remains alive until its target URL has been loaded
* (or aborted).
*/
class nsDocumentOpenInfo : public nsIStreamListener,
public nsIThreadRetargetableStreamListener {
public:
// Real constructor
// aFlags is a combination of the flags on nsIURILoader
nsDocumentOpenInfo(nsIInterfaceRequestor* aWindowContext, uint32_t aFlags,
nsURILoader* aURILoader);
nsDocumentOpenInfo(uint32_t aFlags, bool aAllowListenerConversions);
NS_DECL_THREADSAFE_ISUPPORTS
/**
* Prepares this object for receiving data. The stream
* listener methods of this class must not be called before calling this
* method.
*/
nsresult Prepare();
// Call this (from OnStartRequest) to attempt to find an nsIStreamListener to
// take the data off our hands.
nsresult DispatchContent(nsIRequest* request, nsISupports* aCtxt);
// Call this if we need to insert a stream converter from aSrcContentType to
// aOutContentType into the StreamListener chain. DO NOT call it if the two
// types are the same, since no conversion is needed in that case.
nsresult ConvertData(nsIRequest* request, nsIURIContentListener* aListener,
const nsACString& aSrcContentType,
const nsACString& aOutContentType);
/**
* Function to attempt to use aListener to handle the load. If
* true is returned, nothing else needs to be done; if false
* is returned, then a different way of handling the load should be
* tried.
*/
bool TryContentListener(nsIURIContentListener* aListener,
nsIChannel* aChannel);
/**
* Virtual helper functions for content that we expect to be
* overriden when running in the parent process on behalf of
* a content process docshell.
* We also expect nsIStreamListener functions to be overriden
* to add functionality.
*/
/**
* Attempt to create a steam converter converting from the
* current mContentType into something else.
* Sets m_targetStreamListener if it succeeds.
*/
virtual bool TryStreamConversion(nsIChannel* aChannel);
/**
* Attempt to use the default content listener as our stream
* listener.
* Sets m_targetStreamListener if it succeeds.
*/
virtual bool TryDefaultContentListener(nsIChannel* aChannel);
/**
* Attempt to pass aChannel onto the external helper app service.
* Sets m_targetStreamListener if it succeeds.
*/
virtual bool TryExternalHelperApp(
nsIExternalHelperAppService* aHelperAppService, nsIChannel* aChannel);
/**
* Create another nsDocumentOpenInfo like this one, so that we can chain
* them together when we use a stream converter and don't know what the
* converted content type is until the converter outputs OnStartRequest.
*/
virtual nsDocumentOpenInfo* Clone() {
return new nsDocumentOpenInfo(m_originalContext, mFlags, mURILoader);
}
// nsIRequestObserver methods:
NS_DECL_NSIREQUESTOBSERVER
// nsIStreamListener methods:
NS_DECL_NSISTREAMLISTENER
// nsIThreadRetargetableStreamListener
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
protected:
virtual ~nsDocumentOpenInfo();
protected:
/**
* The first content listener to try dispatching data to. Typically
* the listener associated with the entity that originated the load.
* This can be nullptr when running in the parent process for a content
* process docshell.
*/
nsCOMPtr<nsIURIContentListener> m_contentListener;
/**
* The stream listener to forward nsIStreamListener notifications
* to. This is set once the load is dispatched.
*/
nsCOMPtr<nsIStreamListener> m_targetStreamListener;
/**
* A pointer to the entity that originated the load. We depend on getting
* things like nsIURIContentListeners, nsIDOMWindows, etc off of it.
* This can be nullptr when running in the parent process for a content
* process docshell.
*/
nsCOMPtr<nsIInterfaceRequestor> m_originalContext;
/**
* IS_CONTENT_PREFERRED is used for the boolean to pass to CanHandleContent
* (also determines whether we use CanHandleContent or IsPreferred).
* DONT_RETARGET means that we will only try m_originalContext, no other
* listeners.
*/
uint32_t mFlags;
/**
* The type of the data we will be trying to dispatch.
*/
nsCString mContentType;
/**
* Reference to the URILoader service so we can access its list of
* nsIURIContentListeners.
* This can be nullptr when running in the parent process for a content
* process docshell.
*/
RefPtr<nsURILoader> mURILoader;
/**
* Limit of data conversion depth to prevent infinite conversion loops
*/
uint32_t mDataConversionDepthLimit;
/**
* Set to true if OnStartRequest handles the content using an
* nsIContentHandler, and the content is consumed despite
* m_targetStreamListener being nullptr.
*/
bool mUsedContentHandler = false;
/**
* True if we allow nsIURIContentListeners to return a requested
* input typeToUse, and attempt to create a matching stream converter.
* This is false when running in the parent process for a content process
* docshell
*/
bool mAllowListenerConversions = true;
};
#endif /* nsURILoader_h__ */