Bug 1493225, part 2 - Cancel content JS when navigating through history to prevent hangs r=smaug

In this part, we pass along the navigation type (and index for when using the
dropdown on the back/forward buttons). This allows us to check if there's a
top-level load "between" the start and end pages.

The patch might look a bit strange, since we're passing the navigation
operation to two places from RemoteWebNavigation.js (the normal message passing
that existed before this patch and the HangMonitor channel in this patch). This
is primarily to make it easier to stop passing the navigation info along the
HangMonitor channel once session history is uplifted into the parent process.
At that point, the check for whether there's a top-level load could happen in
TabParent (I think).

Differential Revision: https://phabricator.services.mozilla.com/D23090

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jim Porter 2019-04-30 23:31:36 +00:00
parent 04d397e55f
commit f9d5e48623
13 changed files with 271 additions and 28 deletions

View File

@ -122,10 +122,20 @@ interface nsIRemoteTab : nsISupports
*/
Promise getContentBlockingLog();
cenum NavigationType : 8 {
NAVIGATE_BACK = 0,
NAVIGATE_FORWARD = 1,
NAVIGATE_INDEX = 2,
NAVIGATE_URL = 3
};
/**
* Interrupt content scripts if possible/needed to allow chrome scripts in the
* content process to run (in particular, to allow navigating through browser
* history.
*/
void maybeCancelContentJSExecution();
[implicit_jscontext, binaryname(MaybeCancelContentJSExecutionFromScript)]
void maybeCancelContentJSExecution(
in nsIRemoteTab_NavigationType aNavigationType,
[optional] in jsval aCancelContentJSOptions);
};

View File

