зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1598775 - Ensure postMessage related optimizations during page load work also in Fission, r=farre
Bug 1534012 added a test for postMessage during load and that revealed that mLoading flag isn't always updated soon enough, so add BrowsingContext::IsLoading which checks also possible local loading status. Depends on D54754 Differential Revision: https://phabricator.services.mozilla.com/D54836 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
e2d1797ad5
Коммит
7f0bc5d8d8
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/dom/BrowsingContextBinding.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/Location.h"
|
||||
#include "mozilla/dom/LocationBinding.h"
|
||||
|
@ -1349,17 +1350,40 @@ void BrowsingContext::DidSetIsPopupSpam() {
|
|||
}
|
||||
}
|
||||
|
||||
bool BrowsingContext::IsLoading() {
|
||||
if (GetLoading()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we're in the same process as the page, we're possibly just
|
||||
// updating the flag.
|
||||
nsIDocShell* shell = GetDocShell();
|
||||
if (shell) {
|
||||
Document* doc = shell->GetDocument();
|
||||
return doc && doc->GetReadyStateEnum() < Document::READYSTATE_COMPLETE;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void BrowsingContext::DidSetLoading() {
|
||||
if (!mLoading) {
|
||||
while (!mDeprioritizedLoadRunner.isEmpty()) {
|
||||
nsCOMPtr<nsIRunnable> runner = mDeprioritizedLoadRunner.popFirst();
|
||||
NS_DispatchToCurrentThread(runner.forget());
|
||||
}
|
||||
if (mLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (!mDeprioritizedLoadRunner.isEmpty()) {
|
||||
nsCOMPtr<nsIRunnable> runner = mDeprioritizedLoadRunner.popFirst();
|
||||
NS_DispatchToCurrentThread(runner.forget());
|
||||
}
|
||||
|
||||
if (StaticPrefs::dom_separate_event_queue_for_post_message_enabled() &&
|
||||
Top() == this) {
|
||||
Group()->FlushPostMessageEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void BrowsingContext::AddDeprioritizedLoadRunner(nsIRunnable* aRunner) {
|
||||
MOZ_ASSERT(mLoading);
|
||||
MOZ_ASSERT(IsLoading());
|
||||
MOZ_ASSERT(Top() == this);
|
||||
|
||||
RefPtr<DeprioritizedLoadRunner> runner = new DeprioritizedLoadRunner(aRunner);
|
||||
|
|
|
@ -272,6 +272,8 @@ class BrowsingContext : public nsISupports,
|
|||
|
||||
bool InRDMPane() { return mInRDMPane; }
|
||||
|
||||
bool IsLoading();
|
||||
|
||||
// Using the rules for choosing a browsing context we try to find
|
||||
// the browsing context with the given name in the set of
|
||||
// transitively reachable browsing contexts. Performs access control
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "mozilla/dom/BrowsingContextGroup.h"
|
||||
#include "mozilla/dom/BrowsingContextBinding.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "mozilla/ThrottledEventQueue.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -133,6 +135,46 @@ JSObject* BrowsingContextGroup::WrapObject(JSContext* aCx,
|
|||
return BrowsingContextGroup_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsresult BrowsingContextGroup::QueuePostMessageEvent(
|
||||
already_AddRefed<nsIRunnable>&& aRunnable) {
|
||||
if (StaticPrefs::dom_separate_event_queue_for_post_message_enabled()) {
|
||||
if (!mPostMessageEventQueue) {
|
||||
nsCOMPtr<nsISerialEventTarget> target = GetMainThreadSerialEventTarget();
|
||||
mPostMessageEventQueue = ThrottledEventQueue::Create(
|
||||
target, "PostMessage Queue",
|
||||
nsIRunnablePriority::PRIORITY_DEFERRED_TIMERS);
|
||||
nsresult rv = mPostMessageEventQueue->SetIsPaused(false);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
}
|
||||
|
||||
// Ensure the queue is enabled
|
||||
if (mPostMessageEventQueue->IsPaused()) {
|
||||
nsresult rv = mPostMessageEventQueue->SetIsPaused(false);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
}
|
||||
|
||||
if (mPostMessageEventQueue) {
|
||||
mPostMessageEventQueue->Dispatch(std::move(aRunnable),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void BrowsingContextGroup::FlushPostMessageEvents() {
|
||||
if (StaticPrefs::dom_separate_event_queue_for_post_message_enabled()) {
|
||||
if (mPostMessageEventQueue) {
|
||||
nsresult rv = mPostMessageEventQueue->SetIsPaused(true);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
nsCOMPtr<nsIRunnable> event;
|
||||
while ((event = mPostMessageEventQueue->GetEvent())) {
|
||||
NS_DispatchToMainThread(event.forget());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static StaticRefPtr<BrowsingContextGroup> sChromeGroup;
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "nsWrapperCache.h"
|
||||
|
||||
namespace mozilla {
|
||||
class ThrottledEventQueue;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class BrowsingContext;
|
||||
|
@ -108,6 +110,10 @@ class BrowsingContextGroup final : public nsWrapperCache {
|
|||
}
|
||||
}
|
||||
|
||||
nsresult QueuePostMessageEvent(already_AddRefed<nsIRunnable>&& aRunnable);
|
||||
|
||||
void FlushPostMessageEvents();
|
||||
|
||||
static BrowsingContextGroup* GetChromeGroup();
|
||||
|
||||
private:
|
||||
|
@ -129,6 +135,10 @@ class BrowsingContextGroup final : public nsWrapperCache {
|
|||
|
||||
// Map of cached contexts that need to stay alive due to bfcache.
|
||||
nsTHashtable<nsRefPtrHashKey<BrowsingContext>> mCachedContexts;
|
||||
|
||||
// A queue to store postMessage events during page load, the queue will be
|
||||
// flushed once the page is loaded
|
||||
RefPtr<mozilla::ThrottledEventQueue> mPostMessageEventQueue;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -255,46 +255,6 @@ bool TabGroup::IsBackground() const {
|
|||
return mForegroundCount == 0;
|
||||
}
|
||||
|
||||
nsresult TabGroup::QueuePostMessageEvent(
|
||||
already_AddRefed<nsIRunnable>&& aRunnable) {
|
||||
if (StaticPrefs::dom_separate_event_queue_for_post_message_enabled()) {
|
||||
if (!mPostMessageEventQueue) {
|
||||
nsCOMPtr<nsISerialEventTarget> target = GetMainThreadSerialEventTarget();
|
||||
mPostMessageEventQueue = ThrottledEventQueue::Create(
|
||||
target, "PostMessage Queue",
|
||||
nsIRunnablePriority::PRIORITY_DEFERRED_TIMERS);
|
||||
nsresult rv = mPostMessageEventQueue->SetIsPaused(false);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
}
|
||||
|
||||
// Ensure the queue is enabled
|
||||
if (mPostMessageEventQueue->IsPaused()) {
|
||||
nsresult rv = mPostMessageEventQueue->SetIsPaused(false);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
}
|
||||
|
||||
if (mPostMessageEventQueue) {
|
||||
mPostMessageEventQueue->Dispatch(std::move(aRunnable),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void TabGroup::FlushPostMessageEvents() {
|
||||
if (StaticPrefs::dom_separate_event_queue_for_post_message_enabled()) {
|
||||
if (mPostMessageEventQueue) {
|
||||
nsresult rv = mPostMessageEventQueue->SetIsPaused(true);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
nsCOMPtr<nsIRunnable> event;
|
||||
while ((event = mPostMessageEventQueue->GetEvent())) {
|
||||
Dispatch(TaskCategory::Other, event.forget());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t TabGroup::Count(bool aActiveOnly) const {
|
||||
if (!aActiveOnly) {
|
||||
return mDocGroups.Count();
|
||||
|
|
|
@ -130,10 +130,6 @@ class TabGroup final : public SchedulerGroup,
|
|||
// can be throttled.
|
||||
static bool HasOnlyThrottableTabs();
|
||||
|
||||
nsresult QueuePostMessageEvent(already_AddRefed<nsIRunnable>&& aRunnable);
|
||||
|
||||
void FlushPostMessageEvents();
|
||||
|
||||
private:
|
||||
virtual AbstractThread* AbstractMainThreadForImpl(
|
||||
TaskCategory aCategory) override;
|
||||
|
@ -157,10 +153,6 @@ class TabGroup final : public SchedulerGroup,
|
|||
uint32_t mForegroundCount;
|
||||
|
||||
static LinkedList<TabGroup>* sTabGroups;
|
||||
|
||||
// A queue to store postMessage events during page load, the queue will be
|
||||
// flushed once the page is loaded
|
||||
RefPtr<mozilla::ThrottledEventQueue> mPostMessageEventQueue;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -2564,18 +2564,6 @@ void nsGlobalWindowInner::SetActiveLoadingState(bool aIsLoading) {
|
|||
GetBrowsingContext()->SetLoading(aIsLoading);
|
||||
}
|
||||
|
||||
if (StaticPrefs::dom_separate_event_queue_for_post_message_enabled()) {
|
||||
if (!aIsLoading) {
|
||||
Document* doc = GetExtantDoc();
|
||||
if (doc) {
|
||||
if (doc->IsTopLevelContentDocument()) {
|
||||
mozilla::dom::TabGroup* tabGroup = doc->GetDocGroup()->GetTabGroup();
|
||||
tabGroup->FlushPostMessageEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!nsGlobalWindowInner::Cast(this)->IsChromeWindow()) {
|
||||
mTimeoutManager->SetLoading(aIsLoading);
|
||||
}
|
||||
|
|
|
@ -219,6 +219,7 @@
|
|||
#include "nsXULControllers.h"
|
||||
#include "mozilla/dom/AudioContext.h"
|
||||
#include "mozilla/dom/BrowserElementDictionariesBinding.h"
|
||||
#include "mozilla/dom/BrowsingContextGroup.h"
|
||||
#include "mozilla/dom/cache/CacheStorage.h"
|
||||
#include "mozilla/dom/Console.h"
|
||||
#include "mozilla/dom/Fetch.h"
|
||||
|
@ -6076,33 +6077,33 @@ void nsGlobalWindowOuter::PostMessageMozOuter(JSContext* aCx,
|
|||
return;
|
||||
}
|
||||
|
||||
if (mDoc &&
|
||||
StaticPrefs::dom_separate_event_queue_for_post_message_enabled() &&
|
||||
if (StaticPrefs::dom_separate_event_queue_for_post_message_enabled() &&
|
||||
!DocGroup::TryToLoadIframesInBackground()) {
|
||||
Document* doc = mDoc->GetTopLevelContentDocument();
|
||||
if (doc && doc->GetReadyStateEnum() < Document::READYSTATE_COMPLETE) {
|
||||
BrowsingContext* bc = 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
|
||||
mozilla::dom::TabGroup* tabGroup = TabGroup();
|
||||
aError = tabGroup->QueuePostMessageEvent(event.forget());
|
||||
aError = bc->Group()->QueuePostMessageEvent(event.forget());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mDoc && DocGroup::TryToLoadIframesInBackground()) {
|
||||
if (DocGroup::TryToLoadIframesInBackground()) {
|
||||
RefPtr<nsIDocShell> docShell = GetDocShell();
|
||||
RefPtr<nsDocShell> dShell = nsDocShell::Cast(docShell);
|
||||
|
||||
// PostMessage that are added to the tabGroup are the ones that
|
||||
// can be flushed when the top level document is loaded
|
||||
// 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()) {
|
||||
Document* doc = mDoc->GetTopLevelContentDocument();
|
||||
if (doc && doc->GetReadyStateEnum() < Document::READYSTATE_COMPLETE) {
|
||||
BrowsingContext* bc = 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
|
||||
mozilla::dom::TabGroup* tabGroup = TabGroup();
|
||||
aError = tabGroup->QueuePostMessageEvent(event.forget());
|
||||
aError = bc->Group()->QueuePostMessageEvent(event.forget());
|
||||
return;
|
||||
}
|
||||
} else if (mDoc->GetReadyStateEnum() < Document::READYSTATE_COMPLETE) {
|
||||
|
|
|
@ -585,7 +585,7 @@ void MainThreadFetchResolver::OnResponseAvailableInternal(
|
|||
nsCOMPtr<nsPIDOMWindowInner> inner = do_QueryInterface(go);
|
||||
BrowsingContext* bc = inner ? inner->GetBrowsingContext() : nullptr;
|
||||
bc = bc ? bc->Top() : nullptr;
|
||||
if (bc && bc->GetLoading()) {
|
||||
if (bc && bc->IsLoading()) {
|
||||
bc->AddDeprioritizedLoadRunner(
|
||||
new ResolveFetchPromise(mPromise, mResponse));
|
||||
} else {
|
||||
|
|
|
@ -2310,7 +2310,7 @@ void XMLHttpRequestMainThread::ChangeStateToDone(bool aWasSync) {
|
|||
nsPIDOMWindowInner* owner = GetOwner();
|
||||
BrowsingContext* bc = owner ? owner->GetBrowsingContext() : nullptr;
|
||||
bc = bc ? bc->Top() : nullptr;
|
||||
if (bc && bc->GetLoading()) {
|
||||
if (bc && bc->IsLoading()) {
|
||||
MOZ_ASSERT(!mDelayedDoneNotifier);
|
||||
RefPtr<XMLHttpRequestDoneNotifier> notifier =
|
||||
new XMLHttpRequestDoneNotifier(this);
|
||||
|
|
Загрузка…
Ссылка в новой задаче