зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1650089 - Part 1: Add a remoteTypeOverride option for about:blank loads triggered by chrome, r=annyG,kmag
After the changes in this bug, about:blank loads triggered by chrome will finish in a "web" content process, as they have an untrusted null principal without a precursor. In a few places throughout the codebase, however, we perform about:blank loads with the explicit expectation that they do not change processes. This new remoteTypeOverride option allows the intended final process to be explicitly specified in this situation. For security & simplicity reasons, this new attribute is limited to only be usable on system-principal triggered loads of about:blank in toplevel browsing contexts. Differential Revision: https://phabricator.services.mozilla.com/D120671
This commit is contained in:
Родитель
59692ca913
Коммит
a50cefe2cf
|
@ -1493,8 +1493,14 @@ function _loadURI(browser, uri, params = {}) {
|
|||
uri = "about:blank";
|
||||
}
|
||||
|
||||
let { triggeringPrincipal, referrerInfo, postData, userContextId, csp } =
|
||||
params || {};
|
||||
let {
|
||||
triggeringPrincipal,
|
||||
referrerInfo,
|
||||
postData,
|
||||
userContextId,
|
||||
csp,
|
||||
remoteTypeOverride,
|
||||
} = params || {};
|
||||
let loadFlags =
|
||||
params.loadFlags || params.flags || Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
||||
let hasValidUserGestureActivation =
|
||||
|
@ -1539,6 +1545,7 @@ function _loadURI(browser, uri, params = {}) {
|
|||
referrerInfo,
|
||||
postData,
|
||||
hasValidUserGestureActivation,
|
||||
remoteTypeOverride,
|
||||
};
|
||||
try {
|
||||
browser.webNavigation.loadURI(uri, loadURIOptions);
|
||||
|
|
|
@ -218,6 +218,10 @@ ContentRestoreInternal.prototype = {
|
|||
let loadURIOptions = {
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
loadFlags: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY,
|
||||
// Specify an override to force the load to finish in the current
|
||||
// process, as tests rely on this behaviour for non-fission session
|
||||
// restore.
|
||||
remoteTypeOverride: Services.appinfo.remoteType,
|
||||
};
|
||||
webNavigation.loadURI("about:blank", loadURIOptions);
|
||||
}
|
||||
|
|
|
@ -3649,6 +3649,7 @@ var SessionStoreInternal = {
|
|||
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({
|
||||
userContextId: aTab.userContextId,
|
||||
}),
|
||||
remoteTypeOverride: E10SUtils.NOT_REMOTE,
|
||||
});
|
||||
|
||||
let data = TabState.collect(aTab, TAB_CUSTOM_VALUES.get(aTab));
|
||||
|
|
|
@ -88,6 +88,7 @@ nsDocShellLoadState::nsDocShellLoadState(
|
|||
aLoadState.loadingSessionHistoryInfo().ref());
|
||||
}
|
||||
mUnstrippedURI = aLoadState.UnstrippedURI();
|
||||
mRemoteTypeOverride = aLoadState.RemoteTypeOverride();
|
||||
}
|
||||
|
||||
nsDocShellLoadState::nsDocShellLoadState(const nsDocShellLoadState& aOther)
|
||||
|
@ -133,7 +134,8 @@ nsDocShellLoadState::nsDocShellLoadState(const nsDocShellLoadState& aOther)
|
|||
mLoadIdentifier(aOther.mLoadIdentifier),
|
||||
mChannelInitialized(aOther.mChannelInitialized),
|
||||
mIsMetaRefresh(aOther.mIsMetaRefresh),
|
||||
mUnstrippedURI(aOther.mUnstrippedURI) {
|
||||
mUnstrippedURI(aOther.mUnstrippedURI),
|
||||
mRemoteTypeOverride(aOther.mRemoteTypeOverride) {
|
||||
if (aOther.mLoadingSessionHistoryInfo) {
|
||||
mLoadingSessionHistoryInfo = MakeUnique<LoadingSessionHistoryInfo>(
|
||||
*aOther.mLoadingSessionHistoryInfo);
|
||||
|
@ -369,6 +371,11 @@ nsresult nsDocShellLoadState::CreateFromLoadURIOptions(
|
|||
nsDocShell::MaybeNotifyKeywordSearchLoading(searchProvider, keyword);
|
||||
}
|
||||
|
||||
if (aLoadURIOptions.mRemoteTypeOverride.WasPassed()) {
|
||||
loadState->SetRemoteTypeOverride(
|
||||
aLoadURIOptions.mRemoteTypeOverride.Value());
|
||||
}
|
||||
|
||||
loadState.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1046,6 +1053,7 @@ DocShellLoadStateInit nsDocShellLoadState::Serialize() {
|
|||
loadState.loadingSessionHistoryInfo().emplace(*mLoadingSessionHistoryInfo);
|
||||
}
|
||||
loadState.UnstrippedURI() = mUnstrippedURI;
|
||||
loadState.RemoteTypeOverride() = mRemoteTypeOverride;
|
||||
return loadState;
|
||||
}
|
||||
|
||||
|
|
|
@ -304,6 +304,14 @@ class nsDocShellLoadState final {
|
|||
|
||||
bool IsMetaRefresh() const { return mIsMetaRefresh; }
|
||||
|
||||
const mozilla::Maybe<nsCString>& GetRemoteTypeOverride() const {
|
||||
return mRemoteTypeOverride;
|
||||
}
|
||||
|
||||
void SetRemoteTypeOverride(const nsCString& aRemoteTypeOverride) {
|
||||
mRemoteTypeOverride = mozilla::Some(aRemoteTypeOverride);
|
||||
}
|
||||
|
||||
// When loading a document through nsDocShell::LoadURI(), a special set of
|
||||
// flags needs to be set based on other values in nsDocShellLoadState. This
|
||||
// function calculates those flags, before the LoadState is passed to
|
||||
|
@ -524,6 +532,9 @@ class nsDocShellLoadState final {
|
|||
// The original URI before query stripping happened. If it's present, it shows
|
||||
// the query stripping happened. Otherwise, it will be a nullptr.
|
||||
nsCOMPtr<nsIURI> mUnstrippedURI;
|
||||
|
||||
// If set, the remote type which the load should be completed within.
|
||||
mozilla::Maybe<nsCString> mRemoteTypeOverride;
|
||||
};
|
||||
|
||||
#endif /* nsDocShellLoadState_h__ */
|
||||
|
|
|
@ -719,6 +719,16 @@ nsresult nsFrameLoader::ReallyStartLoadingInternal() {
|
|||
loadState->SetLoadFlags(flags);
|
||||
|
||||
loadState->SetFirstParty(false);
|
||||
|
||||
// If we're loading the default about:blank document in a <browser> element,
|
||||
// prevent the load from causing a process switch by explicitly overriding
|
||||
// remote type selection.
|
||||
if (mPendingBrowsingContext->IsTopContent() &&
|
||||
mOwnerContent->IsXULElement(nsGkAtoms::browser) &&
|
||||
NS_IsAboutBlank(mURIToLoad) &&
|
||||
loadState->TriggeringPrincipal()->IsSystemPrincipal()) {
|
||||
loadState->SetRemoteTypeOverride(mRemoteType);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsRemoteFrame()) {
|
||||
|
|
|
@ -303,6 +303,8 @@ struct DocShellLoadStateInit
|
|||
bool IsMetaRefresh;
|
||||
|
||||
nsIURI UnstrippedURI;
|
||||
|
||||
nsCString? RemoteTypeOverride;
|
||||
};
|
||||
|
||||
struct TimedChannelInfo
|
||||
|
|
|
@ -79,4 +79,14 @@ dictionary LoadURIOptions {
|
|||
* when initiating the load.
|
||||
*/
|
||||
long cancelContentJSEpoch = 0;
|
||||
|
||||
/**
|
||||
* If this is passed, it will control which remote type is used to finish this
|
||||
* load. Ignored for non-`about:` loads.
|
||||
*
|
||||
* NOTE: This is _NOT_ defaulted to `null`, as `null` is the value for
|
||||
* `NOT_REMOTE_TYPE`, and we need to determine the difference between no
|
||||
* `remoteTypeOverride` and a `remoteTypeOverride` of `NOT_REMOTE_TYPE`.
|
||||
*/
|
||||
UTF8String? remoteTypeOverride;
|
||||
};
|
||||
|
|
|
@ -539,6 +539,21 @@ auto DocumentLoadListener::Open(nsDocShellLoadState* aLoadState,
|
|||
}
|
||||
}
|
||||
|
||||
if (aLoadState->GetRemoteTypeOverride()) {
|
||||
if (!mIsDocumentLoad || !NS_IsAboutBlank(aLoadState->URI()) ||
|
||||
!loadingContext->IsTopContent()) {
|
||||
LOG(
|
||||
("DocumentLoadListener::Open with invalid remoteTypeOverride "
|
||||
"[this=%p]",
|
||||
this));
|
||||
*aRv = NS_ERROR_DOM_SECURITY_ERR;
|
||||
mParentChannelListener = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mRemoteTypeOverride = aLoadState->GetRemoteTypeOverride();
|
||||
}
|
||||
|
||||
if (!nsDocShell::CreateAndConfigureRealChannelForLoadState(
|
||||
loadingContext, aLoadState, aLoadInfo, mParentChannelListener,
|
||||
nullptr, attrs, aLoadFlags, aCacheKey, *aRv,
|
||||
|
@ -1574,6 +1589,11 @@ bool DocumentLoadListener::MaybeTriggerProcessSwitch(
|
|||
nsAutoCString preferredRemoteType(currentRemoteType);
|
||||
RemotenessChangeOptions options;
|
||||
|
||||
// If there is a remote type override, default to it.
|
||||
if (mRemoteTypeOverride) {
|
||||
preferredRemoteType = *mRemoteTypeOverride;
|
||||
}
|
||||
|
||||
// Update the preferred final process for our load based on the
|
||||
// Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers.
|
||||
{
|
||||
|
@ -2520,6 +2540,10 @@ DocumentLoadListener::AsyncOnChannelRedirect(
|
|||
// the new URI and set these again.
|
||||
mIParentChannelFunctions.Clear();
|
||||
|
||||
// If we had a remote type override, ensure it's been cleared after a
|
||||
// redirect, as it can't apply anymore.
|
||||
mRemoteTypeOverride.reset();
|
||||
|
||||
#ifdef ANDROID
|
||||
nsCOMPtr<nsIURI> uriBeingLoaded =
|
||||
AntiTrackingUtils::MaybeGetDocumentURIBeingLoaded(mChannel);
|
||||
|
|
|
@ -544,6 +544,8 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
|
||||
bool mSupportsRedirectToRealChannel = true;
|
||||
|
||||
Maybe<nsCString> mRemoteTypeOverride;
|
||||
|
||||
// The process id of the content process that we are being called from
|
||||
// or 0 initiated from a parent process load.
|
||||
base::ProcessId mOtherPid = 0;
|
||||
|
|
|
@ -814,6 +814,7 @@
|
|||
postData,
|
||||
headers,
|
||||
csp,
|
||||
remoteTypeOverride,
|
||||
} = aParams;
|
||||
let loadFlags =
|
||||
aParams.loadFlags ||
|
||||
|
@ -826,6 +827,7 @@
|
|||
loadFlags,
|
||||
postData,
|
||||
headers,
|
||||
remoteTypeOverride,
|
||||
};
|
||||
this._wrapURIChangeCall(() =>
|
||||
this.webNavigation.loadURI(aURI, loadURIOptions)
|
||||
|
|
Загрузка…
Ссылка в новой задаче