/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */
// In this case, we're not reparenting a frameloader, we're just destroying // our current one and creating a new one, so we can use ourselves as the // owner.
RefPtr<Element> owner = do_QueryObject(this);
MOZ_ASSERT(owner);
// When we destroy the original frameloader, it will stop blocking the parent // document's load event, and immediately trigger the load event if there are // no other blockers. Since we're going to be adding a new blocker as soon as // we recreate the frame loader, this is not what we want, so add our own // blocker until the process is complete.
Document* doc = owner->OwnerDoc();
doc->BlockOnload(); auto cleanup = MakeScopeExit([&]() { doc->UnblockOnload(false); });
// If we store the previous nsFrameLoader in the bfcache, this will be filled // with the SessionHistoryEntry which now owns the frame.
RefPtr<SessionHistoryEntry> bfcacheEntry;
{ // Introduce a script blocker to ensure no JS is executed during the // nsFrameLoader teardown & recreation process. Unload listeners will be run // for the previous document, and the load will be started for the new one, // at the end of this block.
nsAutoScriptBlocker sb;
// If we already have a Frameloader, destroy it, possibly preserving its // browsing context. if (mFrameLoader) { // Calling `GetBrowsingContext` here will force frameloader // initialization if it hasn't already happened, which we neither need // or want, so we use the initial (possibly pending) browsing context // directly, instead.
bc = mFrameLoader->GetMaybePendingBrowsingContext();
if (nsFocusManager* fm = nsFocusManager::GetFocusManager()) {
fm->FixUpFocusBeforeFrameLoaderChange(*owner, bc);
}
MOZ_ASSERT_IF(aOptions.mTryUseBFCache, aOptions.mReplaceBrowsingContext); if (aOptions.mTryUseBFCache && bc) {
bfcacheEntry = bc->Canonical()->GetActiveSessionHistoryEntry(); bool useBFCache = bfcacheEntry &&
bfcacheEntry == aOptions.mActiveSessionHistoryEntry &&
!bfcacheEntry->GetFrameLoader(); if (useBFCache) {
MOZ_LOG(gSHIPBFCacheLog, LogLevel::Debug,
("nsFrameLoaderOwner::ChangeRemotenessCommon: store the old " "page in bfcache"));
Unused << bc->SetIsInBFCache(true);
bfcacheEntry->SetFrameLoader(mFrameLoader); // Session history owns now the frameloader.
mFrameLoader = nullptr;
}
}
if (mFrameLoader) { if (aContextType == ChangeRemotenessContextType::PRESERVE) {
mFrameLoader->SetWillChangeProcess();
}
// Preserve the networkCreated status, as nsDocShells created after a // process swap may shouldn't change their dynamically-created status.
mFrameLoader->Destroy(aSwitchingInProgressLoad);
mFrameLoader = nullptr;
}
}
// Invoke the frame loader initialization callback to perform setup on our // new nsFrameLoader. This may cause our ErrorResult to become errored, so // double-check after calling.
aFrameLoaderInit(); if (NS_WARN_IF(aRv.Failed())) { return;
}
}
// Now that we have a new FrameLoader, we'll eventually need to reset // nsSubDocumentFrame to use the new one. We can delay doing this if we're // keeping our old frameloader around in the BFCache and the new frame hasn't // presented yet to continue painting the previous document. constbool retainPaint = bfcacheEntry && mFrameLoader->IsRemoteFrame(); if (!retainPaint) {
MOZ_LOG(
gSHIPBFCacheLog, LogLevel::Debug,
("Previous frameLoader not entering BFCache - not retaining paint data" "(bfcacheEntry=%p, isRemoteFrame=%d)",
bfcacheEntry.get(), mFrameLoader->IsRemoteFrame()));
}
void nsFrameLoaderOwner::ChangeFrameLoaderCommon(Element* aOwner, bool aRetainPaint) { // Now that we've got a new FrameLoader, we need to reset our // nsSubDocumentFrame to use the new FrameLoader. if (nsSubDocumentFrame* ourFrame = do_QueryFrame(aOwner->GetPrimaryFrame())) { auto retain = aRetainPaint ? nsSubDocumentFrame::RetainPaintData::Yes
: nsSubDocumentFrame::RetainPaintData::No;
ourFrame->ResetFrameLoader(retain);
}
if (aOwner->IsXULElement()) { // Assuming this element is a XULFrameElement, once we've reset our // 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.
mozilla::AsyncEventDispatcher::RunDOMEventWhenSafe(
*aOwner, u"XULFrameLoaderCreated"_ns, mozilla::CanBubble::eYes,
mozilla::ChromeOnlyDispatch::eYes);
}
if (mFrameLoader) {
mFrameLoader->PropagateIsUnderHiddenEmbedderElement(
!aOwner->GetPrimaryFrame() ||
!aOwner->GetPrimaryFrame()->StyleVisibility()->IsVisible());
}
}
void nsFrameLoaderOwner::UpdateFocusAndMouseEnterStateAfterFrameLoaderChange(
Element* aOwner) { // If the element is focused, or the current mouse over target then // we need to update that state for the new BrowserParent too. if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) { if (fm->GetFocusedElement() == aOwner) {
fm->FixUpFocusAfterFrameLoaderChange(*aOwner);
}
}
if (aOwner->GetPrimaryFrame()) {
EventStateManager* eventManager =
aOwner->GetPrimaryFrame()->PresContext()->EventStateManager();
eventManager->RecomputeMouseEnterStateForRemoteFrame(*aOwner);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.