Bug 1101825 - Create UITour event framework. r=MattN
authorBlair McBride <bmcbride@mozilla.com>
Fri, 05 Dec 2014 14:50:45 +1300
changeset 218486 6c84bbab28481882d57d98b69497722496e00d0c
parent 218485 e052ef75c2244b862a35fd42e48b75daccdf7d70
child 218487 0e6026de7539086372f56e93e5923cd2cdce939c
push id27932
push usercbook@mozilla.com
push dateFri, 05 Dec 2014 12:05:46 +0000
treeherdermozilla-central@18188c19a3c3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMattN
bugs1101825
milestone37.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 1101825 - Create UITour event framework. r=MattN
browser/base/content/content-UITour.js
browser/modules/UITour.jsm
browser/modules/test/browser.ini
browser/modules/test/browser_UITour_observe.js
browser/modules/test/uitour.js
--- a/browser/base/content/content-UITour.js
+++ b/browser/base/content/content-UITour.js
@@ -7,16 +7,17 @@ let UITourListener = {
   handleEvent: function (event) {
     if (!Services.prefs.getBoolPref("browser.uitour.enabled")) {
       return;
     }
     if (!this.ensureTrustedOrigin()) {
       return;
     }
     addMessageListener("UITour:SendPageCallback", this);
+    addMessageListener("UITour:SendPageNotification", this);
     sendAsyncMessage("UITour:onPageEvent", {detail: event.detail, type: event.type});
   },
 
   isTestingOrigin: function(aURI) {
     if (Services.prefs.getPrefType(PREF_TEST_WHITELIST) != Services.prefs.PREF_STRING) {
       return false;
     }
 
@@ -63,24 +64,28 @@ let UITourListener = {
       return true;
 
     return this.isTestingOrigin(uri);
   },
 
   receiveMessage: function(aMessage) {
     switch (aMessage.name) {
       case "UITour:SendPageCallback":
-        this.sendPageCallback(aMessage.data);
+        this.sendPageEvent("Response", aMessage.data);
         break;
-    }
+      case "UITour:SendPageNotification":
+        this.sendPageEvent("Notification", aMessage.data);
+        break;
+      }
   },
 
-  sendPageCallback: function (detail) {
+  sendPageEvent: function (type, detail) {
     let doc = content.document;
-    let event = new doc.defaultView.CustomEvent("mozUITourResponse", {
+    let eventName = "mozUITour" + type;
+    let event = new doc.defaultView.CustomEvent(eventName, {
       bubbles: true,
       detail: Cu.cloneInto(detail, doc.defaultView)
     });
     doc.dispatchEvent(event);
   }
 };
 
 addEventListener("mozUITour", UITourListener, false, true);
--- a/browser/modules/UITour.jsm
+++ b/browser/modules/UITour.jsm
@@ -603,16 +603,22 @@ this.UITour = {
             };
 
             searchbar.textbox.popup.addEventListener("popupshown", onPopupShown);
             searchbar.openSuggestionsPanel();
           }
         }).then(null, Cu.reportError);
         break;
       }
+
+      case "ping": {
+        if (typeof data.callbackID == "string")
+          this.sendPageCallback(messageManager, data.callbackID);
+        break;
+      }
     }
 
     if (!window.gMultiProcessBrowser) { // Non-e10s. See bug 1089000.
       if (!this.originTabs.has(window)) {
         this.originTabs.set(window, new Set());
       }
 
       this.originTabs.get(window).add(tab);
@@ -1617,17 +1623,39 @@ this.UITour = {
             });
           }
         }
         reject("Search engine not available");
       }.bind(this)).catch(() => {
         reject("Search engine not available");
       });
     });
-  }
+  },
+
+  notify(eventName, params) {
+    let winEnum = Services.wm.getEnumerator("navigator:browser");
+    while (winEnum.hasMoreElements()) {
+      let window = winEnum.getNext();
+      if (window.closed)
+        continue;
+debugger;
+      let originTabs = this.originTabs.get(window);
+      if (!originTabs)
+        continue;
+
+      for (let tab of originTabs) {
+        let messageManager = tab.linkedBrowser.messageManager;
+        let detail = {
+          event: eventName,
+          params: params,
+        };
+        messageManager.sendAsyncMessage("UITour:SendPageNotification", detail);
+      }
+    }
+  },
 };
 
 this.UITour.init();
 
 /**
  * UITour Health Report
  */
 const DAILY_DISCRETE_TEXT_FIELD = Metrics.Storage.FIELD_DAILY_DISCRETE_TEXT;
