Bug 1873967 - Remove DocGroup::TryToLoadIframesInBackground. r=sefeng

This is somewhat complex, untested, never shipped, and predates
fission.

Remove it to simplify the code.

Depends on D198183

Differential Revision: https://phabricator.services.mozilla.com/D198184
This commit is contained in:
Emilio Cobos Álvarez 2024-01-10 22:33:17 +00:00
parent b132d83211
commit 267ec889a9
11 changed files with 38 additions and 312 deletions

View file

@ -2192,19 +2192,6 @@ nsDocShell::HistoryPurged(int32_t aNumEntries) {
return NS_OK;
}
void nsDocShell::TriggerParentCheckDocShellIsEmpty() {
if (RefPtr<nsDocShell> parent = GetInProcessParentDocshell()) {
parent->DocLoaderIsEmpty(true);
}
if (GetBrowsingContext()->IsContentSubframe() &&
!GetBrowsingContext()->GetParentWindowContext()->IsInProcess()) {
if (BrowserChild* browserChild = BrowserChild::GetFrom(this)) {
mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents(
EmbedderElementEventType::NoEvent);
}
}
}
nsresult nsDocShell::HistoryEntryRemoved(int32_t aIndex) {
// These indices are used for fastback cache eviction, to determine
// which session history entries are candidates for content viewer
@ -7696,10 +7683,6 @@ nsresult nsDocShell::RestoreFromHistory() {
nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType,
nsIRequest* aRequest,
nsIStreamListener** aContentHandler) {
if (DocGroup::TryToLoadIframesInBackground()) {
ResetToFirstLoad();
}
*aContentHandler = nullptr;
if (!mTreeOwner || mIsBeingDestroyed) {
@ -7892,44 +7875,6 @@ nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType,
aOpenedChannel->SetNotificationCallbacks(this);
}
if (DocGroup::TryToLoadIframesInBackground()) {
if ((!mDocumentViewer || GetDocument()->IsInitialDocument()) &&
IsSubframe()) {
// At this point, we know we just created a new iframe document based on
// the response from the server, and we check if it's a cross-domain
// iframe
RefPtr<Document> newDoc = viewer->GetDocument();
RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
nsCOMPtr<nsIPrincipal> parentPrincipal =
parent->GetDocument()->NodePrincipal();
nsCOMPtr<nsIPrincipal> thisPrincipal = newDoc->NodePrincipal();
SiteIdentifier parentSite;
SiteIdentifier thisSite;
nsresult rv =
BasePrincipal::Cast(parentPrincipal)->GetSiteIdentifier(parentSite);
NS_ENSURE_SUCCESS(rv, rv);
rv = BasePrincipal::Cast(thisPrincipal)->GetSiteIdentifier(thisSite);
NS_ENSURE_SUCCESS(rv, rv);
if (!parentSite.Equals(thisSite)) {
if (profiler_thread_is_being_profiled_for_markers()) {
nsCOMPtr<nsIURI> prinURI;
BasePrincipal::Cast(thisPrincipal)->GetURI(getter_AddRefs(prinURI));
nsPrintfCString marker(
"Iframe loaded in background: %s",
nsContentUtils::TruncatedURLForDisplay(prinURI).get());
PROFILER_MARKER_TEXT("Background Iframe", DOM, {}, marker);
}
SetBackgroundLoadIframe();
}
}
}
NS_ENSURE_SUCCESS(Embed(viewer, nullptr, false,
ShouldAddToSessionHistory(finalURI, aOpenedChannel),
aOpenedChannel, previousURI),
@ -7939,14 +7884,6 @@ nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType,
MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetHasLoadedNonInitialDocument(true));
}
if (TreatAsBackgroundLoad()) {
nsCOMPtr<nsIRunnable> triggerParentCheckDocShell =
NewRunnableMethod("nsDocShell::TriggerParentCheckDocShellIsEmpty", this,
&nsDocShell::TriggerParentCheckDocShellIsEmpty);
nsresult rv = NS_DispatchToCurrentThread(triggerParentCheckDocShell);
NS_ENSURE_SUCCESS(rv, rv);
}
mSavedRefreshURIList = nullptr;
mSavingOldViewer = false;
mEODForCurrentDocument = false;

View file

@ -313,13 +313,6 @@ class nsDocShell final : public nsDocLoader,
LOCATION_CHANGE_SAME_DOCUMENT);
}
// This function is created exclusively for dom.background_loading_iframe is
// set. As soon as the current DocShell knows itself can be treated as
// background loading, it triggers the parent docshell to see if the parent
// document can fire load event earlier.
// TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
MOZ_CAN_RUN_SCRIPT_BOUNDARY void TriggerParentCheckDocShellIsEmpty();
nsresult HistoryEntryRemoved(int32_t aIndex);
// Notify Scroll observers when an async panning/zooming transform

