зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1493225, part 3 - Cancel content JS when navigating through history to prevent hangs r=smaug
This patch adds an ID to ensure that we avoid canceling content JS if the next page already started loading by the time we're ready to try canceling the JS. Differential Revision: https://phabricator.services.mozilla.com/D25164 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
dcf852821e
Коммит
7f3f2e49dc
|
@ -670,6 +670,15 @@ nsDocShell::GetInterface(const nsIID& aIID, void** aSink) {
|
|||
return *aSink ? NS_OK : NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetCancelContentJSEpoch(int32_t aEpoch) {
|
||||
// Note: this gets called fairly early (before a pageload actually starts).
|
||||
// We could probably defer this even longer.
|
||||
nsCOMPtr<nsITabChild> tabChild = GetTabChild();
|
||||
static_cast<TabChild*>(tabChild.get())->SetCancelContentJSEpoch(aEpoch);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::LoadURI(nsDocShellLoadState* aLoadState) {
|
||||
MOZ_ASSERT(aLoadState, "Must have a valid load state!");
|
||||
|
|
|
@ -75,6 +75,8 @@ webidl Document;
|
|||
[scriptable, builtinclass, uuid(049234fe-da10-478b-bc5d-bc6f9a1ba63d)]
|
||||
interface nsIDocShell : nsIDocShellTreeItem
|
||||
{
|
||||
void setCancelContentJSEpoch(in long aEpoch);
|
||||
|
||||
/**
|
||||
* Loads a given URI. This will give priority to loading the requested URI
|
||||
* in the object implementing this interface. If it can't be loaded here
|
||||
|
|
|
@ -50,7 +50,7 @@ child:
|
|||
|
||||
async CancelContentJSExecutionIfRunning(
|
||||
TabId tabId, NavigationType aNavigationType,
|
||||
int32_t aNavigationIndex, nsCString? aNavigationURI);
|
||||
int32_t aNavigationIndex, nsCString? aNavigationURI, int32_t aEpoch);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -118,7 +118,8 @@ class HangMonitorChild : public PProcessHangMonitorChild,
|
|||
mozilla::ipc::IPCResult RecvCancelContentJSExecutionIfRunning(
|
||||
const TabId& aTabId, const nsITabParent::NavigationType& aNavigationType,
|
||||
const int32_t& aNavigationIndex,
|
||||
const mozilla::Maybe<nsCString>& aNavigationURI) override;
|
||||
const mozilla::Maybe<nsCString>& aNavigationURI,
|
||||
const int32_t& aEpoch) override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
|
@ -163,6 +164,7 @@ class HangMonitorChild : public PProcessHangMonitorChild,
|
|||
nsITabParent::NavigationType mCancelContentJSNavigationType;
|
||||
int32_t mCancelContentJSNavigationIndex;
|
||||
mozilla::Maybe<nsCString> mCancelContentJSNavigationURI;
|
||||
int32_t mCancelContentJSEpoch;
|
||||
JSContext* mContext;
|
||||
bool mShutdownDone;
|
||||
|
||||
|
@ -279,7 +281,7 @@ class HangMonitorParent : public PProcessHangMonitorParent,
|
|||
const LayersObserverEpoch& aEpoch);
|
||||
void CancelContentJSExecutionIfRunningOnThread(
|
||||
TabId aTabId, nsITabParent::NavigationType aNavigationType,
|
||||
int32_t aNavigationIndex, nsIURI* aNavigationURI);
|
||||
int32_t aNavigationIndex, nsIURI* aNavigationURI, int32_t aEpoch);
|
||||
|
||||
void ShutdownOnThread();
|
||||
|
||||
|
@ -326,6 +328,7 @@ HangMonitorChild::HangMonitorChild(ProcessHangMonitor* aMonitor)
|
|||
mCancelContentJS(false),
|
||||
mCancelContentJSNavigationType(nsITabParent::NAVIGATE_BACK),
|
||||
mCancelContentJSNavigationIndex(0),
|
||||
mCancelContentJSEpoch(0),
|
||||
mShutdownDone(false),
|
||||
mIPCOpen(true),
|
||||
mPaintWhileInterruptingJSActive(false) {
|
||||
|
@ -354,6 +357,7 @@ void HangMonitorChild::InterruptCallback() {
|
|||
nsITabParent::NavigationType cancelContentJSNavigationType;
|
||||
int32_t cancelContentJSNavigationIndex;
|
||||
mozilla::Maybe<nsCString> cancelContentJSNavigationURI;
|
||||
int32_t cancelContentJSEpoch;
|
||||
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
@ -367,6 +371,7 @@ void HangMonitorChild::InterruptCallback() {
|
|||
cancelContentJSNavigationType = mCancelContentJSNavigationType;
|
||||
cancelContentJSNavigationIndex = mCancelContentJSNavigationIndex;
|
||||
cancelContentJSNavigationURI = std::move(mCancelContentJSNavigationURI);
|
||||
cancelContentJSEpoch = mCancelContentJSEpoch;
|
||||
|
||||
mPaintWhileInterruptingJS = false;
|
||||
mCancelContentJS = false;
|
||||
|
@ -402,7 +407,7 @@ void HangMonitorChild::InterruptCallback() {
|
|||
bool canCancel;
|
||||
rv = tabChild->CanCancelContentJS(cancelContentJSNavigationType,
|
||||
cancelContentJSNavigationIndex, uri,
|
||||
&canCancel);
|
||||
cancelContentJSEpoch, &canCancel);
|
||||
if (NS_SUCCEEDED(rv) && canCancel) {
|
||||
// Tell xpconnect that we want to cancel the content JS in this tab
|
||||
// during the next interrupt callback.
|
||||
|
@ -513,7 +518,7 @@ void HangMonitorChild::ClearPaintWhileInterruptingJS(
|
|||
mozilla::ipc::IPCResult HangMonitorChild::RecvCancelContentJSExecutionIfRunning(
|
||||
const TabId& aTabId, const nsITabParent::NavigationType& aNavigationType,
|
||||
const int32_t& aNavigationIndex,
|
||||
const mozilla::Maybe<nsCString>& aNavigationURI) {
|
||||
const mozilla::Maybe<nsCString>& aNavigationURI, const int32_t& aEpoch) {
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
{
|
||||
|
@ -523,6 +528,7 @@ mozilla::ipc::IPCResult HangMonitorChild::RecvCancelContentJSExecutionIfRunning(
|
|||
mCancelContentJSNavigationType = aNavigationType;
|
||||
mCancelContentJSNavigationIndex = aNavigationIndex;
|
||||
mCancelContentJSNavigationURI = aNavigationURI;
|
||||
mCancelContentJSEpoch = aEpoch;
|
||||
}
|
||||
|
||||
JS_RequestInterruptCallback(mContext);
|
||||
|
@ -744,16 +750,16 @@ void HangMonitorParent::CancelContentJSExecutionIfRunning(
|
|||
TabId id = aTab->GetTabId();
|
||||
|
||||
Dispatch(NewNonOwningRunnableMethod<TabId, nsITabParent::NavigationType,
|
||||
int32_t, nsIURI*>(
|
||||
int32_t, nsIURI*, int32_t>(
|
||||
"HangMonitorParent::CancelContentJSExecutionIfRunningOnThread", this,
|
||||
&HangMonitorParent::CancelContentJSExecutionIfRunningOnThread, id,
|
||||
aNavigationType, aCancelContentJSOptions.mIndex,
|
||||
aCancelContentJSOptions.mUri));
|
||||
aCancelContentJSOptions.mUri, aCancelContentJSOptions.mEpoch));
|
||||
}
|
||||
|
||||
void HangMonitorParent::CancelContentJSExecutionIfRunningOnThread(
|
||||
TabId aTabId, nsITabParent::NavigationType aNavigationType,
|
||||
int32_t aNavigationIndex, nsIURI* aNavigationURI) {
|
||||
int32_t aNavigationIndex, nsIURI* aNavigationURI, int32_t aEpoch) {
|
||||
MOZ_RELEASE_ASSERT(IsOnThread());
|
||||
|
||||
mozilla::Maybe<nsCString> spec;
|
||||
|
@ -766,8 +772,8 @@ void HangMonitorParent::CancelContentJSExecutionIfRunningOnThread(
|
|||
}
|
||||
|
||||
if (mIPCOpen) {
|
||||
Unused << SendCancelContentJSExecutionIfRunning(aTabId, aNavigationType,
|
||||
aNavigationIndex, spec);
|
||||
Unused << SendCancelContentJSExecutionIfRunning(
|
||||
aTabId, aNavigationType, aNavigationIndex, spec, aEpoch);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -405,7 +405,8 @@ TabChild::TabChild(ContentChild* aManager, const TabId& aTabId,
|
|||
mPendingDocShellIsActive(false), mPendingDocShellReceivedMessage(false),
|
||||
mPendingRenderLayers(false),
|
||||
mPendingRenderLayersReceivedMessage(false), mPendingLayersObserverEpoch{0},
|
||||
mPendingDocShellBlockers(0), mWidgetNativeData(0) {
|
||||
mPendingDocShellBlockers(0), mCancelContentJSEpoch(0),
|
||||
mWidgetNativeData(0) {
|
||||
mozilla::HoldJSObjects(this);
|
||||
|
||||
nsWeakPtr weakPtrThis(do_GetWeakReference(
|
||||
|
@ -3290,10 +3291,17 @@ void TabChild::PaintWhileInterruptingJS(
|
|||
|
||||
nsresult TabChild::CanCancelContentJS(
|
||||
nsITabParent::NavigationType aNavigationType, int32_t aNavigationIndex,
|
||||
nsIURI* aNavigationURI, bool* aCanCancel) {
|
||||
nsIURI* aNavigationURI, int32_t aEpoch, bool* aCanCancel) {
|
||||
nsresult rv;
|
||||
*aCanCancel = false;
|
||||
|
||||
if (aEpoch <= mCancelContentJSEpoch) {
|
||||
// The next page loaded before we got here, so we shouldn't try to cancel
|
||||
// the content JS.
|
||||
TABC_LOG("Unable to cancel content JS; the next page is already loaded!\n");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISHistory> history = do_GetInterface(WebNavigation());
|
||||
if (!history) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -615,7 +615,7 @@ class TabChild final : public TabChildBase,
|
|||
|
||||
nsresult CanCancelContentJS(nsITabParent::NavigationType aNavigationType,
|
||||
int32_t aNavigationIndex, nsIURI* aNavigationURI,
|
||||
bool* aCanCancel);
|
||||
int32_t aEpoch, bool* aCanCancel);
|
||||
|
||||
layers::LayersObserverEpoch LayersObserverEpoch() const {
|
||||
return mLayersObserverEpoch;
|
||||
|
@ -665,6 +665,10 @@ class TabChild final : public TabChildBase,
|
|||
const ScrollableLayerGuid& aGuid,
|
||||
const uint64_t& aInputBlockId);
|
||||
|
||||
void SetCancelContentJSEpoch(int32_t aEpoch) {
|
||||
mCancelContentJSEpoch = aEpoch;
|
||||
}
|
||||
|
||||
static bool HasVisibleTabs() {
|
||||
return sVisibleTabs && !sVisibleTabs->IsEmpty();
|
||||
}
|
||||
|
@ -921,6 +925,7 @@ class TabChild final : public TabChildBase,
|
|||
// When mPendingDocShellBlockers is greater than 0, the DocShell is blocked,
|
||||
// and once it reaches 0, it is no longer blocked.
|
||||
uint32_t mPendingDocShellBlockers;
|
||||
int32_t mCancelContentJSEpoch;
|
||||
|
||||
WindowsHandle mWidgetNativeData;
|
||||
|
||||
|
|
|
@ -5,4 +5,5 @@
|
|||
dictionary CancelContentJSOptions {
|
||||
long index = 0;
|
||||
URI? uri = null;
|
||||
long epoch = 0;
|
||||
};
|
||||
|
|
|
@ -27,13 +27,13 @@ class WebNavigationChild extends ActorChild {
|
|||
receiveMessage(message) {
|
||||
switch (message.name) {
|
||||
case "WebNavigation:GoBack":
|
||||
this.goBack();
|
||||
this.goBack(message.data);
|
||||
break;
|
||||
case "WebNavigation:GoForward":
|
||||
this.goForward();
|
||||
this.goForward(message.data);
|
||||
break;
|
||||
case "WebNavigation:GotoIndex":
|
||||
this.gotoIndex(message.data.index);
|
||||
this.gotoIndex(message.data);
|
||||
break;
|
||||
case "WebNavigation:LoadURI":
|
||||
let histogram = Services.telemetry.getKeyedHistogramById("FX_TAB_REMOTE_NAVIGATION_DELAY_MS");
|
||||
|
@ -65,19 +65,26 @@ class WebNavigationChild extends ActorChild {
|
|||
}
|
||||
}
|
||||
|
||||
goBack() {
|
||||
goBack(params) {
|
||||
if (this.webNavigation.canGoBack) {
|
||||
this.mm.docShell.setCancelContentJSEpoch(params.cancelContentJSEpoch);
|
||||
this._wrapURIChangeCall(() => this.webNavigation.goBack());
|
||||
}
|
||||
}
|
||||
|
||||
goForward() {
|
||||
goForward(params) {
|
||||
if (this.webNavigation.canGoForward) {
|
||||
this.mm.docShell.setCancelContentJSEpoch(params.cancelContentJSEpoch);
|
||||
this._wrapURIChangeCall(() => this.webNavigation.goForward());
|
||||
}
|
||||
}
|
||||
|
||||
gotoIndex(index) {
|
||||
gotoIndex(params) {
|
||||
let {
|
||||
index,
|
||||
cancelContentJSEpoch,
|
||||
} = params || {};
|
||||
this.mm.docShell.setCancelContentJSEpoch(cancelContentJSEpoch);
|
||||
this._wrapURIChangeCall(() => this.webNavigation.gotoIndex(index));
|
||||
}
|
||||
|
||||
|
@ -91,6 +98,7 @@ class WebNavigationChild extends ActorChild {
|
|||
baseURI,
|
||||
triggeringPrincipal,
|
||||
csp,
|
||||
cancelContentJSEpoch,
|
||||
} = params || {};
|
||||
|
||||
if (AppConstants.MOZ_CRASHREPORTER && CrashReporter.enabled) {
|
||||
|
@ -131,6 +139,7 @@ class WebNavigationChild extends ActorChild {
|
|||
headers,
|
||||
baseURI,
|
||||
};
|
||||
this.mm.docShell.setCancelContentJSEpoch(cancelContentJSEpoch);
|
||||
this._wrapURIChangeCall(() => {
|
||||
return this.webNavigation.loadURI(uri, loadURIOptions);
|
||||
});
|
||||
|
|
|
@ -18,6 +18,7 @@ function makeURI(url) {
|
|||
|
||||
function RemoteWebNavigation() {
|
||||
this.wrappedJSObject = this;
|
||||
this._cancelContentJSEpoch = 1;
|
||||
}
|
||||
|
||||
RemoteWebNavigation.prototype = {
|
||||
|
@ -55,19 +56,24 @@ RemoteWebNavigation.prototype = {
|
|||
canGoBack: false,
|
||||
canGoForward: false,
|
||||
goBack() {
|
||||
let cancelContentJSEpoch = this._cancelContentJSEpoch++;
|
||||
this._browser.frameLoader.tabParent.maybeCancelContentJSExecution(
|
||||
Ci.nsITabParent.NAVIGATE_BACK);
|
||||
this._sendMessage("WebNavigation:GoBack", {});
|
||||
Ci.nsITabParent.NAVIGATE_BACK, {epoch: cancelContentJSEpoch});
|
||||
this._sendMessage("WebNavigation:GoBack", {cancelContentJSEpoch});
|
||||
},
|
||||
goForward() {
|
||||
let cancelContentJSEpoch = this._cancelContentJSEpoch++;
|
||||
this._browser.frameLoader.tabParent.maybeCancelContentJSExecution(
|
||||
Ci.nsITabParent.NAVIGATE_FORWARD);
|
||||
this._sendMessage("WebNavigation:GoForward", {});
|
||||
Ci.nsITabParent.NAVIGATE_FORWARD, {epoch: cancelContentJSEpoch});
|
||||
this._sendMessage("WebNavigation:GoForward", {cancelContentJSEpoch});
|
||||
},
|
||||
gotoIndex(aIndex) {
|
||||
let cancelContentJSEpoch = this._cancelContentJSEpoch++;
|
||||
this._browser.frameLoader.tabParent.maybeCancelContentJSExecution(
|
||||
Ci.nsITabParent.NAVIGATE_INDEX, {index: aIndex});
|
||||
this._sendMessage("WebNavigation:GotoIndex", {index: aIndex});
|
||||
Ci.nsITabParent.NAVIGATE_INDEX,
|
||||
{index: aIndex, epoch: cancelContentJSEpoch});
|
||||
this._sendMessage("WebNavigation:GotoIndex", {index: aIndex,
|
||||
cancelContentJSEpoch});
|
||||
},
|
||||
loadURI(aURI, aLoadURIOptions) {
|
||||
let uri;
|
||||
|
@ -97,8 +103,9 @@ RemoteWebNavigation.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
let cancelContentJSEpoch = this._cancelContentJSEpoch++;
|
||||
this._browser.frameLoader.tabParent.maybeCancelContentJSExecution(
|
||||
Ci.nsITabParent.NAVIGATE_URL, {uri});
|
||||
Ci.nsITabParent.NAVIGATE_URL, {uri, epoch: cancelContentJSEpoch});
|
||||
this._sendMessage("WebNavigation:LoadURI", {
|
||||
uri: aURI,
|
||||
flags: aLoadURIOptions.loadFlags,
|
||||
|
@ -110,6 +117,7 @@ RemoteWebNavigation.prototype = {
|
|||
aLoadURIOptions.triggeringPrincipal || Services.scriptSecurityManager.createNullPrincipal({})),
|
||||
csp: aLoadURIOptions.csp ? E10SUtils.serializeCSP(aLoadURIOptions.csp) : null,
|
||||
requestTime: Services.telemetry.msSystemNow(),
|
||||
cancelContentJSEpoch,
|
||||
});
|
||||
},
|
||||
setOriginAttributesBeforeLoading(aOriginAttributes) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче