Bug 1397426 - Rename TabChild's notion of "active tabs" to "visible tabs" and move logic into renderLayers. r=billm
MozReview-Commit-ID: 1bBNwew7uCk
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -6439,20 +6439,16 @@ nsDocShell::SetIsActive(bool aIsActive)
// We disallow setting active on chrome docshells.
if (mItemType == nsIDocShellTreeItem::typeChrome) {
return NS_ERROR_INVALID_ARG;
}
// Keep track ourselves.
mIsActive = aIsActive;
- if (TabChild* tc = TabChild::GetFrom(this)) {
- tc->OnDocShellActivated(aIsActive);
- }
-
// Clear prerender flag if necessary.
if (mIsPrerendered && aIsActive) {
MOZ_ASSERT(mPrerenderGlobalHistory.get());
mIsPrerendered = false;
nsCOMPtr<IHistory> history = services::GetHistoryService();
nsresult rv = NS_OK;
if (history) {
rv = mPrerenderGlobalHistory->ApplyChanges(history);
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -160,17 +160,17 @@ using mozilla::layers::GeckoContentContr
NS_IMPL_ISUPPORTS(ContentListener, nsIDOMEventListener)
NS_IMPL_ISUPPORTS(TabChildSHistoryListener,
nsISHistoryListener,
nsIPartialSHistoryListener,
nsISupportsWeakReference)
static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
-nsTHashtable<nsPtrHashKey<TabChild>>* TabChild::sActiveTabs;
+nsTHashtable<nsPtrHashKey<TabChild>>* TabChild::sVisibleTabs;
typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
static TabChildMap* sTabChildren;
StaticMutex sTabChildrenMutex;
TabChildBase::TabChildBase()
: mTabChildGlobal(nullptr)
{
@@ -1145,21 +1145,21 @@ TabChild::ActorDestroy(ActorDestroyReaso
if (GetTabId() != 0) {
NestedTabChildMap().erase(GetTabId());
}
}
TabChild::~TabChild()
{
- if (sActiveTabs) {
- sActiveTabs->RemoveEntry(this);
- if (sActiveTabs->IsEmpty()) {
- delete sActiveTabs;
- sActiveTabs = nullptr;
+ if (sVisibleTabs) {
+ sVisibleTabs->RemoveEntry(this);
+ if (sVisibleTabs->IsEmpty()) {
+ delete sVisibleTabs;
+ sVisibleTabs = nullptr;
}
}
DestroyWindow();
nsCOMPtr<nsIWebBrowser> webBrowser = do_QueryInterface(WebNavigation());
if (webBrowser) {
webBrowser->SetContainerWindow(nullptr);
@@ -2661,33 +2661,16 @@ TabChild::RemovePendingDocShellBlocker()
mPendingDocShellBlockers--;
if (!mPendingDocShellBlockers && mPendingDocShellReceivedMessage) {
mPendingDocShellReceivedMessage = false;
InternalSetDocShellIsActive(mPendingDocShellIsActive);
}
}
void
-TabChild::OnDocShellActivated(bool aIsActive)
-{
- if (aIsActive) {
- if (!sActiveTabs) {
- sActiveTabs = new nsTHashtable<nsPtrHashKey<TabChild>>();
- }
- sActiveTabs->PutEntry(this);
- } else {
- if (sActiveTabs) {
- sActiveTabs->RemoveEntry(this);
- // We don't delete sActiveTabs here when it's empty since that
- // could cause a lot of churn. Instead, we wait until ~TabChild.
- }
- }
-}
-
-void
TabChild::InternalSetDocShellIsActive(bool aIsActive)
{
// docshell is consider prerendered only if not active yet
mIsPrerendered &= !aIsActive;
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
if (docShell) {
docShell->SetIsActive(aIsActive);
@@ -2750,16 +2733,21 @@ TabChild::RecvRenderLayers(const bool& a
// notification to fire in the parent (so that it knows that the child has
// updated its epoch). ForcePaintNoOp does that.
if (IPCOpen()) {
Unused << SendForcePaintNoOp(mLayerObserverEpoch);
return IPC_OK();
}
}
+ if (!sVisibleTabs) {
+ sVisibleTabs = new nsTHashtable<nsPtrHashKey<TabChild>>();
+ }
+ sVisibleTabs->PutEntry(this);
+
MakeVisible();
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
if (!docShell) {
return IPC_OK();
}
// We don't use TabChildBase::GetPresShell() here because that would create
@@ -2788,16 +2776,22 @@ TabChild::RecvRenderLayers(const bool& a
if (nsView* view = vm->GetRootView()) {
presShell->Paint(view, view->GetBounds(),
nsIPresShell::PAINT_LAYERS);
}
}
APZCCallbackHelper::SuppressDisplayport(false, presShell);
}
} else {
+ if (sVisibleTabs) {
+ sVisibleTabs->RemoveEntry(this);
+ // We don't delete sVisibleTabs here when it's empty since that
+ // could cause a lot of churn. Instead, we wait until ~TabChild.
+ }
+
MakeHidden();
}
return IPC_OK();
}
mozilla::ipc::IPCResult
TabChild::RecvNavigateByKey(const bool& aForward, const bool& aForDocumentNavigation)
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -576,18 +576,16 @@ public:
* Signal to this TabChild that it should be made visible:
* activated widget, retained layer tree, etc. (Respectively,
* made not visible.)
*/
void MakeVisible();
void MakeHidden();
bool IsVisible();
- void OnDocShellActivated(bool aIsActive);
-
nsIContentChild* Manager() const { return mManager; }
static inline TabChild*
GetFrom(nsIDocShell* aDocShell)
{
if (!aDocShell) {
return nullptr;
}
@@ -773,30 +771,30 @@ public:
// dispatching some mouse events other than mousemove.
void FlushAllCoalescedMouseData();
void ProcessPendingCoalescedMouseDataAndDispatchEvents();
void HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId);
- static bool HasActiveTabs()
+ static bool HasVisibleTabs()
{
- return sActiveTabs && !sActiveTabs->IsEmpty();
+ return sVisibleTabs && !sVisibleTabs->IsEmpty();
}
- // Returns the set of TabChilds that are currently in the foreground. There
- // can be multiple foreground TabChilds if Firefox has multiple windows
- // open. There can also be zero foreground TabChilds if the foreground tab is
- // in a different content process. Note that this function should only be
- // called if HasActiveTabs() returns true.
- static const nsTHashtable<nsPtrHashKey<TabChild>>& GetActiveTabs()
+ // Returns the set of TabChilds that are currently rendering layers. There
+ // can be multiple TabChilds in this state if Firefox has multiple windows
+ // open or is warming tabs up. There can also be zero TabChilds in this
+ // state. Note that this function should only be called if HasVisibleTabs()
+ // returns true.
+ static const nsTHashtable<nsPtrHashKey<TabChild>>& GetVisibleTabs()
{
- MOZ_ASSERT(HasActiveTabs());
- return *sActiveTabs;
+ MOZ_ASSERT(HasVisibleTabs());
+ return *sVisibleTabs;
}
protected:
virtual ~TabChild();
virtual PRenderFrameChild* AllocPRenderFrameChild() override;
virtual bool DeallocPRenderFrameChild(PRenderFrameChild* aFrame) override;
@@ -986,21 +984,21 @@ private:
bool mCoalesceMouseMoveEvents;
bool mPendingDocShellIsActive;
bool mPendingDocShellReceivedMessage;
uint32_t mPendingDocShellBlockers;
WindowsHandle mWidgetNativeData;
- // This state is used to keep track of the current active tabs (the ones in
- // the foreground). There may be more than one if there are multiple browser
- // windows open. There may be none if this process does not host any
- // foreground tabs.
- static nsTHashtable<nsPtrHashKey<TabChild>>* sActiveTabs;
+ // This state is used to keep track of the current visible tabs (the ones rendering
+ // layers). There may be more than one if there are multiple browser windows open, or
+ // tabs are being warmed up. There may be none if this process does not host any
+ // visible or warming tabs.
+ static nsTHashtable<nsPtrHashKey<TabChild>>* sVisibleTabs;
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_TabChild_h
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -657,18 +657,18 @@ BackgroundChildImpl::RecvDispatchLocalSt
}
bool
BackgroundChildImpl::GetMessageSchedulerGroups(const Message& aMsg, SchedulerGroupSet& aGroups)
{
if (aMsg.type() == layout::PVsync::MessageType::Msg_Notify__ID) {
MOZ_ASSERT(NS_IsMainThread());
aGroups.Clear();
- if (dom::TabChild::HasActiveTabs()) {
- for (auto iter = dom::TabChild::GetActiveTabs().ConstIter();
+ if (dom::TabChild::HasVisibleTabs()) {
+ for (auto iter = dom::TabChild::GetVisibleTabs().ConstIter();
!iter.Done(); iter.Next()) {
aGroups.Put(iter.Get()->GetKey()->TabGroup());
}
}
return true;
}
return false;
--- a/xpcom/threads/LabeledEventQueue.cpp
+++ b/xpcom/threads/LabeledEventQueue.cpp
@@ -166,46 +166,46 @@ LabeledEventQueue::GetEvent(EventPriorit
MOZ_ASSERT(entry.mRunnable.get());
return entry.mRunnable.forget();
}
if (!sCurrentSchedulerGroup) {
return nullptr;
}
- // Move active tabs to the front of the queue. The mAvoidActiveTabCount field
- // prevents us from preferentially processing events from active tabs twice in
+ // Move visible tabs to the front of the queue. The mAvoidVisibleTabCount field
+ // prevents us from preferentially processing events from visible tabs twice in
// a row. This scheme is designed to prevent starvation.
- if (TabChild::HasActiveTabs() && mAvoidActiveTabCount <= 0) {
- for (auto iter = TabChild::GetActiveTabs().ConstIter();
+ if (TabChild::HasVisibleTabs() && mAvoidVisibleTabCount <= 0) {
+ for (auto iter = TabChild::GetVisibleTabs().ConstIter();
!iter.Done(); iter.Next()) {
SchedulerGroup* group = iter.Get()->GetKey()->TabGroup();
if (!group->isInList() || group == sCurrentSchedulerGroup) {
continue;
}
- // For each active tab we move to the front of the queue, we have to
- // process two SchedulerGroups (the active tab and another one, presumably
- // a background group) before we prioritize active tabs again.
- mAvoidActiveTabCount += 2;
+ // For each visible tab we move to the front of the queue, we have to
+ // process two SchedulerGroups (the visible tab and another one, presumably
+ // a background group) before we prioritize visible tabs again.
+ mAvoidVisibleTabCount += 2;
// We move |group| right before sCurrentSchedulerGroup and then set
// sCurrentSchedulerGroup to group.
MOZ_ASSERT(group != sCurrentSchedulerGroup);
group->removeFrom(*sSchedulerGroups);
sCurrentSchedulerGroup->setPrevious(group);
sCurrentSchedulerGroup = group;
}
}
// Iterate over each SchedulerGroup once, starting at sCurrentSchedulerGroup.
SchedulerGroup* firstGroup = sCurrentSchedulerGroup;
SchedulerGroup* group = firstGroup;
do {
- mAvoidActiveTabCount--;
+ mAvoidVisibleTabCount--;
RunnableEpochQueue& queue = group->GetQueue(mPriority);
if (queue.IsEmpty()) {
// This can happen if |group| is in a different LabeledEventQueue than |this|.
group = NextSchedulerGroup(group);
continue;
}
--- a/xpcom/threads/LabeledEventQueue.h
+++ b/xpcom/threads/LabeledEventQueue.h
@@ -132,19 +132,19 @@ private:
static LinkedList<SchedulerGroup>* sSchedulerGroups;
static size_t sLabeledEventQueueCount;
static SchedulerGroup* sCurrentSchedulerGroup;
RunnableEpochQueue mUnlabeled;
EpochQueue mEpochs;
size_t mNumEvents = 0;
- // Number of SchedulerGroups that must be processed before we prioritize an
- // active tab. This field is designed to guarantee a 1:1 interleaving between
+ // Number of SchedulerGroups that must be processed before we prioritize a
+ // visible tab. This field is designed to guarantee a 1:1 interleaving between
// foreground and background SchedulerGroups. For details, see its usage in
// LabeledEventQueue.cpp.
- int64_t mAvoidActiveTabCount = 0;
+ int64_t mAvoidVisibleTabCount = 0;
EventPriority mPriority;
};
} // namespace mozilla
#endif // mozilla_LabeledEventQueue_h