Bug 1607624 - Migrating UnselectedTabHover to use JSWindowActor r=NeilDeakin
authorBernard Igiri <bigiri@mozilla.com>
Fri, 06 Mar 2020 17:29:03 +0000
changeset 517643 8a2e9f0301bd42138a8235a5a4cd0335fe426d3d
parent 517641 f58f490db16763834d282651e5848e3f67a0df1e
child 517644 ca857d55b59e124490c0fa3e2cf05d3aa7ff4041
push id37199
push useropoprus@mozilla.com
push dateTue, 10 Mar 2020 03:43:44 +0000
treeherdermozilla-central@6f21f98dcfcd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersNeilDeakin
bugs1607624
milestone75.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 1607624 - Migrating UnselectedTabHover to use JSWindowActor r=NeilDeakin Differential Revision: https://phabricator.services.mozilla.com/D64388
toolkit/actors/UnselectedTabHoverChild.jsm
toolkit/actors/UnselectedTabHoverParent.jsm
toolkit/actors/moz.build
toolkit/content/tests/browser/browser_resume_bkg_video_on_tab_hover.js
toolkit/content/widgets/browser-custom-element.js
toolkit/modules/ActorManagerParent.jsm
--- a/toolkit/actors/UnselectedTabHoverChild.jsm
+++ b/toolkit/actors/UnselectedTabHoverChild.jsm
@@ -1,28 +1,25 @@
 /* vim: set ts=2 sw=2 sts=2 et 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/. */
 "use strict";
 
 var EXPORTED_SYMBOLS = ["UnselectedTabHoverChild"];
 
-const { ActorChild } = ChromeUtils.import(
-  "resource://gre/modules/ActorChild.jsm"
-);
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
-class UnselectedTabHoverChild extends ActorChild {
+class UnselectedTabHoverChild extends JSWindowActorChild {
   receiveMessage(message) {
     Services.obs.notifyObservers(
-      this.content,
+      this.contentWindow,
       "unselected-tab-hover",
       message.data.hovered
     );
   }
 
   handleEvent(event) {
-    this.mm.sendAsyncMessage("UnselectedTabHover:Toggle", {
+    this.sendAsyncMessage("UnselectedTabHover:Toggle", {
       enable: event.type == "UnselectedTabHover:Enable",
     });
   }
 }
new file mode 100644
--- /dev/null
+++ b/toolkit/actors/UnselectedTabHoverParent.jsm
@@ -0,0 +1,18 @@
+/* vim: set ts=2 sw=2 sts=2 et 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/. */
+"use strict";
+
+var EXPORTED_SYMBOLS = ["UnselectedTabHoverParent"];
+
+class UnselectedTabHoverParent extends JSWindowActorParent {
+  receiveMessage(message) {
+    const topBrowsingContext = this.manager.browsingContext.top;
+    const browser = topBrowsingContext.embedderElement;
+    if (!browser) {
+      return;
+    }
+    browser.shouldHandleUnselectedTabHover = message.data.enable;
+  }
+}
--- a/toolkit/actors/moz.build
+++ b/toolkit/actors/moz.build
@@ -48,16 +48,17 @@ FINAL_TARGET_FILES.actors += [
     'PrintingChild.jsm',
     'PurgeSessionHistoryChild.jsm',
     'SelectChild.jsm',
     'SelectParent.jsm',
     'SidebarSearchParent.jsm',
     'ThumbnailsChild.jsm',
     'UAWidgetsChild.jsm',
     'UnselectedTabHoverChild.jsm',
+    'UnselectedTabHoverParent.jsm',
     'ViewSourceChild.jsm',
     'ViewSourcePageChild.jsm',
     'ViewSourcePageParent.jsm',
     'WebChannelChild.jsm',
     'WebChannelParent.jsm',
     'WebNavigationChild.jsm',
     'ZoomChild.jsm',
     'ZoomParent.jsm',
--- a/toolkit/content/tests/browser/browser_resume_bkg_video_on_tab_hover.js
+++ b/toolkit/content/tests/browser/browser_resume_bkg_video_on_tab_hover.js
@@ -27,62 +27,37 @@ async function check_video_decoding_stat
         ok(true, `Video decoding is ${state}.`);
         resolve();
       },
       { once: true }
     );
   });
 }
 
