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:
Kyle Machulis 2019-04-03 15:40:28 -07:00
Родитель 434596e533
Коммит 9f9436d028
14 изменённых файлов: 87 добавлений и 13 удалений

Просмотреть файл

@ -385,7 +385,8 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext)
mHasLoadedNonBlankURI(false),
mBlankTiming(false),
mTitleValidForCurrentURI(false),
mIsFrame(false) {
mIsFrame(false),
mSkipBrowsingContextDetachOnDestroy(false) {
mHistoryID.m0 = 0;
mHistoryID.m1 = 0;
mHistoryID.m2 = 0;
@ -5036,7 +5037,11 @@ nsDocShell::Destroy() {
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);

Просмотреть файл

@ -405,6 +405,10 @@ class nsDocShell final : public nsDocLoader,
// Clear the document's storage access flag if needed.
void MaybeClearStorageAccessFlag();
void SkipBrowsingContextDetach() {
mSkipBrowsingContextDetachOnDestroy = true;
}
private: // member functions
friend class nsDSURIContentListener;
friend class FramingChecker;
@ -1205,6 +1209,11 @@ class nsDocShell final : public nsDocLoader,
bool mTitleValidForCurrentURI : 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__ */

Просмотреть файл

@ -364,7 +364,7 @@ nsFrameLoader* nsFrameLoader::Create(Element* aOwner, BrowsingContext* aOpener,
/* static */
nsFrameLoader* nsFrameLoader::Create(
mozilla::dom::Element* aOwner,
mozilla::dom::Element* aOwner, BrowsingContext* aPreservedBrowsingContext,
const mozilla::dom::RemotenessOptions& aOptions) {
NS_ENSURE_TRUE(aOwner, nullptr);
// This version of Create is only called for Remoteness updates, so we can
@ -381,7 +381,12 @@ nsFrameLoader* nsFrameLoader::Create(
if (hasOpener) {
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);
return new nsFrameLoader(aOwner, context, aOptions);
}
@ -3490,3 +3495,22 @@ JSObject* nsFrameLoader::WrapObject(JSContext* cx,
FrameLoader_Binding::Wrap(cx, this, this, aGivenProto, &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::Document Document;
typedef mozilla::dom::BrowserParent BrowserParent;
typedef mozilla::dom::BrowsingContext BrowsingContext;
typedef mozilla::layout::RenderFrame RenderFrame;
public:
@ -106,6 +107,7 @@ class nsFrameLoader final : public nsStubMutationObserver,
// Called by nsFrameLoaderOwner::ChangeRemoteness when switching out
// FrameLoaders.
static nsFrameLoader* Create(mozilla::dom::Element* aOwner,
BrowsingContext* aPreservedBrowsingContext,
const mozilla::dom::RemotenessOptions& aOptions);
NS_DECLARE_STATIC_IID_ACCESSOR(NS_FRAMELOADER_IID)
@ -385,6 +387,8 @@ class nsFrameLoader final : public nsStubMutationObserver,
virtual JSObject* WrapObject(JSContext* cx,
JS::Handle<JSObject*> aGivenProto) override;
void SkipBrowsingContextDetach();
private:
nsFrameLoader(mozilla::dom::Element* aOwner,
mozilla::dom::BrowsingContext* aBrowsingContext,

Просмотреть файл

@ -32,8 +32,14 @@ nsFrameLoaderOwner::GetBrowsingContext() {
void nsFrameLoaderOwner::ChangeRemoteness(
const mozilla::dom::RemotenessOptions& aOptions, mozilla::ErrorResult& rv) {
RefPtr<mozilla::dom::BrowsingContext> bc;
// If we already have a Frameloader, destroy it.
if (mFrameLoader) {
bc = mFrameLoader->GetBrowsingContext();
// TODO pass in Cross-Origin-Load-Policy rules
mFrameLoader->SkipBrowsingContextDetach();
mFrameLoader->Destroy();
mFrameLoader = nullptr;
}
@ -43,7 +49,8 @@ void nsFrameLoaderOwner::ChangeRemoteness(
// owner.
RefPtr<Element> owner = do_QueryObject(this);
MOZ_ASSERT(owner);
mFrameLoader = nsFrameLoader::Create(owner, aOptions);
mFrameLoader = nsFrameLoader::Create(owner, bc, aOptions);
if (NS_WARN_IF(!mFrameLoader)) {
return;
}
@ -70,9 +77,8 @@ void nsFrameLoaderOwner::ChangeRemoteness(
// FrameLoader, fire an event to act like we've recreated ourselves, similar
// to what XULFrameElement does after rebinding to the tree.
// ChromeOnlyDispatch is turns on to make sure this isn't fired into content.
(new mozilla::AsyncEventDispatcher(owner,
NS_LITERAL_STRING("XULFrameLoaderCreated"),
mozilla::CanBubble::eYes,
mozilla::ChromeOnlyDispatch::eYes))
(new mozilla::AsyncEventDispatcher(
owner, NS_LITERAL_STRING("XULFrameLoaderCreated"),
mozilla::CanBubble::eYes, mozilla::ChromeOnlyDispatch::eYes))
->RunDOMEventWhenSafe();
}

Просмотреть файл

@ -182,6 +182,11 @@ IPCResult BrowserBridgeParent::RecvDispatchSynthesizedMouseEvent(
return IPC_OK();
}
IPCResult BrowserBridgeParent::RecvSkipBrowsingContextDetach() {
mBrowserParent->SkipBrowsingContextDetach();
return IPC_OK();
}
IPCResult BrowserBridgeParent::RecvActivate() {
mBrowserParent->Activate();
return IPC_OK();

Просмотреть файл

@ -59,6 +59,8 @@ class BrowserBridgeParent : public PBrowserBridgeParent {
mozilla::ipc::IPCResult RecvDispatchSynthesizedMouseEvent(
const WidgetMouseEvent& aEvent);
mozilla::ipc::IPCResult RecvSkipBrowsingContextDetach();
mozilla::ipc::IPCResult RecvActivate();
mozilla::ipc::IPCResult RecvDeactivate();

Просмотреть файл

@ -1052,6 +1052,17 @@ BrowserChild::~BrowserChild() {
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,
const ShowInfo& aInfo) {
if (!mDidLoadURLInit) {

Просмотреть файл

@ -555,6 +555,7 @@ class BrowserChild final : public BrowserChildBase,
mozilla::ipc::IPCResult RecvUpdateNativeWindowHandle(
const uintptr_t& aNewHandle);
virtual mozilla::ipc::IPCResult RecvSkipBrowsingContextDetach() override;
/**
* 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;
}
void BrowserParent::SkipBrowsingContextDetach() {
RefPtr<nsFrameLoader> fl = GetFrameLoader();
MOZ_ASSERT(fl);
fl->SkipBrowsingContextDetach();
}
mozilla::ipc::IPCResult BrowserParent::RecvLookUpDictionary(
const nsString& aText, nsTArray<FontRange>&& aFontRangeArray,
const bool& aIsVertical, const LayoutDeviceIntPoint& aPoint) {

Просмотреть файл

@ -678,6 +678,8 @@ class BrowserParent final : public PBrowserParent,
void NavigateByKey(bool aForward, bool aForDocumentNavigation);
void SkipBrowsingContextDetach();
protected:
bool ReceiveMessage(
const nsString& aMessage, bool aSync, ipc::StructuredCloneData* aData,

Просмотреть файл

@ -948,6 +948,7 @@ child:
*/
async GetContentBlockingLog() returns(nsCString log, bool success);
async SkipBrowsingContextDetach();
parent:
/** Records a history visit. */
async VisitURI(URIParams aURI, URIParams? aLastVisitedURI,

Просмотреть файл

@ -74,6 +74,8 @@ parent:
async Deactivate();
async SetIsUnderHiddenEmbedderElement(bool aIsUnderHiddenEmbedderElement);
async SkipBrowsingContextDetach();
};
} // namespace dom

Просмотреть файл

@ -82,10 +82,6 @@ void WindowGlobalParent::Init(const WindowGlobalInit& aInit) {
mBrowsingContext = CanonicalBrowsingContext::Cast(aInit.browsingContext());
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.
mBrowsingContext->RegisterWindowGlobal(this);