View file

@ -122,11 +122,8 @@ DocGroup::DocGroup(BrowsingContextGroup* aBrowsingContextGroup,
DocGroup::~DocGroup() {
MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(mDocuments.IsEmpty());
if (mIframePostMessageQueue) {
FlushIframePostMessageQueue();
}
}
void DocGroup::SignalSlotChange(HTMLSlotElement& aSlot) {
MOZ_ASSERT(!mSignalSlotList.Contains(&aSlot));
mSignalSlotList.AppendElement(&aSlot);
@ -140,58 +137,6 @@ void DocGroup::SignalSlotChange(HTMLSlotElement& aSlot) {
sPendingDocGroups->AppendElement(this);
}
bool DocGroup::TryToLoadIframesInBackground() {
return !FissionAutostart() &&
StaticPrefs::dom_separate_event_queue_for_post_message_enabled() &&
StaticPrefs::dom_cross_origin_iframes_loaded_in_background();
}
nsresult DocGroup::QueueIframePostMessages(
already_AddRefed<nsIRunnable>&& aRunnable, uint64_t aWindowId) {
if (DocGroup::TryToLoadIframesInBackground()) {
if (!mIframePostMessageQueue) {
nsCOMPtr<nsISerialEventTarget> target = GetMainThreadSerialEventTarget();
mIframePostMessageQueue = ThrottledEventQueue::Create(
target, "Background Loading Iframe PostMessage Queue",
nsIRunnablePriority::PRIORITY_DEFERRED_TIMERS);
nsresult rv = mIframePostMessageQueue->SetIsPaused(true);
MOZ_ALWAYS_SUCCEEDS(rv);
}
// Ensure the queue is disabled. Unlike the postMessageEvent queue
// in BrowsingContextGroup, this postMessage queue should always
// be paused, because if we leave it open, the postMessage may get
// dispatched to an unloaded iframe
MOZ_ASSERT(mIframePostMessageQueue);
MOZ_ASSERT(mIframePostMessageQueue->IsPaused());
mIframesUsedPostMessageQueue.Insert(aWindowId);
mIframePostMessageQueue->Dispatch(std::move(aRunnable), NS_DISPATCH_NORMAL);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
void DocGroup::TryFlushIframePostMessages(uint64_t aWindowId) {
if (DocGroup::TryToLoadIframesInBackground()) {
mIframesUsedPostMessageQueue.Remove(aWindowId);
if (mIframePostMessageQueue && mIframesUsedPostMessageQueue.IsEmpty()) {
MOZ_ASSERT(mIframePostMessageQueue->IsPaused());
nsresult rv = mIframePostMessageQueue->SetIsPaused(true);
MOZ_ALWAYS_SUCCEEDS(rv);
FlushIframePostMessageQueue();
}
}
}
void DocGroup::FlushIframePostMessageQueue() {
nsCOMPtr<nsIRunnable> event;
while ((event = mIframePostMessageQueue->GetEvent())) {
SchedulerGroup::Dispatch(event.forget());
}
}
nsTArray<RefPtr<HTMLSlotElement>> DocGroup::MoveSignalSlotList() {
for (const RefPtr<HTMLSlotElement>& slot : mSignalSlotList) {
slot->RemovedFromSignalSlotList();

View file

@ -104,13 +104,6 @@ class DocGroup final {
// Returns true if any of its documents are active but not in the bfcache.
bool IsActive() const;
nsresult QueueIframePostMessages(already_AddRefed<nsIRunnable>&& aRunnable,
uint64_t aWindowId);
void TryFlushIframePostMessages(uint64_t aWindowId);
static bool TryToLoadIframesInBackground();
const nsID& AgentClusterId() const { return mAgentClusterId; }
bool IsEmpty() const { return mDocuments.IsEmpty(); }
@ -120,14 +113,11 @@ class DocGroup final {
~DocGroup();
void FlushIframePostMessageQueue();
nsCString mKey;
nsTArray<Document*> mDocuments;
RefPtr<mozilla::dom::CustomElementReactionsStack> mReactionsStack;
nsTArray<RefPtr<HTMLSlotElement>> mSignalSlotList;
RefPtr<BrowsingContextGroup> mBrowsingContextGroup;
RefPtr<mozilla::ThrottledEventQueue> mIframePostMessageQueue;
nsTHashSet<uint64_t> mIframesUsedPostMessageQueue;
// non-null if the JS execution for this docgroup is regulated with regards
// to worker threads. This should only be used when we are forcing serialized

View file

@ -259,35 +259,7 @@ void PostMessageEvent::Dispatch(nsGlobalWindowInner* aTargetWindow,
void PostMessageEvent::DispatchToTargetThread(ErrorResult& aError) {
nsCOMPtr<nsIRunnable> event = this;
// XXX Loading iframes in background isn't enabled by default and doesn't
// work with Fission at the moment.
if (DocGroup::TryToLoadIframesInBackground()) {
RefPtr<nsIDocShell> docShell = mTargetWindow->GetDocShell();
RefPtr<nsDocShell> dShell = nsDocShell::Cast(docShell);
// PostMessage that are added to the BrowsingContextGroup are the ones that
// can be flushed when the top level document is loaded.
// TreadAsBackgroundLoad DocShells are treated specially.
if (dShell) {
if (!dShell->TreatAsBackgroundLoad()) {
BrowsingContext* bc = mTargetWindow->GetBrowsingContext();
bc = bc ? bc->Top() : nullptr;
if (bc && bc->IsLoading()) {
// As long as the top level is loading, we can dispatch events to the
// queue because the queue will be flushed eventually
aError = bc->Group()->QueuePostMessageEvent(event.forget());
return;
}
} else if (mTargetWindow->GetExtantDoc() &&
mTargetWindow->GetExtantDoc()->GetReadyStateEnum() <
Document::READYSTATE_COMPLETE) {
mozilla::dom::DocGroup* docGroup = mTargetWindow->GetDocGroup();
aError = docGroup->QueueIframePostMessages(event.forget(),
dShell->GetOuterWindowID());
return;
}
}
} else if (StaticPrefs::dom_separate_event_queue_for_post_message_enabled()) {
if (StaticPrefs::dom_separate_event_queue_for_post_message_enabled()) {
BrowsingContext* bc = mTargetWindow->GetBrowsingContext();
bc = bc ? bc->Top() : nullptr;
if (bc && bc->IsLoading()) {

View file

@ -2127,20 +2127,11 @@ void nsGlobalWindowInner::FireFrameLoadEvent() {
event.mFlags.mBubbles = false;
event.mFlags.mCancelable = false;
if (mozilla::dom::DocGroup::TryToLoadIframesInBackground()) {
nsDocShell* ds = nsDocShell::Cast(GetDocShell());
if (ds && !ds->HasFakeOnLoadDispatched()) {
// Most of the time we could get a pres context to pass in here, but not
// always (i.e. if this window is not shown there won't be a pres context
// available). Since we're not firing a GUI event we don't need a pres
// context anyway so we just pass null as the pres context all the time.
EventDispatcher::Dispatch(element, nullptr, &event, nullptr, &status);
}
} else {
// Most of the time we could get a pres context to pass in here,
// but not always (i.e. if this window is not shown there won't
// be a pres context available). Since we're not firing a GUI
// event we don't need a pres context anyway so we just pass
// null as the pres context all the time here.
EventDispatcher::Dispatch(element, nullptr, &event, nullptr, &status);
}
return;
}

View file

@ -2681,15 +2681,6 @@ void nsGlobalWindowOuter::DetachFromDocShell(bool aIsBeingDiscarded) {
// later. Meanwhile, keep our weak reference to the script object
// so that it can be retrieved later (until it is finalized by the JS GC).
if (mDoc && DocGroup::TryToLoadIframesInBackground()) {
DocGroup* docGroup = GetDocGroup();
RefPtr<nsIDocShell> docShell = GetDocShell();
RefPtr<nsDocShell> dShell = nsDocShell::Cast(docShell);
if (dShell) {
docGroup->TryFlushIframePostMessages(dShell->GetOuterWindowID());
}
}
// Call FreeInnerObjects on all inner windows, not just the current
// one, since some could be held by WindowStateHolder objects that
// are GC-owned.

View file

@ -1022,55 +1022,6 @@ nsDocumentViewer::LoadComplete(nsresult aStatus) {
}
nsPIDOMWindowInner* innerWindow = window->GetCurrentInnerWindow();
RefPtr<DocGroup> docGroup = d->GetDocGroup();
// It is possible that the parent document's load event fires earlier than
// childs' load event, and in this case we need to fire some artificial
// load events to make the parent thinks the load events for child has
// been done
if (innerWindow && DocGroup::TryToLoadIframesInBackground()) {
nsTArray<nsCOMPtr<nsIDocShell>> docShells;
nsCOMPtr<nsIDocShell> container(mContainer);
if (container) {
int32_t count;
container->GetInProcessChildCount(&count);
// We first find all background loading iframes that need to
// fire artificial load events, and instead of firing them as
// soon as we find them, we store them in an array, to prevent
// us from skipping some events.
for (int32_t i = 0; i < count; ++i) {
nsCOMPtr<nsIDocShellTreeItem> child;
container->GetInProcessChildAt(i, getter_AddRefs(child));
nsCOMPtr<nsIDocShell> childIDocShell = do_QueryInterface(child);
RefPtr<nsDocShell> docShell = nsDocShell::Cast(childIDocShell);
if (docShell && docShell->TreatAsBackgroundLoad() &&
docShell->GetDocument()->GetReadyStateEnum() <
Document::READYSTATE_COMPLETE) {
docShells.AppendElement(childIDocShell);
}
}
// Re-iterate the stored docShells to fire artificial load events
for (size_t i = 0; i < docShells.Length(); ++i) {
RefPtr<nsDocShell> docShell = nsDocShell::Cast(docShells[i]);
if (docShell && docShell->TreatAsBackgroundLoad() &&
docShell->GetDocument()->GetReadyStateEnum() <
Document::READYSTATE_COMPLETE) {
nsEventStatus status = nsEventStatus_eIgnore;
WidgetEvent event(true, eLoad);
event.mFlags.mBubbles = false;
event.mFlags.mCancelable = false;
nsCOMPtr<nsPIDOMWindowOuter> win = docShell->GetWindow();
nsCOMPtr<Element> element = win->GetFrameElementInternal();
docShell->SetFakeOnLoadDispatched();
EventDispatcher::Dispatch(element, nullptr, &event, nullptr,
&status);
}
}
}
}
d->SetLoadEventFiring(true);
RefPtr<nsPresContext> presContext = mPresContext;
// MOZ_KnownLive due to bug 1506441
@ -1079,10 +1030,6 @@ nsDocumentViewer::LoadComplete(nsresult aStatus) {
nullptr, &status);
d->SetLoadEventFiring(false);
if (docGroup && docShell->TreatAsBackgroundLoad()) {
docGroup->TryFlushIframePostMessages(docShell->GetOuterWindowID());
}
if (timing) {
timing->NotifyLoadEventEnd();
}

View file

@ -4694,13 +4694,6 @@
value: false
mirror: always
# When this pref is set, parent documents may consider child iframes have
# loaded while they are still loading.
- name: dom.cross_origin_iframes_loaded_in_background
type: bool
value: false
mirror: always
# WebIDL test prefs.
- name: dom.webidl.test1
type: bool

View file

@ -114,9 +114,6 @@ nsDocLoader::nsDocLoader(bool aNotifyAboutBackgroundRequests)
mIsRestoringDocument(false),
mDontFlushLayout(false),
mIsFlushingLayout(false),
mTreatAsBackgroundLoad(false),
mHasFakeOnLoadDispatched(false),
mIsReadyToHandlePostMessage(false),
mDocumentOpenedButNotLoaded(false),
mNotifyAboutBackgroundRequests(aNotifyAboutBackgroundRequests) {
ClearInternalProgress();
@ -294,10 +291,6 @@ MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP nsDocLoader::Stop(void) {
return rv;
}
bool nsDocLoader::TreatAsBackgroundLoad() { return mTreatAsBackgroundLoad; }
void nsDocLoader::SetBackgroundLoadIframe() { mTreatAsBackgroundLoad = true; }
bool nsDocLoader::IsBusy() {
nsresult rv;
@ -337,15 +330,11 @@ bool nsDocLoader::IsBusy() {
uint32_t count = mChildList.Length();
for (uint32_t i = 0; i < count; i++) {
nsIDocumentLoader* loader = ChildAt(i);
// If 'dom.cross_origin_iframes_loaded_in_background' is set, the parent
// document treats cross domain iframes as background loading frame
if (loader && static_cast<nsDocLoader*>(loader)->TreatAsBackgroundLoad()) {
continue;
}
// This is a safe cast, because we only put nsDocLoader objects into the
// array
if (loader && static_cast<nsDocLoader*>(loader)->IsBusy()) return true;
if (loader && static_cast<nsDocLoader*>(loader)->IsBusy()) {
return true;
}
}
return false;
@ -813,17 +802,13 @@ void nsDocLoader::DocLoaderIsEmpty(bool aFlushLayout,
loadGroupStatus == NS_ERROR_PARSED_DATA_CACHED) {
// Can "doc" or "window" ever come back null here? Our state machine
// is complicated enough I wouldn't bet against it...
nsCOMPtr<Document> doc = do_GetInterface(GetAsSupports(this));
if (doc) {
if (nsCOMPtr<Document> doc = do_GetInterface(GetAsSupports(this))) {
doc->SetReadyStateInternal(Document::READYSTATE_COMPLETE,
/* updateTimingInformation = */ false);
doc->StopDocumentLoad();
nsCOMPtr<nsPIDOMWindowOuter> window = doc->GetWindow();
if (window && !doc->SkipLoadEventAfterClose()) {
if (!mozilla::dom::DocGroup::TryToLoadIframesInBackground() ||
(mozilla::dom::DocGroup::TryToLoadIframesInBackground() &&
!HasFakeOnLoadDispatched())) {
MOZ_LOG(gDocLoaderLog, LogLevel::Debug,
("DocLoader:%p: Firing load event for document.open\n",
this));
@ -859,7 +844,6 @@ void nsDocLoader::DocLoaderIsEmpty(bool aFlushLayout,
}
}
}
}
NotifyDoneWithOnload(parent);
}
}

View file

@ -121,18 +121,6 @@ class nsDocLoader : public nsIDocumentLoader,
void SetDocumentOpenedButNotLoaded() { mDocumentOpenedButNotLoaded = true; }
bool TreatAsBackgroundLoad();
void SetFakeOnLoadDispatched() { mHasFakeOnLoadDispatched = true; };
bool HasFakeOnLoadDispatched() { return mHasFakeOnLoadDispatched; };
void ResetToFirstLoad() {
mHasFakeOnLoadDispatched = false;
mIsReadyToHandlePostMessage = false;
mTreatAsBackgroundLoad = false;
};
uint32_t ChildCount() const { return mChildList.Length(); }
// TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
@ -333,12 +321,7 @@ class nsDocLoader : public nsIDocumentLoader,
flushing. */
bool mIsFlushingLayout;
bool mTreatAsBackgroundLoad;
private:
bool mHasFakeOnLoadDispatched;
bool mIsReadyToHandlePostMessage;
/**
* This flag indicates that the loader is waiting for completion of
* a document.open-triggered "document load". This is set when