-function check_should_send_unselected_tab_hover_msg(browser) {
+async function check_should_send_unselected_tab_hover_msg(browser) {
+  info("did not update the value now, wait until it changes.");
   if (browser.shouldHandleUnselectedTabHover) {
     ok(
       true,
       "Should send unselected tab hover msg, someone is listening for it."
     );
     return true;
   }
-
-  info("did not update the value now, wait until it changes.");
-  return new Promise(resolve => {
-    browser.messageManager.addMessageListener(
-      "UnselectedTabHoverMsg:Enabled",
-      function() {
-        ok(
-          true,
-          "Should send unselected tab hover msg, someone is listening for it."
-        );
-        resolve();
-      }
-    );
-  });
+  return BrowserTestUtils.waitForCondition(
+    () => browser.shouldHandleUnselectedTabHover,
+    "Should send unselected tab hover msg, someone is listening for it."
+  );
 }
 
-function check_should_not_send_unselected_tab_hover_msg(browser) {
-  if (!browser.shouldHandleUnselectedTabHover) {
-    ok(
-      true,
-      "Should not send unselected tab hover msg, no one is listening for it."
-    );
-    return true;
-  }
-
+async function check_should_not_send_unselected_tab_hover_msg(browser) {
   info("did not update the value now, wait until it changes.");
-  return new Promise(resolve => {
-    browser.messageManager.addMessageListener(
-      "UnselectedTabHoverMsg:Disabled",
-      function() {
-        ok(
-          true,
-          "Should not send unselected tab hover msg, no one is listening for it."
-        );
-        resolve();
-      }
-    );
-  });
+  return BrowserTestUtils.waitForCondition(
+    () => !browser.shouldHandleUnselectedTabHover,
+    "Should not send unselected tab hover msg, no one is listening for it."
+  );
 }
 
 function get_video_decoding_suspend_promise(browser, reload) {
   let suspend = true;
   return SpecialPowers.spawn(
     browser,
     [{ suspend, reload }],
     check_video_decoding_state
--- a/toolkit/content/widgets/browser-custom-element.js
+++ b/toolkit/content/widgets/browser-custom-element.js
@@ -356,22 +356,16 @@
       this.mPrefs = Services.prefs;
 
       this._mStrBundle = null;
 
       this._audioMuted = false;
 
       this._hasAnyPlayingMediaBeenBlocked = false;
 
-      /**
-       * Only send the message "Browser:UnselectedTabHover" when someone requests
-       * for the message, which can reduce non-necessary communication.
-       */
-      this._shouldSendUnselectedTabHover = false;
-
       this._unselectedTabHoverMessageListenerCount = 0;
 
       this._securityUI = null;
 
       this.urlbarChangeTracker = {
         _startedLoadSinceLastUserTyping: false,
 
         startedLoad() {
@@ -871,17 +865,21 @@
       return this._mStrBundle;
     }
 
     get audioMuted() {
       return this._audioMuted;
     }
 
     get shouldHandleUnselectedTabHover() {
-      return this._shouldSendUnselectedTabHover;
+      return this._unselectedTabHoverMessageListenerCount > 0;
+    }
+
+    set shouldHandleUnselectedTabHover(value) {
+      this._unselectedTabHoverMessageListenerCount += value ? 1 : -1;
     }
 
     get securityUI() {
       if (this.isRemoteBrowser) {
         if (!this._securityUI) {
           // Don't attempt to create the remote web progress if the
           // messageManager has already gone away
           if (!this.messageManager) {
@@ -1155,22 +1153,27 @@
         this._hasAnyPlayingMediaBeenBlocked = false;
         let event = document.createEvent("Events");
         event.initEvent("DOMAudioPlaybackBlockStopped", true, false);
         this.dispatchEvent(event);
       }
     }
 
     unselectedTabHover(hovered) {
-      if (!this._shouldSendUnselectedTabHover) {
+      if (!this.shouldHandleUnselectedTabHover) {
         return;
       }
-      this.messageManager.sendAsyncMessage("Browser:UnselectedTabHover", {
-        hovered,
-      });
+      this.sendMessageToActor(
+        "Browser:UnselectedTabHover",
+        {
+          hovered,
+        },
+        "UnselectedTabHover",
+        "roots"
+      );
     }
 
     didStartLoadSinceLastUserTyping() {
       return (
         !this.isNavigating &&
         this.urlbarChangeTracker._startedLoadSinceLastUserTyping
       );
     }
@@ -1289,23 +1292,16 @@
         // our RemoteWebProgress or its associated manager, but we'll need to
         // add the progress listeners to the new non-remote WebProgress.
         this._remoteWebProgressManager = null;
         this._remoteWebProgress = null;
         this.restoreProgressListeners();
 
         this.addEventListener("pagehide", this.onPageHide, true);
       }
-
-      if (this.messageManager) {
-        this.messageManager.addMessageListener(
-          "UnselectedTabHover:Toggle",
-          this
-        );
-      }
     }
 
     /**
      * This is necessary because the destructor doesn't always get called when
      * we are removed from a tabbrowser. This will be explicitly called by tabbrowser.
      */
     destroy() {
       elementsToDestroyOnUnload.delete(this);
@@ -1347,49 +1343,30 @@
       }
 
       if (this._autoScrollNeedsCleanup) {
         // we polluted the global scope, so clean it up
         this._autoScrollPopup.remove();
       }
     }
 
-    /**
-     * We call this _receiveMessage (and alias receiveMessage to it) so that
-     * bindings that inherit from this one can delegate to it.
-     */
-    _receiveMessage(aMessage) {
-      let data = aMessage.data;
-      switch (aMessage.name) {
-        case "UnselectedTabHover:Toggle":
-          this._shouldSendUnselectedTabHover = data.enable
-            ? ++this._unselectedTabHoverMessageListenerCount > 0
-            : --this._unselectedTabHoverMessageListenerCount == 0;
-          break;
+    receiveMessage(aMessage) {
+      if (this.isRemoteBrowser) {
+        const data = aMessage.data;
+        switch (aMessage.name) {
+          case "Browser:Init":
+            this._outerWindowID = data.outerWindowID;
+            break;
+          case "DOMTitleChanged":
+            this._contentTitle = data.title;
+            break;
+          default:
+            break;
+        }
       }
-      return undefined;
-    }
-
-    receiveMessage(aMessage) {
-      if (!this.isRemoteBrowser) {
-        return this._receiveMessage(aMessage);
-      }
-
-      let data = aMessage.data;
-      switch (aMessage.name) {
-        case "Browser:Init":
-          this._outerWindowID = data.outerWindowID;
-          break;
-        case "DOMTitleChanged":
-          this._contentTitle = data.title;
-          break;
-        default:
-          return this._receiveMessage(aMessage);
-      }
-      return undefined;
     }
 
     enableDisableCommandsRemoteOnly(
       aAction,
       aEnabledCommands,
       aDisabledCommands
     ) {
       if (this._controller) {
--- a/toolkit/modules/ActorManagerParent.jsm
+++ b/toolkit/modules/ActorManagerParent.jsm
@@ -364,16 +364,31 @@ let ACTORS = {
         UAWidgetSetupOrChange: {},
         UAWidgetTeardown: {},
       },
     },
 
     allFrames: true,
   },
 
+  UnselectedTabHover: {
+    parent: {
+      moduleURI: "resource://gre/actors/UnselectedTabHoverParent.jsm",
+    },
+    child: {
+      moduleURI: "resource://gre/actors/UnselectedTabHoverChild.jsm",
+      events: {
+        "UnselectedTabHover:Enable": {},
+        "UnselectedTabHover:Disable": {},
+      },
+    },
+
+    allFrames: true,
+  },
+
   WebNavigation: {
     child: {
       moduleURI: "resource://gre/actors/WebNavigationChild.jsm",
     },
   },
 
   Zoom: {
     parent: {
@@ -523,27 +538,16 @@ let LEGACY_ACTORS = {
         "Printing:Preview:Enter",
         "Printing:Preview:Exit",
         "Printing:Preview:Navigate",
         "Printing:Preview:ParseDocument",
         "Printing:Print",
       ],
     },
   },
-
-  UnselectedTabHover: {
-    child: {
-      module: "resource://gre/actors/UnselectedTabHoverChild.jsm",
-      events: {
-        "UnselectedTabHover:Enable": {},
-        "UnselectedTabHover:Disable": {},
-      },
-      messages: ["Browser:UnselectedTabHover"],
-    },
-  },
 };
 
 class ActorSet {
   constructor(group, actorSide) {
     this.group = group;
     this.actorSide = actorSide;
 
     this.actors = new Map();