From 47421837bf1fa8b7521be5c9e9891e00680c2301 Mon Sep 17 00:00:00 2001 From: Bob Owen Date: Thu, 18 May 2017 12:08:56 +0100 Subject: [PATCH] Bug 1351358 Part 2: Limit the http pages that will load in the file content process with allowLinkedWebInFileUriProcess pref. r=Gijs, r=mystor This change means that any related http pages driven through content (window.open, links, etc.) will continue to be loaded in the file content process. Same-origin loads via the UI will also remain in the file content process. Cross-origin loads via the UI will cause a process switch. History navigation will stay in the process, if it was originally loaded in that process. --- browser/base/content/browser.js | 4 +- browser/base/content/tabbrowser.xml | 1 + .../components/sessionstore/SessionStore.jsm | 65 ++++++++++--------- browser/modules/E10SUtils.jsm | 46 +++++++++++-- 4 files changed, 76 insertions(+), 40 deletions(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index fb05b42ff935..00d854c3eed9 100755 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -1017,7 +1017,8 @@ function _loadURIWithFlags(browser, uri, params) { let currentRemoteType = browser.remoteType; let requiredRemoteType = - E10SUtils.getRemoteTypeForURI(uri, gMultiProcessBrowser, currentRemoteType); + E10SUtils.getRemoteTypeForURI(uri, gMultiProcessBrowser, currentRemoteType, + browser.currentURI); let mustChangeProcess = requiredRemoteType != currentRemoteType; // !requiredRemoteType means we're loading in the parent/this process. @@ -1052,6 +1053,7 @@ function _loadURIWithFlags(browser, uri, params) { flags, referrer: referrer ? referrer.spec : null, referrerPolicy, + remoteType: requiredRemoteType, postData } diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 63a49afe1b85..e5278d47c6c8 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -1854,6 +1854,7 @@ E10SUtils.getRemoteTypeForURI(aURL, gMultiProcessBrowser, preferredRemoteType, + aBrowser.currentURI, aOptions.freshProcess); // If this URL can't load in the current browser then flip it to the diff --git a/browser/components/sessionstore/SessionStore.jsm b/browser/components/sessionstore/SessionStore.jsm index c53f1f4bc3ee..eaee455af04f 100644 --- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -2888,6 +2888,7 @@ var SessionStoreInternal = { // whether or not a historyIndex is passed in. Thus, we extract it from // the loadArguments. reloadInFreshProcess: !!recentLoadArguments.reloadInFreshProcess, + remoteType: recentLoadArguments.remoteType, // Make sure that SessionStore knows that this restoration is due // to a navigation, as opposed to us restoring a closed window or tab. restoreContentReason: RESTORE_TAB_CONTENT_REASON.NAVIGATE_AND_RESTORE, @@ -3536,18 +3537,14 @@ var SessionStoreInternal = { NS_ASSERT(!tab.linkedBrowser.__SS_restoreState, "must reset tab before calling restoreTab()"); - let restoreImmediately = options.restoreImmediately; let loadArguments = options.loadArguments; let browser = tab.linkedBrowser; let window = tab.ownerGlobal; let tabbrowser = window.gBrowser; let forceOnDemand = options.forceOnDemand; - let reloadInFreshProcess = options.reloadInFreshProcess; - let restoreContentReason = options.restoreContentReason; - let willRestoreImmediately = restoreImmediately || - tabbrowser.selectedBrowser == browser || - loadArguments; + let willRestoreImmediately = options.restoreImmediately || + tabbrowser.selectedBrowser == browser; let isBrowserInserted = browser.isConnected; @@ -3666,8 +3663,7 @@ var SessionStoreInternal = { // This could cause us to ignore MAX_CONCURRENT_TAB_RESTORES a bit, but // it ensures each window will have its selected tab loaded. if (willRestoreImmediately) { - this.restoreTabContent(tab, loadArguments, reloadInFreshProcess, - restoreContentReason); + this.restoreTabContent(tab, options); } else if (!forceOnDemand) { TabRestoreQueue.add(tab); this.restoreNextTab(); @@ -3709,18 +3705,12 @@ var SessionStoreInternal = { * * @param aTab * the tab to restore - * @param aLoadArguments - * optional load arguments used for loadURI() - * @param aReloadInFreshProcess - * true if we want to reload into a fresh process - * @param aReason - * The reason for why this tab content is being restored. - * Should be one of the values within RESTORE_TAB_CONTENT_REASON. - * Defaults to RESTORE_TAB_CONTENT_REASON.SET_STATE. + * @param aOptions + * optional arguments used when performing process switch during load */ - restoreTabContent(aTab, aLoadArguments = null, aReloadInFreshProcess = false, - aReason = RESTORE_TAB_CONTENT_REASON.SET_STATE) { - if (aTab.hasAttribute("customizemode") && !aLoadArguments) { + restoreTabContent(aTab, aOptions = {}) { + let loadArguments = aOptions.loadArguments; + if (aTab.hasAttribute("customizemode") && !loadArguments) { return; } @@ -3731,10 +3721,10 @@ var SessionStoreInternal = { let activeIndex = tabData.index - 1; let activePageData = tabData.entries[activeIndex] || null; let uri = activePageData ? activePageData.url || null : null; - if (aLoadArguments) { - uri = aLoadArguments.uri; - if (aLoadArguments.userContextId) { - browser.setAttribute("usercontextid", aLoadArguments.userContextId); + if (loadArguments) { + uri = loadArguments.uri; + if (loadArguments.userContextId) { + browser.setAttribute("usercontextid", loadArguments.userContextId); } } @@ -3748,12 +3738,21 @@ var SessionStoreInternal = { // process, or we have a browser with a grouped session history (as we don't // support restoring into browsers with grouped session histories directly). let newFrameloader = - aReloadInFreshProcess || !!browser.frameLoader.groupedSHistory; - let isRemotenessUpdate = - tabbrowser.updateBrowserRemotenessByURL(browser, uri, { - freshProcess: aReloadInFreshProcess, - newFrameloader, - }); + aOptions.reloadInFreshProcess || !!browser.frameLoader.groupedSHistory; + + let isRemotenessUpdate; + if (aOptions.remoteType !== undefined) { + // We already have a selected remote type so we update to that. + isRemotenessUpdate = + tabbrowser.updateBrowserRemoteness(browser, !!aOptions.remoteType, + { remoteType: aOptions.remoteType, + newFrameloader }); + } else { + isRemotenessUpdate = + tabbrowser.updateBrowserRemotenessByURL(browser, uri, { + newFrameloader, + }); + } if (isRemotenessUpdate) { // We updated the remoteness, so we need to send the history down again. @@ -3766,7 +3765,7 @@ var SessionStoreInternal = { this._sendRestoreHistory(browser, { tabData, epoch, - loadArguments: aLoadArguments, + loadArguments, isRemotenessUpdate, }); } @@ -3778,8 +3777,10 @@ var SessionStoreInternal = { } browser.messageManager.sendAsyncMessage("SessionStore:restoreTabContent", - {loadArguments: aLoadArguments, isRemotenessUpdate, - reason: aReason, requestTime: Services.telemetry.msSystemNow()}); + {loadArguments, isRemotenessUpdate, + reason: aOptions.restoreContentReason || + RESTORE_TAB_CONTENT_REASON.SET_STATE, + requestTime: Services.telemetry.msSystemNow()}); }, /** diff --git a/browser/modules/E10SUtils.jsm b/browser/modules/E10SUtils.jsm index 18e0936a6b7d..8d3956849a50 100644 --- a/browser/modules/E10SUtils.jsm +++ b/browser/modules/E10SUtils.jsm @@ -46,7 +46,7 @@ const EXTENSION_REMOTE_TYPE = "extension"; const LARGE_ALLOCATION_REMOTE_TYPE = "webLargeAllocation"; const DEFAULT_REMOTE_TYPE = WEB_REMOTE_TYPE; -function validatedWebRemoteType(aPreferredRemoteType) { +function validatedWebRemoteType(aPreferredRemoteType, aTargetUri, aCurrentUri) { if (!aPreferredRemoteType) { return WEB_REMOTE_TYPE; } @@ -57,7 +57,20 @@ function validatedWebRemoteType(aPreferredRemoteType) { if (allowLinkedWebInFileUriProcess && aPreferredRemoteType == FILE_REMOTE_TYPE) { - return aPreferredRemoteType; + // If aCurrentUri is passed then we should only allow FILE_REMOTE_TYPE + // when it is same origin as target. + if (aCurrentUri) { + const sm = Services.scriptSecurityManager; + try { + // checkSameOriginURI throws when not same origin. + sm.checkSameOriginURI(aCurrentUri, aTargetUri, false); + return FILE_REMOTE_TYPE; + } catch (e) { + return WEB_REMOTE_TYPE; + } + } + + return FILE_REMOTE_TYPE; } return WEB_REMOTE_TYPE; @@ -79,6 +92,7 @@ this.E10SUtils = { getRemoteTypeForURI(aURL, aMultiProcess, aPreferredRemoteType = DEFAULT_REMOTE_TYPE, + aCurrentUri, aLargeAllocation = false) { if (!aMultiProcess) { return NOT_REMOTE; @@ -95,7 +109,7 @@ this.E10SUtils = { let uri; try { - uri = Services.io.newURI(aURL); + uri = Services.uriFixup.createFixupURI(aURL, Ci.nsIURIFixup.FIXUP_FLAG_NONE); } catch (e) { // If we have an invalid URI, it's still possible that it might get // fixed-up into a valid URI later on. However, we don't want to return @@ -105,11 +119,12 @@ this.E10SUtils = { } return this.getRemoteTypeForURIObject(uri, aMultiProcess, - aPreferredRemoteType); + aPreferredRemoteType, aCurrentUri); }, getRemoteTypeForURIObject(aURI, aMultiProcess, - aPreferredRemoteType = DEFAULT_REMOTE_TYPE) { + aPreferredRemoteType = DEFAULT_REMOTE_TYPE, + aCurrentUri) { if (!aMultiProcess) { return NOT_REMOTE; } @@ -182,10 +197,11 @@ this.E10SUtils = { if (aURI instanceof Ci.nsINestedURI) { let innerURI = aURI.QueryInterface(Ci.nsINestedURI).innerURI; return this.getRemoteTypeForURIObject(innerURI, aMultiProcess, - aPreferredRemoteType); + aPreferredRemoteType, + aCurrentUri); } - return validatedWebRemoteType(aPreferredRemoteType); + return validatedWebRemoteType(aPreferredRemoteType, aURI, aCurrentUri); } }, @@ -210,6 +226,22 @@ this.E10SUtils = { return false; } + // Allow history load if loaded in this process before. + let webNav = aDocShell.QueryInterface(Ci.nsIWebNavigation); + let sessionHistory = webNav.sessionHistory; + let requestedIndex = sessionHistory.requestedIndex; + if (requestedIndex >= 0) { + if (sessionHistory.getEntryAtIndex(requestedIndex, false).loadedInThisProcess) { + return true; + } + + // If not originally loaded in this process allow it if the URI would + // normally be allowed to load in this process by default. + let remoteType = Services.appinfo.remoteType; + return remoteType == + this.getRemoteTypeForURIObject(aURI, true, remoteType, webNav.currentURI); + } + // If the URI can be loaded in the current process then continue return this.shouldLoadURIInThisProcess(aURI); },