Bug 1394846 - Fix EventEmitter.decorate exception on Firefox for Android. draft
authorLuca Greco <lgreco@mozilla.com>
Tue, 29 Aug 2017 18:26:29 +0200
changeset 655257 177f38c5be0b42a8d74db8b7cc556a6ce17bafb6
parent 655242 9957a25209908aaea4bfd4915c3201f006b29b6e
child 728784 06611bbcef35958fd13d3ac6109ba632b7eab72b
push id76817
push userluca.greco@alcacoop.it
push dateTue, 29 Aug 2017 20:00:12 +0000
bugs1394846
milestone57.0a1
Bug 1394846 - Fix EventEmitter.decorate exception on Firefox for Android. MozReview-Commit-ID: DhaVpD1zcaS
mobile/android/components/extensions/ext-android.js
mobile/android/components/extensions/ext-browserAction.js
mobile/android/components/extensions/ext-pageAction.js
mobile/android/components/extensions/ext-utils.js
mobile/android/components/extensions/test/mochitest/test_ext_pageAction_show_hide.html
mobile/android/components/extensions/test/mochitest/test_ext_tabs_lastAccessed.html
--- a/mobile/android/components/extensions/ext-android.js
+++ b/mobile/android/components/extensions/ext-android.js
@@ -1,13 +1,10 @@
 "use strict";
 