--- a/browser/modules/test/browser.ini
+++ b/browser/modules/test/browser.ini
@@ -28,16 +28,18 @@ skip-if = e10s # Bug 941428 - UITour.jsm
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
 [browser_UITour_annotation_size_attributes.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly.
 [browser_UITour_loop.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly.
 [browser_UITour_modalDialog.js]
 run-if = os == "mac" # modal dialog disabling only working on OS X
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
+[browser_UITour_observe.js]
+skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly.
 [browser_UITour_panel_close_annotation.js]
 skip-if = true # Disabled due to frequent failures, bugs 1026310 and 1032137
 [browser_UITour_registerPageID.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
 [browser_UITour_sync.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
 [browser_UITour_resetProfile.js]
 skip-if = e10s # Bug 941428 - UITour.jsm not e10s friendly
new file mode 100644
--- /dev/null
+++ b/browser/modules/test/browser_UITour_observe.js
@@ -0,0 +1,51 @@
+"use strict";
+
+let gTestTab;
+let gContentAPI;
+let gContentWindow;
+
+Components.utils.import("resource:///modules/UITour.jsm");
+
+function test() {
+  requestLongerTimeout(2);
+  UITourTest();
+}
+
+let tests = [
+  function test_no_params(done) {
+    function listener(event, params) {
+      is(event, "test-event-1", "Correct event name");
+      is(params, null, "No param object");
+      gContentAPI.observe(null);
+      done();
+    }
+
+    gContentAPI.observe(listener, () => {
+      UITour.notify("test-event-1");
+    });
+  },
+  function test_param_string(done) {
+    function listener(event, params) {
+      is(event, "test-event-2", "Correct event name");
+      is(params, "a param", "Correct param string");
+      gContentAPI.observe(null);
+      done();
+    }
+
+    gContentAPI.observe(listener, () => {
+      UITour.notify("test-event-2", "a param");
+    });
+  },
+  function test_param_object(done) {
+    function listener(event, params) {
+      is(event, "test-event-3", "Correct event name");
+      is(JSON.stringify(params), JSON.stringify({key: "something"}), "Correct param object");
+      gContentAPI.observe(null);
+      done();
+    }
+
+    gContentAPI.observe(listener, () => {
+      UITour.notify("test-event-3", {key: "something"});
+    });
+  },
+];
\ No newline at end of file
--- a/browser/modules/test/uitour.js
+++ b/browser/modules/test/uitour.js
@@ -38,33 +38,64 @@ if (typeof Mozilla == 'undefined') {
 	function _generateCallbackID() {
 		return Math.random().toString(36).replace(/[^a-z]+/g, '');
 	}
 
 	function _waitForCallback(callback) {
 		var id = _generateCallbackID();
 
 		function listener(event) {
-			if (typeof event.detail != "object")
+			if (typeof event.detail != 'object')
 				return;
 			if (event.detail.callbackID != id)
 				return;
 
-			document.removeEventListener("mozUITourResponse", listener);
+			document.removeEventListener('mozUITourResponse', listener);
 			callback(event.detail.data);
 		}
-		document.addEventListener("mozUITourResponse", listener);
+		document.addEventListener('mozUITourResponse', listener);
 
 		return id;
 	}
 
+  var notificationListener = null;
+  function _notificationListener(event) {
+    if (typeof event.detail != 'object')
+      return;
+    if (typeof notificationListener != 'function')
+      return;
+
+    notificationListener(event.detail.event, event.detail.params);
+  }
+
 	Mozilla.UITour.DEFAULT_THEME_CYCLE_DELAY = 10 * 1000;
 
-	Mozilla.UITour.CONFIGNAME_SYNC = "sync";
-	Mozilla.UITour.CONFIGNAME_AVAILABLETARGETS = "availableTargets";
+	Mozilla.UITour.CONFIGNAME_SYNC = 'sync';
+	Mozilla.UITour.CONFIGNAME_AVAILABLETARGETS = 'availableTargets';
+
+  Mozilla.UITour.ping = function(callback) {
+    var data = {};
+    if (callback) {
+      data.callbackID = _waitForCallback(callback);
+    }
+    _sendEvent('ping', data);
+  };
+
+  Mozilla.UITour.observe = function(listener, callback) {
+    notificationListener = listener;
+
+    if (listener) {
+      document.addEventListener('mozUITourNotification',
+                                _notificationListener);
+      Mozilla.UITour.ping(callback);
+    } else {
+      document.removeEventListener('mozUITourNotification',
+                                   _notificationListener);
+    }
+  };
 
 	Mozilla.UITour.registerPageID = function(pageID) {
 		_sendEvent('registerPageID', {
 			pageID: pageID
 		});
 	};
 
 	Mozilla.UITour.showHighlight = function(target, effect) {