Bug 1540839 - Add ability to preserve browsing contexts between FrameLoaders; r=nika
When changing processes and therefore destroying/rebuilding frameloaders, add ability to keep the browsing context around and add it to the new frameloader. Differential Revision: https://phabricator.services.mozilla.com/D26267
This commit is contained in:
@@ -385,7 +385,8 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext)
|
|||||||
mHasLoadedNonBlankURI(false),
|
mHasLoadedNonBlankURI(false),
|
||||||
mBlankTiming(false),
|
mBlankTiming(false),
|
||||||
mTitleValidForCurrentURI(false),
|
mTitleValidForCurrentURI(false),
|
||||||
mIsFrame(false) {
|
mIsFrame(false),
|
||||||
|
mSkipBrowsingContextDetachOnDestroy(false) {
|
||||||
mHistoryID.m0 = 0;
|
mHistoryID.m0 = 0;
|
||||||
mHistoryID.m1 = 0;
|
mHistoryID.m1 = 0;
|
||||||
mHistoryID.m2 = 0;
|
mHistoryID.m2 = 0;
|
||||||
@@ -5036,7 +5037,11 @@ nsDocShell::Destroy() {
|
|||||||
mSessionHistory = nullptr;
|
mSessionHistory = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
mBrowsingContext->Detach();
|
// This will be skipped in cases where we want to preserve the browsing
|
||||||
|
// context between loads.
|
||||||
|
if (!mSkipBrowsingContextDetachOnDestroy) {
|
||||||
|
mBrowsingContext->Detach();
|
||||||
|
}
|
||||||
|
|
||||||
SetTreeOwner(nullptr);
|
SetTreeOwner(nullptr);
|
||||||
|
|
||||||
|
|||||||
@@ -405,6 +405,10 @@ class nsDocShell final : public nsDocLoader,
|
|||||||
// Clear the document's storage access flag if needed.
|
// Clear the document's storage access flag if needed.
|
||||||
void MaybeClearStorageAccessFlag();
|
void MaybeClearStorageAccessFlag();
|
||||||
|
|
||||||
|
void SkipBrowsingContextDetach() {
|
||||||
|
mSkipBrowsingContextDetachOnDestroy = true;
|
||||||
|
}
|
||||||
|
|
||||||
private: // member functions
|
private: // member functions
|
||||||
friend class nsDSURIContentListener;
|
friend class nsDSURIContentListener;
|
||||||
friend class FramingChecker;
|
friend class FramingChecker;
|
||||||
@@ -1205,6 +1209,11 @@ class nsDocShell final : public nsDocLoader,
|
|||||||
bool mTitleValidForCurrentURI : 1;
|
bool mTitleValidForCurrentURI : 1;
|
||||||
|
|
||||||
bool mIsFrame : 1;
|
bool mIsFrame : 1;
|
||||||
|
|
||||||
|
// If mSkipBrowsingContextDetachOnDestroy is set to true, then when the
|
||||||
|
// docshell is destroyed, the browsing context will not be detached. This is
|
||||||
|
// for cases where we want to preserve the BC for future use.
|
||||||
|
bool mSkipBrowsingContextDetachOnDestroy : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* nsDocShell_h__ */
|
#endif /* nsDocShell_h__ */
|
||||||
|
|||||||
@@ -364,7 +364,7 @@ nsFrameLoader* nsFrameLoader::Create(Element* aOwner, BrowsingContext* aOpener,
|
|||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
nsFrameLoader* nsFrameLoader::Create(
|
nsFrameLoader* nsFrameLoader::Create(
|
||||||
mozilla::dom::Element* aOwner,
|
mozilla::dom::Element* aOwner, BrowsingContext* aPreservedBrowsingContext,
|
||||||
const mozilla::dom::RemotenessOptions& aOptions) {
|
const mozilla::dom::RemotenessOptions& aOptions) {
|
||||||
NS_ENSURE_TRUE(aOwner, nullptr);
|
NS_ENSURE_TRUE(aOwner, nullptr);
|
||||||
// This version of Create is only called for Remoteness updates, so we can
|
// This version of Create is only called for Remoteness updates, so we can
|
||||||
@@ -381,7 +381,12 @@ nsFrameLoader* nsFrameLoader::Create(
|
|||||||
if (hasOpener) {
|
if (hasOpener) {
|
||||||
opener = aOptions.mOpener.Value().Value().get();
|
opener = aOptions.mOpener.Value().Value().get();
|
||||||
}
|
}
|
||||||
RefPtr<BrowsingContext> context = CreateBrowsingContext(aOwner, opener);
|
RefPtr<BrowsingContext> context;
|
||||||
|
if (aPreservedBrowsingContext) {
|
||||||
|
context = aPreservedBrowsingContext;
|
||||||
|
} else {
|
||||||
|
context = CreateBrowsingContext(aOwner, opener);
|
||||||
|
}
|
||||||
NS_ENSURE_TRUE(context, nullptr);
|
NS_ENSURE_TRUE(context, nullptr);
|
||||||
return new nsFrameLoader(aOwner, context, aOptions);
|
return new nsFrameLoader(aOwner, context, aOptions);
|
||||||
}
|
}
|
||||||
@@ -3490,3 +3495,22 @@ JSObject* nsFrameLoader::WrapObject(JSContext* cx,
|
|||||||
FrameLoader_Binding::Wrap(cx, this, this, aGivenProto, &result);
|
FrameLoader_Binding::Wrap(cx, this, this, aGivenProto, &result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nsFrameLoader::SkipBrowsingContextDetach() {
|
||||||
|
if (IsRemoteFrame()) {
|
||||||
|
// OOP Browser - Go directly over Browser Parent
|
||||||
|
if (mBrowserParent) {
|
||||||
|
Unused << mBrowserParent->SendSkipBrowsingContextDetach();
|
||||||
|
}
|
||||||
|
// OOP IFrame - Through Browser Bridge Parent, set on browser child
|
||||||
|
else if (mBrowserBridgeChild) {
|
||||||
|
Unused << mBrowserBridgeChild->SendSkipBrowsingContextDetach();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In process
|
||||||
|
RefPtr<nsDocShell> docshell = GetDocShell();
|
||||||
|
MOZ_ASSERT(docshell);
|
||||||
|
docshell->SkipBrowsingContextDetach();
|
||||||
|
}
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||||||
typedef mozilla::dom::PBrowserParent PBrowserParent;
|
typedef mozilla::dom::PBrowserParent PBrowserParent;
|
||||||
typedef mozilla::dom::Document Document;
|
typedef mozilla::dom::Document Document;
|
||||||
typedef mozilla::dom::BrowserParent BrowserParent;
|
typedef mozilla::dom::BrowserParent BrowserParent;
|
||||||
|
typedef mozilla::dom::BrowsingContext BrowsingContext;
|
||||||
typedef mozilla::layout::RenderFrame RenderFrame;
|
typedef mozilla::layout::RenderFrame RenderFrame;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -106,6 +107,7 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||||||
// Called by nsFrameLoaderOwner::ChangeRemoteness when switching out
|
// Called by nsFrameLoaderOwner::ChangeRemoteness when switching out
|
||||||
// FrameLoaders.
|
// FrameLoaders.
|
||||||
static nsFrameLoader* Create(mozilla::dom::Element* aOwner,
|
static nsFrameLoader* Create(mozilla::dom::Element* aOwner,
|
||||||
|
BrowsingContext* aPreservedBrowsingContext,
|
||||||
const mozilla::dom::RemotenessOptions& aOptions);
|
const mozilla::dom::RemotenessOptions& aOptions);
|
||||||
|
|
||||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_FRAMELOADER_IID)
|
NS_DECLARE_STATIC_IID_ACCESSOR(NS_FRAMELOADER_IID)
|
||||||
@@ -385,6 +387,8 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||||||
virtual JSObject* WrapObject(JSContext* cx,
|
virtual JSObject* WrapObject(JSContext* cx,
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
|
void SkipBrowsingContextDetach();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsFrameLoader(mozilla::dom::Element* aOwner,
|
nsFrameLoader(mozilla::dom::Element* aOwner,
|
||||||
mozilla::dom::BrowsingContext* aBrowsingContext,
|
mozilla::dom::BrowsingContext* aBrowsingContext,
|
||||||
|
|||||||
@@ -32,8 +32,14 @@ nsFrameLoaderOwner::GetBrowsingContext() {
|
|||||||
|
|
||||||
void nsFrameLoaderOwner::ChangeRemoteness(
|
void nsFrameLoaderOwner::ChangeRemoteness(
|
||||||
const mozilla::dom::RemotenessOptions& aOptions, mozilla::ErrorResult& rv) {
|
const mozilla::dom::RemotenessOptions& aOptions, mozilla::ErrorResult& rv) {
|
||||||
|
RefPtr<mozilla::dom::BrowsingContext> bc;
|
||||||
// If we already have a Frameloader, destroy it.
|
// If we already have a Frameloader, destroy it.
|
||||||
if (mFrameLoader) {
|
if (mFrameLoader) {
|
||||||
|
bc = mFrameLoader->GetBrowsingContext();
|
||||||
|
|
||||||
|
// TODO pass in Cross-Origin-Load-Policy rules
|
||||||
|
mFrameLoader->SkipBrowsingContextDetach();
|
||||||
|
|
||||||
mFrameLoader->Destroy();
|
mFrameLoader->Destroy();
|
||||||
mFrameLoader = nullptr;
|
mFrameLoader = nullptr;
|
||||||
}
|
}
|
||||||
@@ -43,7 +49,8 @@ void nsFrameLoaderOwner::ChangeRemoteness(
|
|||||||
// owner.
|
// owner.
|
||||||
RefPtr<Element> owner = do_QueryObject(this);
|
RefPtr<Element> owner = do_QueryObject(this);
|
||||||
MOZ_ASSERT(owner);
|
MOZ_ASSERT(owner);
|
||||||
mFrameLoader = nsFrameLoader::Create(owner, aOptions);
|
mFrameLoader = nsFrameLoader::Create(owner, bc, aOptions);
|
||||||
|
|
||||||
if (NS_WARN_IF(!mFrameLoader)) {
|
if (NS_WARN_IF(!mFrameLoader)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -70,9 +77,8 @@ void nsFrameLoaderOwner::ChangeRemoteness(
|
|||||||
// FrameLoader, fire an event to act like we've recreated ourselves, similar
|
// FrameLoader, fire an event to act like we've recreated ourselves, similar
|
||||||
// to what XULFrameElement does after rebinding to the tree.
|
// to what XULFrameElement does after rebinding to the tree.
|
||||||
// ChromeOnlyDispatch is turns on to make sure this isn't fired into content.
|
// ChromeOnlyDispatch is turns on to make sure this isn't fired into content.
|
||||||
(new mozilla::AsyncEventDispatcher(owner,
|
(new mozilla::AsyncEventDispatcher(
|
||||||
NS_LITERAL_STRING("XULFrameLoaderCreated"),
|
owner, NS_LITERAL_STRING("XULFrameLoaderCreated"),
|
||||||
mozilla::CanBubble::eYes,
|
mozilla::CanBubble::eYes, mozilla::ChromeOnlyDispatch::eYes))
|
||||||
mozilla::ChromeOnlyDispatch::eYes))
|
|
||||||
->RunDOMEventWhenSafe();
|
->RunDOMEventWhenSafe();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,6 +182,11 @@ IPCResult BrowserBridgeParent::RecvDispatchSynthesizedMouseEvent(
|
|||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IPCResult BrowserBridgeParent::RecvSkipBrowsingContextDetach() {
|
||||||
|
mBrowserParent->SkipBrowsingContextDetach();
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
IPCResult BrowserBridgeParent::RecvActivate() {
|
IPCResult BrowserBridgeParent::RecvActivate() {
|
||||||
mBrowserParent->Activate();
|
mBrowserParent->Activate();
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ class BrowserBridgeParent : public PBrowserBridgeParent {
|
|||||||
mozilla::ipc::IPCResult RecvDispatchSynthesizedMouseEvent(
|
mozilla::ipc::IPCResult RecvDispatchSynthesizedMouseEvent(
|
||||||
const WidgetMouseEvent& aEvent);
|
const WidgetMouseEvent& aEvent);
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult RecvSkipBrowsingContextDetach();
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvActivate();
|
mozilla::ipc::IPCResult RecvActivate();
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvDeactivate();
|
mozilla::ipc::IPCResult RecvDeactivate();
|
||||||
|
|||||||
@@ -1052,6 +1052,17 @@ BrowserChild::~BrowserChild() {
|
|||||||
mozilla::DropJSObjects(this);
|
mozilla::DropJSObjects(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult BrowserChild::RecvSkipBrowsingContextDetach() {
|
||||||
|
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
|
||||||
|
if (!docShell) {
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
RefPtr<nsDocShell> docshell = nsDocShell::Cast(docShell);
|
||||||
|
MOZ_ASSERT(docshell);
|
||||||
|
docshell->SkipBrowsingContextDetach();
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult BrowserChild::RecvLoadURL(const nsCString& aURI,
|
mozilla::ipc::IPCResult BrowserChild::RecvLoadURL(const nsCString& aURI,
|
||||||
const ShowInfo& aInfo) {
|
const ShowInfo& aInfo) {
|
||||||
if (!mDidLoadURLInit) {
|
if (!mDidLoadURLInit) {
|
||||||
|
|||||||
@@ -555,6 +555,7 @@ class BrowserChild final : public BrowserChildBase,
|
|||||||
mozilla::ipc::IPCResult RecvUpdateNativeWindowHandle(
|
mozilla::ipc::IPCResult RecvUpdateNativeWindowHandle(
|
||||||
const uintptr_t& aNewHandle);
|
const uintptr_t& aNewHandle);
|
||||||
|
|
||||||
|
virtual mozilla::ipc::IPCResult RecvSkipBrowsingContextDetach() override;
|
||||||
/**
|
/**
|
||||||
* Native widget remoting protocol for use with windowed plugins with e10s.
|
* Native widget remoting protocol for use with windowed plugins with e10s.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3744,6 +3744,12 @@ BrowserParent::StopApzAutoscroll(nsViewID aScrollId, uint32_t aPresShellId) {
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BrowserParent::SkipBrowsingContextDetach() {
|
||||||
|
RefPtr<nsFrameLoader> fl = GetFrameLoader();
|
||||||
|
MOZ_ASSERT(fl);
|
||||||
|
fl->SkipBrowsingContextDetach();
|
||||||
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult BrowserParent::RecvLookUpDictionary(
|
mozilla::ipc::IPCResult BrowserParent::RecvLookUpDictionary(
|
||||||
const nsString& aText, nsTArray<FontRange>&& aFontRangeArray,
|
const nsString& aText, nsTArray<FontRange>&& aFontRangeArray,
|
||||||
const bool& aIsVertical, const LayoutDeviceIntPoint& aPoint) {
|
const bool& aIsVertical, const LayoutDeviceIntPoint& aPoint) {
|
||||||
|
|||||||
@@ -678,6 +678,8 @@ class BrowserParent final : public PBrowserParent,
|
|||||||
|
|
||||||
void NavigateByKey(bool aForward, bool aForDocumentNavigation);
|
void NavigateByKey(bool aForward, bool aForDocumentNavigation);
|
||||||
|
|
||||||
|
void SkipBrowsingContextDetach();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ReceiveMessage(
|
bool ReceiveMessage(
|
||||||
const nsString& aMessage, bool aSync, ipc::StructuredCloneData* aData,
|
const nsString& aMessage, bool aSync, ipc::StructuredCloneData* aData,
|
||||||
|
|||||||
@@ -948,6 +948,7 @@ child:
|
|||||||
*/
|
*/
|
||||||
async GetContentBlockingLog() returns(nsCString log, bool success);
|
async GetContentBlockingLog() returns(nsCString log, bool success);
|
||||||
|
|
||||||
|
async SkipBrowsingContextDetach();
|
||||||
parent:
|
parent:
|
||||||
/** Records a history visit. */
|
/** Records a history visit. */
|
||||||
async VisitURI(URIParams aURI, URIParams? aLastVisitedURI,
|
async VisitURI(URIParams aURI, URIParams? aLastVisitedURI,
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ parent:
|
|||||||
async Deactivate();
|
async Deactivate();
|
||||||
|
|
||||||
async SetIsUnderHiddenEmbedderElement(bool aIsUnderHiddenEmbedderElement);
|
async SetIsUnderHiddenEmbedderElement(bool aIsUnderHiddenEmbedderElement);
|
||||||
|
|
||||||
|
async SkipBrowsingContextDetach();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|||||||
@@ -82,10 +82,6 @@ void WindowGlobalParent::Init(const WindowGlobalInit& aInit) {
|
|||||||
mBrowsingContext = CanonicalBrowsingContext::Cast(aInit.browsingContext());
|
mBrowsingContext = CanonicalBrowsingContext::Cast(aInit.browsingContext());
|
||||||
MOZ_ASSERT(mBrowsingContext);
|
MOZ_ASSERT(mBrowsingContext);
|
||||||
|
|
||||||
// XXX(nika): This won't be the case soon, but for now this is a good
|
|
||||||
// assertion as we can't switch processes. We should relax this eventually.
|
|
||||||
MOZ_ASSERT(mBrowsingContext->IsOwnedByProcess(processId));
|
|
||||||
|
|
||||||
// Attach ourself to the browsing context.
|
// Attach ourself to the browsing context.
|
||||||
mBrowsingContext->RegisterWindowGlobal(this);
|
mBrowsingContext->RegisterWindowGlobal(this);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user