-XPCOMUtils.defineLazyModuleGetter(global, "EventEmitter",
-                                  "resource://gre/modules/EventEmitter.jsm");
-
 // This function is pretty tightly tied to Extension.jsm.
 // Its job is to fill in the |tab| property of the sender.
 const getSender = (extension, target, sender) => {
   let tabId = -1;
   if ("tabId" in sender) {
     // The message came from a privileged extension page running in a tab. In
     // that case, it should include a tabId property (which is filled in by the
     // page-open listener below).
--- a/mobile/android/components/extensions/ext-browserAction.js
+++ b/mobile/android/components/extensions/ext-browserAction.js
@@ -10,18 +10,20 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 
 // Import the android BrowserActions module.
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserActions",
                                   "resource://gre/modules/BrowserActions.jsm");
 
 // WeakMap[Extension -> BrowserAction]
 let browserActionMap = new WeakMap();
 
-class BrowserAction {
+class BrowserAction extends EventEmitter {
   constructor(options, extension) {
+    super();
+
     this.uuid = `{${extension.uuid}}`;
 
     this.defaults = {
       name: options.default_title || extension.name,
     };
 
     this.tabContext = new TabContext(tab => Object.create(this.defaults),
                                      extension);
@@ -29,17 +31,16 @@ class BrowserAction {
     this.tabManager = extension.tabManager;
 
     this.tabContext.on("tab-selected", // eslint-disable-line mozilla/balanced-listeners
                        (evt, tabId) => { this.onTabSelected(tabId); });
     this.tabContext.on("tab-closed", // eslint-disable-line mozilla/balanced-listeners
                        (evt, tabId) => { this.onTabClosed(tabId); });
 
     BrowserActions.register(this);
-    EventEmitter.decorate(this);
   }
 
   /**
    * Required by the BrowserActions module. This event will get
    * called whenever the browser action is clicked on.
    */
   onClicked() {
     const tab = tabTracker.activeTab;
--- a/mobile/android/components/extensions/ext-pageAction.js
+++ b/mobile/android/components/extensions/ext-pageAction.js
@@ -17,18 +17,20 @@ Cu.import("resource://gre/modules/Extens
 
 var {
   IconDetails,
 } = ExtensionParent;
 
 // WeakMap[Extension -> PageAction]
 let pageActionMap = new WeakMap();
 
-class PageAction {
+class PageAction extends EventEmitter {
   constructor(manifest, extension) {
+    super();
+
     this.id = null;
 
     this.extension = extension;
 
     this.defaults = {
       icons: IconDetails.normalize({path: manifest.default_icon}, extension),
       popup: manifest.default_popup,
     };
@@ -60,18 +62,16 @@ class PageAction {
     };
 
     this.shouldShow = false;
 
     this.tabContext.on("tab-selected", // eslint-disable-line mozilla/balanced-listeners
                        (evt, tabId) => { this.onTabSelected(tabId); });
     this.tabContext.on("tab-closed", // eslint-disable-line mozilla/balanced-listeners
                        (evt, tabId) => { this.onTabClosed(tabId); });
-
-    EventEmitter.decorate(this);
   }
 
   /**
    * Updates the page action whenever a tab is selected.
    * @param {Integer} tabId The ID of the selected tab.
    */
   onTabSelected(tabId) {
     if (this.options.icon) {
@@ -187,16 +187,17 @@ class PageAction {
     });
   }
 
   /**
    * Hides the page action for the active tab.
    */
   hide() {
     this.shouldShow = false;
+
     if (this.id) {
       PageActions.remove(this.id);
       this.id = null;
     }
   }
 
   shutdown() {
     this.tabContext.shutdown();
--- a/mobile/android/components/extensions/ext-utils.js
+++ b/mobile/android/components/extensions/ext-utils.js
@@ -429,24 +429,24 @@ class Tab extends TabBase {
   }
 
   get windowId() {
     return windowTracker.getId(this.window);
   }
 }
 
 // Manages tab-specific context data and dispatches tab select and close events.
-class TabContext {
+class TabContext extends EventEmitter {
   constructor(getDefaults, extension) {
+    super();
+
     this.extension = extension;
     this.getDefaults = getDefaults;
     this.tabData = new Map();
 
-    EventEmitter.decorate(this);
-
     GlobalEventDispatcher.registerListener(this, [
       "Tab:Selected",
       "Tab:Closed",
     ]);
   }
 
   get(tabId) {
     if (!this.tabData.has(tabId)) {
--- a/mobile/android/components/extensions/test/mochitest/test_ext_pageAction_show_hide.html
+++ b/mobile/android/components/extensions/test/mochitest/test_ext_pageAction_show_hide.html
@@ -34,18 +34,25 @@ add_task(async function test_pageAction(
       return tab;
     }
 
     let tab1 = await createNewTab("about:blank");
     let tab2 = await createNewTab("about:blank");
 
     browser.test.onMessage.addListener(async (msg, data) => {
       if (msg === "select-tab") {
+        const onActivatedListener = ({tabId}) => {
+          if (tabId === data) {
+            browser.tabs.onActivated.removeListener(onActivatedListener);
+            browser.test.sendMessage("tab-selected");
+          }
+        };
+        browser.tabs.onActivated.addListener(onActivatedListener);
+
         await browser.tabs.update(data, {active: true});
-        browser.test.sendMessage("tab-selected");
       } else if (msg === "pageAction-show") {
         browser.pageAction.show(data).then(() => {
           browser.test.sendMessage("page-action-shown");
         });
       } else if (msg === "pageAction-hide") {
         browser.pageAction.hide(data).then(() => {
           browser.test.sendMessage("page-action-hidden");
         });
--- a/mobile/android/components/extensions/test/mochitest/test_ext_tabs_lastAccessed.html
+++ b/mobile/android/components/extensions/test/mochitest/test_ext_tabs_lastAccessed.html
@@ -31,18 +31,24 @@ add_task(async function testLastAccessed
 
         let [tab1] = await browser.tabs.query({url: "https://example.com/?1"});
         let [tab2] = await browser.tabs.query({url: "https://example.com/?2"});
 
         browser.test.assertTrue(tab1 && tab2, "Expected tabs were found");
 
         let now = Date.now();
 
-        browser.test.assertTrue(past < tab1.lastAccessed &&
-                                tab1.lastAccessed < tab2.lastAccessed &&
+        browser.test.assertTrue(typeof tab1.lastAccessed == "number",
+                                "tab1 lastAccessed should be a number");
+
+        browser.test.assertTrue(typeof tab2.lastAccessed == "number",
+                                "tab2 lastAccessed should be a number");
+
+        browser.test.assertTrue(past <= tab1.lastAccessed &&
+                                tab1.lastAccessed <= tab2.lastAccessed &&
                                 tab2.lastAccessed <= now,
                                 "lastAccessed timestamps are recent and in the right order");
 
         await browser.tabs.remove([tab1.id, tab2.id]);
 
         browser.test.notifyPass("tabs.lastAccessed");
       });
     },