@ -119,6 +119,7 @@
#include "FrameLayerBuilder.h"
#include "VRManagerChild.h"
#include "nsCommandParams.h"
#include "nsISHEntry.h"
#include "nsISHistory.h"
#include "nsQueryObject.h"
#include "nsIHttpChannel.h"
@ -3301,6 +3302,96 @@ void BrowserChild::PaintWhileInterruptingJS(
RecvRenderLayers(true /* aEnabled */, aForceRepaint, aEpoch);
}
nsresult BrowserChild::CanCancelContentJS(
nsIRemoteTab::NavigationType aNavigationType, int32_t aNavigationIndex,
nsIURI* aNavigationURI, bool* aCanCancel) {
nsresult rv;
*aCanCancel = false;
nsCOMPtr<nsISHistory> history = do_GetInterface(WebNavigation());
if (!history) {
return NS_ERROR_FAILURE;
}
int32_t current;
rv = history->GetIndex(&current);
NS_ENSURE_SUCCESS(rv, rv);
if (current == -1) {
// This tab has no history! Just return.
return NS_OK;
}
nsCOMPtr<nsISHEntry> entry;
rv = history->GetEntryAtIndex(current, getter_AddRefs(entry));
NS_ENSURE_SUCCESS(rv, rv);
if (aNavigationType == nsIRemoteTab::NAVIGATE_BACK) {
aNavigationIndex = current - 1;
} else if (aNavigationType == nsIRemoteTab::NAVIGATE_FORWARD) {
aNavigationIndex = current + 1;
} else if (aNavigationType == nsIRemoteTab::NAVIGATE_URL) {
if (!aNavigationURI) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIURI> currentURI = entry->GetURI();
CanCancelContentJSBetweenURIs(currentURI, aNavigationURI, aCanCancel);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
// Note: aNavigationType may also be NAVIGATE_INDEX, in which case we don't
// need to do anything special.
int32_t delta = aNavigationIndex > current ? 1 : -1;
for (int32_t i = current + delta; i != aNavigationIndex + delta; i += delta) {
nsCOMPtr<nsISHEntry> nextEntry;
// If `i` happens to be negative, this call will fail (which is what we
// would want to happen).
rv = history->GetEntryAtIndex(i, getter_AddRefs(nextEntry));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISHEntry> laterEntry = delta == 1 ? nextEntry : entry;
nsCOMPtr<nsIURI> uri = entry->GetURI();
nsCOMPtr<nsIURI> nextURI = nextEntry->GetURI();
// If we changed origin and the load wasn't in a subframe, we know it was
// a full document load, so we can cancel the content JS safely.
if (!laterEntry->GetIsSubFrame()) {
CanCancelContentJSBetweenURIs(uri, nextURI, aCanCancel);
NS_ENSURE_SUCCESS(rv, rv);
if (*aCanCancel) {
return NS_OK;
}
}
entry = nextEntry;
}
return NS_OK;
}
nsresult BrowserChild::CanCancelContentJSBetweenURIs(nsIURI* aFirstURI,
nsIURI* aSecondURI,
bool* aCanCancel) {
nsresult rv;
*aCanCancel = false;
nsAutoCString firstHost;
rv = aFirstURI->GetHostPort(firstHost);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString secondHost;
rv = aSecondURI->GetHostPort(secondHost);
NS_ENSURE_SUCCESS(rv, rv);
if (!firstHost.Equals(secondHost)) {
*aCanCancel = true;
}
return NS_OK;
}
void BrowserChild::BeforeUnloadAdded() {
// Don't bother notifying the parent if we don't have an IPC link open.
if (mBeforeUnloadListeners == 0 && IPCOpen()) {

View File

@ -612,6 +612,10 @@ class BrowserChild final : public BrowserChildBase,
void PaintWhileInterruptingJS(const layers::LayersObserverEpoch& aEpoch,
bool aForceRepaint);
nsresult CanCancelContentJS(nsIRemoteTab::NavigationType aNavigationType,
int32_t aNavigationIndex, nsIURI* aNavigationURI,
bool* aCanCancel);
layers::LayersObserverEpoch LayersObserverEpoch() const {
return mLayersObserverEpoch;
}
@ -808,6 +812,9 @@ class BrowserChild final : public BrowserChildBase,
Maybe<WebProgressData>& aWebProgressData,
RequestData& aRequestData);
nsresult CanCancelContentJSBetweenURIs(nsIURI* aFirstURI, nsIURI* aSecondURI,
bool* aCanCancel);
class DelayedDeleteRunnable;
TextureFactoryIdentifier mTextureFactoryIdentifier;

View File

@ -13,6 +13,7 @@
# include "nsAccessibilityService.h"
#endif
#include "mozilla/BrowserElementParent.h"
#include "mozilla/dom/CancelContentJSOptionsBinding.h"
#include "mozilla/dom/ChromeMessageSender.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/DataTransfer.h"
@ -3121,9 +3122,16 @@ BrowserParent::GetContentBlockingLog(Promise** aPromise) {
}
NS_IMETHODIMP
BrowserParent::MaybeCancelContentJSExecution() {
BrowserParent::MaybeCancelContentJSExecutionFromScript(
nsIRemoteTab::NavigationType aNavigationType,
JS::Handle<JS::Value> aCancelContentJSOptions, JSContext* aCx) {
dom::CancelContentJSOptions cancelContentJSOptions;
if (!cancelContentJSOptions.Init(aCx, aCancelContentJSOptions)) {
return NS_ERROR_INVALID_ARG;
}
if (StaticPrefs::dom_ipc_cancel_content_js_when_navigating()) {
Manager()->CancelContentJSExecutionIfRunning(this);
Manager()->CancelContentJSExecutionIfRunning(this, aNavigationType,
cancelContentJSOptions);
}
return NS_OK;
}

View File

@ -40,6 +40,7 @@
#include "mozilla/docshell/OfflineCacheUpdateParent.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/dom/CancelContentJSOptionsBinding.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/ClientManager.h"
#include "mozilla/dom/ClientOpenWindowOpActors.h"
@ -5296,12 +5297,14 @@ void ContentParent::PaintTabWhileInterruptingJS(
}
void ContentParent::CancelContentJSExecutionIfRunning(
BrowserParent* aBrowserParent) {
BrowserParent* aBrowserParent, nsIRemoteTab::NavigationType aNavigationType,
const CancelContentJSOptions& aCancelContentJSOptions) {
if (!mHangMonitorActor) {
return;
}
ProcessHangMonitor::CancelContentJSExecutionIfRunning(mHangMonitorActor,
aBrowserParent);
ProcessHangMonitor::CancelContentJSExecutionIfRunning(
mHangMonitorActor, aBrowserParent, aNavigationType,
aCancelContentJSOptions);
}
void ContentParent::UpdateCookieStatus(nsIChannel* aChannel) {

View File

@ -32,6 +32,7 @@
#include "nsHashKeys.h"
#include "nsIInterfaceRequestor.h"
#include "nsIObserver.h"
#include "nsIRemoteTab.h"
#include "nsIThreadInternal.h"
#include "nsIDOMGeoPositionCallback.h"
#include "nsIDOMGeoPositionErrorCallback.h"
@ -109,6 +110,7 @@ class MemoryReport;
class TabContext;
class GetFilesHelper;
class MemoryReportRequestHost;
struct CancelContentJSOptions;
#define NS_CONTENTPARENT_IID \
{ \
@ -591,7 +593,10 @@ class ContentParent final : public PContentParent,
bool aForceRepaint,
const layers::LayersObserverEpoch& aEpoch);
void CancelContentJSExecutionIfRunning(BrowserParent* aBrowserParent);
void CancelContentJSExecutionIfRunning(
BrowserParent* aBrowserParent,
nsIRemoteTab::NavigationType aNavigationType,
const CancelContentJSOptions& aCancelContentJSOptions);
// This function is called when we are about to load a document from an
// HTTP(S) or FTP channel for a content process. It is a useful place

View File

@ -5,6 +5,10 @@
* 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/. */
// ParamTraits stuff for nsIRemoteTab::NavigationType
include "mozilla/dom/TabMessageUtils.h";
using nsIRemoteTab::NavigationType from "nsIRemoteTab.h";
using base::ProcessId from "base/process.h";
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
@ -44,7 +48,9 @@ child:
async PaintWhileInterruptingJS(TabId tabId, bool forceRepaint, LayersObserverEpoch aEpoch);
async CancelContentJSExecutionIfRunning(TabId tabId);
async CancelContentJSExecutionIfRunning(
TabId tabId, NavigationType aNavigationType,
int32_t aNavigationIndex, nsCString? aNavigationURI);
};
} // namespace mozilla

View File

@ -12,6 +12,7 @@
#include "mozilla/Atomics.h"
#include "mozilla/BackgroundHangMonitor.h"
#include "mozilla/dom/CancelContentJSOptionsBinding.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ScriptSettings.h"
@ -28,6 +29,7 @@
#include "nsFrameLoader.h"
#include "nsIHangReport.h"
#include "nsIRemoteTab.h"
#include "nsNetUtil.h"
#include "nsQueryObject.h"
#include "nsPluginHost.h"
#include "nsThreadUtils.h"
@ -114,7 +116,9 @@ class HangMonitorChild : public PProcessHangMonitorChild,
const LayersObserverEpoch& aEpoch) override;
mozilla::ipc::IPCResult RecvCancelContentJSExecutionIfRunning(
const TabId& aTabId) override;
const TabId& aTabId, const nsIRemoteTab::NavigationType& aNavigationType,
const int32_t& aNavigationIndex,
const mozilla::Maybe<nsCString>& aNavigationURI) override;
void ActorDestroy(ActorDestroyReason aWhy) override;
@ -154,6 +158,11 @@ class HangMonitorChild : public PProcessHangMonitorChild,
bool mPaintWhileInterruptingJSForce;
TabId mPaintWhileInterruptingJSTab;
MOZ_INIT_OUTSIDE_CTOR LayersObserverEpoch mPaintWhileInterruptingJSEpoch;
bool mCancelContentJS;
TabId mCancelContentJSTab;
nsIRemoteTab::NavigationType mCancelContentJSNavigationType;
int32_t mCancelContentJSNavigationIndex;
mozilla::Maybe<nsCString> mCancelContentJSNavigationURI;
JSContext* mContext;
bool mShutdownDone;
@ -238,7 +247,10 @@ class HangMonitorParent : public PProcessHangMonitorParent,
void PaintWhileInterruptingJS(dom::BrowserParent* aBrowserParent,
bool aForceRepaint,
const LayersObserverEpoch& aEpoch);
void CancelContentJSExecutionIfRunning(dom::BrowserParent* aBrowserParent);
void CancelContentJSExecutionIfRunning(
dom::BrowserParent* aBrowserParent,
nsIRemoteTab::NavigationType aNavigationType,
const dom::CancelContentJSOptions& aCancelContentJSOptions);
void TerminateScript(bool aTerminateGlobal);
void BeginStartingDebugger();
@ -267,7 +279,9 @@ class HangMonitorParent : public PProcessHangMonitorParent,
void PaintWhileInterruptingJSOnThread(TabId aTabId, bool aForceRepaint,
const LayersObserverEpoch& aEpoch);
void CancelContentJSExecutionIfRunningOnThread(TabId aTabId);
void CancelContentJSExecutionIfRunningOnThread(
TabId aTabId, nsIRemoteTab::NavigationType aNavigationType,
int32_t aNavigationIndex, nsIURI* aNavigationURI);
void ShutdownOnThread();
@ -311,6 +325,9 @@ HangMonitorChild::HangMonitorChild(ProcessHangMonitor* aMonitor)
mFinishedStartingDebugger(false),
mPaintWhileInterruptingJS(false),
mPaintWhileInterruptingJSForce(false),
mCancelContentJS(false),
mCancelContentJSNavigationType(nsIRemoteTab::NAVIGATE_BACK),
mCancelContentJSNavigationIndex(0),
mShutdownDone(false),
mIPCOpen(true),
mPaintWhileInterruptingJSActive(false) {
@ -334,6 +351,12 @@ void HangMonitorChild::InterruptCallback() {
TabId paintWhileInterruptingJSTab;
LayersObserverEpoch paintWhileInterruptingJSEpoch;
bool cancelContentJS;
TabId cancelContentJSTab;
nsIRemoteTab::NavigationType cancelContentJSNavigationType;
int32_t cancelContentJSNavigationIndex;
mozilla::Maybe<nsCString> cancelContentJSNavigationURI;
{
MonitorAutoLock lock(mMonitor);
paintWhileInterruptingJS = mPaintWhileInterruptingJS;
@ -341,7 +364,14 @@ void HangMonitorChild::InterruptCallback() {
paintWhileInterruptingJSTab = mPaintWhileInterruptingJSTab;
paintWhileInterruptingJSEpoch = mPaintWhileInterruptingJSEpoch;
cancelContentJS = mCancelContentJS;
cancelContentJSTab = mCancelContentJSTab;
cancelContentJSNavigationType = mCancelContentJSNavigationType;
cancelContentJSNavigationIndex = mCancelContentJSNavigationIndex;
cancelContentJSNavigationURI = std::move(mCancelContentJSNavigationURI);
mPaintWhileInterruptingJS = false;
mCancelContentJS = false;
}
// Don't paint from the interrupt callback when recording or replaying, as
@ -355,6 +385,35 @@ void HangMonitorChild::InterruptCallback() {
paintWhileInterruptingJSForce);
}
}
if (cancelContentJS) {
RefPtr<BrowserChild> browserChild =
BrowserChild::FindBrowserChild(cancelContentJSTab);
if (browserChild) {
js::AutoAssertNoContentJS nojs(mContext);
nsresult rv;
nsCOMPtr<nsIURI> uri;
if (cancelContentJSNavigationURI) {
rv = NS_NewURI(getter_AddRefs(uri),
cancelContentJSNavigationURI.value());
if (NS_FAILED(rv)) {
return;
}
}
bool canCancel;
rv = browserChild->CanCancelContentJS(cancelContentJSNavigationType,
cancelContentJSNavigationIndex, uri,
&canCancel);
if (NS_SUCCEEDED(rv) && canCancel) {
// Tell xpconnect that we want to cancel the content JS in this tab
// during the next interrupt callback.
XPCJSContext::SetTabIdToCancelContentJS(cancelContentJSTab);
JS_RequestInterruptCallback(mContext);
}
}
}
}
void HangMonitorChild::AnnotateHang(BackgroundHangAnnotations& aAnnotations) {
@ -455,12 +514,20 @@ void HangMonitorChild::ClearPaintWhileInterruptingJS(
}
mozilla::ipc::IPCResult HangMonitorChild::RecvCancelContentJSExecutionIfRunning(
const TabId& aTabId) {
const TabId& aTabId, const nsIRemoteTab::NavigationType& aNavigationType,
const int32_t& aNavigationIndex,
const mozilla::Maybe<nsCString>& aNavigationURI) {
MOZ_RELEASE_ASSERT(IsOnThread());
// Tell xpconnect that we want to cancel the content JS in this tab during the
// next interrupt callback.
XPCJSContext::SetTabIdToCancelContentJS(aTabId);
{
MonitorAutoLock lock(mMonitor);
mCancelContentJS = true;
mCancelContentJSTab = aTabId;
mCancelContentJSNavigationType = aNavigationType;
mCancelContentJSNavigationIndex = aNavigationIndex;
mCancelContentJSNavigationURI = aNavigationURI;
}
JS_RequestInterruptCallback(mContext);
return IPC_OK();
@ -675,21 +742,37 @@ void HangMonitorParent::PaintWhileInterruptingJSOnThread(
}
void HangMonitorParent::CancelContentJSExecutionIfRunning(
dom::BrowserParent* aBrowserParent) {
dom::BrowserParent* aBrowserParent,
nsIRemoteTab::NavigationType aNavigationType,
const dom::CancelContentJSOptions& aCancelContentJSOptions) {
MOZ_RELEASE_ASSERT(NS_IsMainThread());
TabId id = aBrowserParent->GetTabId();
Dispatch(NewNonOwningRunnableMethod<TabId>(
Dispatch(NewNonOwningRunnableMethod<TabId, nsIRemoteTab::NavigationType,
int32_t, nsIURI*>(
"HangMonitorParent::CancelContentJSExecutionIfRunningOnThread", this,
&HangMonitorParent::CancelContentJSExecutionIfRunningOnThread, id));
&HangMonitorParent::CancelContentJSExecutionIfRunningOnThread, id,
aNavigationType, aCancelContentJSOptions.mIndex,
aCancelContentJSOptions.mUri));
}
void HangMonitorParent::CancelContentJSExecutionIfRunningOnThread(
TabId aTabId) {
TabId aTabId, nsIRemoteTab::NavigationType aNavigationType,
int32_t aNavigationIndex, nsIURI* aNavigationURI) {
MOZ_RELEASE_ASSERT(IsOnThread());
mozilla::Maybe<nsCString> spec;
if (aNavigationURI) {
nsAutoCString tmp;
nsresult rv = aNavigationURI->GetSpec(tmp);
if (NS_SUCCEEDED(rv)) {
spec.emplace(tmp);
}
}
if (mIPCOpen) {
Unused << SendCancelContentJSExecutionIfRunning(aTabId);
Unused << SendCancelContentJSExecutionIfRunning(aTabId, aNavigationType,
aNavigationIndex, spec);
}
}
@ -1296,8 +1379,11 @@ void ProcessHangMonitor::MaybeStartPaintWhileInterruptingJS() {
/* static */
void ProcessHangMonitor::CancelContentJSExecutionIfRunning(
PProcessHangMonitorParent* aParent, dom::BrowserParent* aBrowserParent) {
PProcessHangMonitorParent* aParent, dom::BrowserParent* aBrowserParent,
nsIRemoteTab::NavigationType aNavigationType,
const dom::CancelContentJSOptions& aCancelContentJSOptions) {
MOZ_RELEASE_ASSERT(NS_IsMainThread());
auto parent = static_cast<HangMonitorParent*>(aParent);
parent->CancelContentJSExecutionIfRunning(aBrowserParent);
parent->CancelContentJSExecutionIfRunning(aBrowserParent, aNavigationType,
aCancelContentJSOptions);
}

View File

@ -11,6 +11,7 @@
#include "mozilla/Atomics.h"
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "nsIRemoteTab.h"
#include "nsStringFwd.h"
class nsIRunnable;
@ -22,6 +23,7 @@ namespace mozilla {
namespace dom {
class ContentParent;
class BrowserParent;
struct CancelContentJSOptions;
} // namespace dom
namespace layers {
@ -56,7 +58,9 @@ class ProcessHangMonitor final : public nsIObserver {
static void MaybeStartPaintWhileInterruptingJS();
static void CancelContentJSExecutionIfRunning(
PProcessHangMonitorParent* aParent, dom::BrowserParent* aTab);
PProcessHangMonitorParent* aParent, dom::BrowserParent* aTab,
nsIRemoteTab::NavigationType aNavigationType,
const dom::CancelContentJSOptions& aCancelContentJSOptions);
enum SlowScriptAction {
Continue,

View File

@ -11,6 +11,7 @@
#include "mozilla/RefPtr.h"
#include "mozilla/dom/Event.h"
#include "nsExceptionHandler.h"
#include "nsIRemoteTab.h"
#include "nsPIDOMWindow.h"
#include "nsCOMPtr.h"
@ -65,6 +66,13 @@ struct ParamTraits<UIStateChangeType>
UIStateChangeType_NoChange,
UIStateChangeType_Invalid> {};
template <>
struct ParamTraits<nsIRemoteTab::NavigationType>
: public ContiguousEnumSerializerInclusive<
nsIRemoteTab::NavigationType,
nsIRemoteTab::NavigationType::NAVIGATE_BACK,
nsIRemoteTab::NavigationType::NAVIGATE_URL> {};
} // namespace IPC
#endif // TABMESSAGE_UTILS_H

View File

@ -0,0 +1,8 @@
/* 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/. */
dictionary CancelContentJSOptions {
long index = 0;
URI? uri = null;
};

View File

@ -406,6 +406,7 @@ WEBIDL_FILES = [
'BrowserElementDictionaries.webidl',
'Cache.webidl',
'CacheStorage.webidl',
'CancelContentJSOptions.webidl',
'CanvasCaptureMediaStream.webidl',
'CanvasRenderingContext2D.webidl',
'CaretPosition.webidl',

View File

@ -55,25 +55,30 @@ RemoteWebNavigation.prototype = {
canGoBack: false,
canGoForward: false,
goBack() {
this._browser.frameLoader.remoteTab.maybeCancelContentJSExecution();
this._browser.frameLoader.remoteTab.maybeCancelContentJSExecution(
Ci.nsIRemoteTab.NAVIGATE_BACK);
this._sendMessage("WebNavigation:GoBack", {});
},
goForward() {
this._browser.frameLoader.remoteTab.maybeCancelContentJSExecution();
this._browser.frameLoader.remoteTab.maybeCancelContentJSExecution(
Ci.nsIRemoteTab.NAVIGATE_FORWARD);
this._sendMessage("WebNavigation:GoForward", {});
},
gotoIndex(aIndex) {
this._browser.frameLoader.remoteTab.maybeCancelContentJSExecution();
this._browser.frameLoader.remoteTab.maybeCancelContentJSExecution(
Ci.nsIRemoteTab.NAVIGATE_INDEX, {index: aIndex});
this._sendMessage("WebNavigation:GotoIndex", {index: aIndex});
},
loadURI(aURI, aLoadURIOptions) {
let uri;
// We know the url is going to be loaded, let's start requesting network
// connection before the content process asks.
// Note that we might have already setup the speculative connection in some
// cases, especially when the url is from location bar or its popup menu.
if (aURI.startsWith("http:") || aURI.startsWith("https:")) {
try {
let uri = makeURI(aURI);
uri = makeURI(aURI);
let principal = aLoadURIOptions.triggeringPrincipal;
// We usually have a triggeringPrincipal assigned, but in case we
// don't have one or if it's a SystemPrincipal, let's create it with OA
@ -92,7 +97,8 @@ RemoteWebNavigation.prototype = {
}
}
this._browser.frameLoader.remoteTab.maybeCancelContentJSExecution();
this._browser.frameLoader.remoteTab.maybeCancelContentJSExecution(
Ci.nsIRemoteTab.NAVIGATE_URL, {uri});
this._sendMessage("WebNavigation:LoadURI", {
uri: aURI,
flags: aLoadURIOptions.loadFlags,