Bug 1383333 - Keep track of foreground TabChildren (r=kanru)
authorBill McCloskey <billm@mozilla.com>
Wed, 19 Jul 2017 16:10:48 -0700
changeset 376850 7f426b4432ff060878c2238d60e04c11b1b2b97d
parent 376849 f3455c101b7a672cce40ecd64f332d5e6e2d9447
child 376851 2f1557d8ea437f5cd1fa31ea7914fdbd9ad4a46a
push id94187
push userwmccloskey@mozilla.com
push dateFri, 25 Aug 2017 17:28:56 +0000
treeherdermozilla-inbound@3519544711af [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskanru
bugs1383333
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1383333 - Keep track of foreground TabChildren (r=kanru) MozReview-Commit-ID: 1hT3BHzoZVA
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -159,16 +159,18 @@ 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";
 
+nsTArray<TabChild*>* TabChild::sActiveTabs;
+
 typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
 static TabChildMap* sTabChildren;
 StaticMutex sTabChildrenMutex;
 
 TabChildBase::TabChildBase()
   : mTabChildGlobal(nullptr)
 {
   mozilla::HoldJSObjects(this);
@@ -1112,16 +1114,24 @@ TabChild::ActorDestroy(ActorDestroyReaso
 
   if (GetTabId() != 0) {
     NestedTabChildMap().erase(GetTabId());
   }
 }
 
 TabChild::~TabChild()
 {
+  if (sActiveTabs) {
+    sActiveTabs->RemoveElement(this);
+    if (sActiveTabs->IsEmpty()) {
+      delete sActiveTabs;
+      sActiveTabs = nullptr;
+    }
+  }
+
   DestroyWindow();
 
   nsCOMPtr<nsIWebBrowser> webBrowser = do_QueryInterface(WebNavigation());
   if (webBrowser) {
     webBrowser->SetContainerWindow(nullptr);
   }
 
   if (mHistoryListener) {
@@ -2585,16 +2595,29 @@ TabChild::InternalSetDocShellIsActive(bo
         return;
       }
     }
 
     docShell->SetIsActive(aIsActive);
   }
 
   if (aIsActive) {
+    if (!sActiveTabs) {
+      sActiveTabs = new nsTArray<TabChild*>();
+    }
+    sActiveTabs->AppendElement(this);
+  } else {
+    if (sActiveTabs) {
+      sActiveTabs->RemoveElement(this);
+      // We don't delete sActiveTabs here when it's empty since that
+      // could cause a lot of churn. Instead, we wait until ~TabChild.
+    }
+  }
+
+  if (aIsActive) {
     MakeVisible();
 
     if (!docShell) {
       return;
     }
 
     // We don't use TabChildBase::GetPresShell() here because that would create
     // a content viewer if one doesn't exist yet. Creating a content viewer can
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -745,18 +745,34 @@ public:
   void RemovePendingDocShellBlocker();
 
   // The HANDLE object for the widget this TabChild in.
   WindowsHandle WidgetNativeData()
   {
     return mWidgetNativeData;
   }
 
+
   void MaybeDispatchCoalescedMouseMoveEvents();
 
+  static bool HasActiveTabs()
+  {
+    return sActiveTabs && !sActiveTabs->IsEmpty();
+  }
+
+  // Returns whichever TabChild is currently in the foreground. If there are
+  // multiple TabChilds in the foreground (due to multiple windows being open),
+  // this returns null. This should only be called if HasActiveTabs() returns
+  // true.
+  static const nsTArray<TabChild*>& GetActiveTabs()
+  {
+    MOZ_ASSERT(HasActiveTabs());
+    return *sActiveTabs;
+  }
+
 protected:
   virtual ~TabChild();
 
   virtual PRenderFrameChild* AllocPRenderFrameChild() override;
 
   virtual bool DeallocPRenderFrameChild(PRenderFrameChild* aFrame) override;
 
   virtual mozilla::ipc::IPCResult RecvDestroy() override;
@@ -942,15 +958,21 @@ private:
 
   bool mPendingDocShellIsActive;
   bool mPendingDocShellPreserveLayers;
   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 nsTArray<TabChild*>* sActiveTabs;
+
   DISALLOW_EVIL_CONSTRUCTORS(TabChild);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_TabChild_h