Part 2: Implement {set|get}Popup for chrome.pageAction (
Bug 1264118) r?kmag
MozReview-Commit-ID: 1ZyQgs8ktic
--- a/mobile/android/components/extensions/ext-pageAction.js
+++ b/mobile/android/components/extensions/ext-pageAction.js
@@ -21,26 +21,28 @@ var {
// WeakMap[Extension -> PageAction]
var pageActionMap = new WeakMap();
function PageAction(options, extension) {
this.id = null;
let DEFAULT_ICON = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAC4klEQVRYhdWXLWzbQBSADQtDAwsHC1tUhUxqfL67lk2tdn+OJg0ODU0rLByqgqINBY6tmlbn7LMTJ5FaFVVBk1G0oUGjG2jT2Y7jxmmcbU/6iJ+f36fz+e5sGP9riCGm9hB37RG+scd4Yo/wsDXCZyIE2xuXsce4bY+wXkAsQtzYmExrfFgvkJkRbkzo1ehoxx5iXcgI/9iYUGt8WH9MqDXEcmNChmEYrRCf2SHWeYgQx3x0tLNRIeKQLTtEFyJEep4NTuhk8BC+yMrwEE3+iozo42d8gK7FAOkMsRiiN8QhW2ttSK5QTfRRV4QoymVeJMvPvDp7gCZigD613MN6yRFA3SWarow9QB9LCfG+NeF9qCtjAKOSQjCqVKhfVsiHEQ+grgx/lRGqUihAc1uL8EFD+KCRO+GrF4J61phcoRoPoEzkYhZYpykh5sMb7kOdIeY+jHKur4QI4Feh4AFX1nVeLxrAvQchGsBz5ls6wa2QdwcvIcE2863bTH79KOvsz/uUYJsp+J0pSzNlDckVqqVGUAF+n6uS7txcOl6wot4JVy70ufDLy4pWLUQVPE81pRI0mGe9oxLMHSeohHvMs/STUNaUK6vDPCvOyxMFDx4achehRDJmHnydnkPww5OFfLxrGIZBFDyYl4LpMzlTQFIP6AQx86w2UeYBccFpJrcKv5L9eGDtUAU6RIELqsB74uynjy/UBRF1gS5BTFxwQT1wTiXoUg9MH7m/3NZRRoi5IJytUbMgzv4Wc832+oQkiKgEehmyMkkpKsFkQV11QsRJL5rJYBLItQgRaUZEmnoZXsomz3vGiWw+I9KMF9SVFOqZEemZekli1jN3U/UOqhHHvC6oWWGElhfSpGdOk6+O9prdwvtLj5BjRsQxdRnot+Zeifpy/2/0stktKTRNLmbk0mwXyl8253fyojj+8rxOHNAhjjm5n0/5OOCGOKBzkrMO0Z75lvSAzKlrF32Z/3z8BqLAn+yMV7VhAAAAAElFTkSuQmCC";
+ this.popupUrl = options.default_popup;
+
this.options = {
title: options.default_title || extension.name,
icon: DEFAULT_ICON,
id: extension.id,
clickCallback: () => {
- if (this.default_popup) {
+ if (this.popupUrl) {
let win = Services.wm.getMostRecentWindow("navigator:browser");
- win.BrowserApp.addTab(this.default_popup, {
+ win.BrowserApp.addTab(this.popupUrl, {
selected: true,
- parentId: win.BrowserApp.selectedTab.id
+ parentId: win.BrowserApp.selectedTab.id,
});
} else {
this.emit("click");
}
},
};
EventEmitter.decorate(this);
@@ -56,16 +58,26 @@ PageAction.prototype = {
hide(tabId) {
if (this.id) {
PageActions.remove(this.id);
this.id = null;
}
},
+ setPopup(tab, url) {
+ // TODO: Only set the popup for the specified tab once we have Tabs API support.
+ this.popupUrl = url;
+ },
+
+ getPopup(tab) {
+ // TODO: Only return the popup for the specified tab once we have Tabs API support.
+ return this.popupUrl;
+ },
+
shutdown() {
this.hide();
},
};
/* eslint-disable mozilla/balanced-listeners */
extensions.on("manifest_page_action", (type, directive, extension, manifest) => {
let pageAction = new PageAction(manifest.page_action, extension);
@@ -95,11 +107,25 @@ extensions.registerSchemaAPI("pageAction
show(tabId) {
pageActionMap.get(extension).show(tabId);
},
hide(tabId) {
pageActionMap.get(extension).hide(tabId);
},
+
+ setPopup(details) {
+ // TODO: Use the Tabs API to get the tab from details.tabId.
+ let tab = null;
+ let url = details.popup && context.uri.resolve(details.popup);
+ pageActionMap.get(extension).setPopup(tab, url);
+ },
+
+ getPopup(details) {
+ // TODO: Use the Tabs API to get the tab from details.tabId.
+ let tab = null;
+ let popup = pageActionMap.get(extension).getPopup(tab);
+ return Promise.resolve(popup);
+ },
},
};
});
--- a/mobile/android/components/extensions/schemas/page_action.json
+++ b/mobile/android/components/extensions/schemas/page_action.json
@@ -155,17 +155,16 @@
"name": "callback",
"optional": true,
"parameters": []
}
]
},
{
"name": "setPopup",
- "unsupported": true,
"type": "function",
"description": "Sets the html document to be opened as a popup when the user clicks on the page action's icon.",
"parameters": [
{
"name": "details",
"type": "object",
"properties": {
"tabId": {"type": "integer", "minimum": 0, "description": "The id of the tab for which you want to modify the page action."},
@@ -174,17 +173,16 @@
"description": "The html file to show in a popup. If set to the empty string (''), no popup is shown."
}
}
}
]
},
{
"name": "getPopup",
- "unsupported": true,
"type": "function",
"description": "Gets the html document set as the popup for this page action.",
"async": "callback",
"parameters": [
{
"name": "details",
"type": "object",
"properties": {
--- a/mobile/android/components/extensions/test/mochitest/chrome.ini
+++ b/mobile/android/components/extensions/test/mochitest/chrome.ini
@@ -1,6 +1,6 @@
[DEFAULT]
support-files =
head.js
[test_ext_pageAction.html]
-[test_ext_pageAction_defaultPopup.html]
\ No newline at end of file
+[test_ext_pageAction_popup.html]
\ No newline at end of file
--- a/mobile/android/components/extensions/test/mochitest/test_ext_pageAction_popup.html
+++ b/mobile/android/components/extensions/test/mochitest/test_ext_pageAction_popup.html
@@ -14,87 +14,140 @@
"use strict";
Cu.import("resource://gre/modules/Services.jsm");
add_task(function* test_contentscript() {
function backgroundScript() {
// TODO: Use the Tabs API to obtain the tab ids for showing pageActions.
let tabId = 1;
- browser.test.onMessage.addListener(msg => {
+ let onClickedListenerEnabled = false;
+
+ browser.test.onMessage.addListener((msg, details) => {
if (msg === "page-action-show") {
// TODO: switch to using .show(tabId).then(...) once bug 1270742 lands.
browser.pageAction.show(tabId);
browser.test.sendMessage("page-action-shown");
- } else if (msg == "page-action-close-popup") {
- browser.runtime.sendMessage("close-popup");
+ } else if (msg == "page-action-set-popup") {
+ browser.pageAction.setPopup({popup: details.name, tabId: tabId});
+ browser.test.sendMessage("page-action-popup-set");
+ } else if (msg == "page-action-get-popup") {
+ browser.pageAction.getPopup({tabId: tabId}).then(url => {
+ browser.test.sendMessage("page-action-got-popup", url);
+ });
+ } else if (msg == "page-action-enable-onClicked-listener") {
+ onClickedListenerEnabled = true;
+ browser.test.sendMessage("page-action-onClicked-listener-enabled");
+ } else if (msg == "page-action-disable-onClicked-listener") {
+ onClickedListenerEnabled = false;
+ browser.test.sendMessage("page-action-onClicked-listener-disabled");
}
});
browser.pageAction.onClicked.addListener(tab => {
- browser.test.fail(`The onClicked listener should never fire when a popup is shown.`);
+ browser.test.assertTrue(onClickedListenerEnabled, "The onClicked listener should only fire when it is enabled.");
+ browser.test.sendMessage("page-action-onClicked-fired");
});
browser.test.sendMessage("ready");
}
function popupScript() {
window.onload = () => {
- browser.test.sendMessage("from-page-action-popup-shown");
+ browser.test.sendMessage("page-action-from-popup", location.href);
};
- browser.runtime.onMessage.addListener(msg => {
- if (msg == "close-popup") {
- window.close();
+ browser.test.onMessage.addListener((msg, details) => {
+ if (msg == "page-action-close-popup") {
+ if (details.location == location.href) {
+ window.close();
+ }
}
});
}
let extension = ExtensionTestUtils.loadExtension({
background: `(${backgroundScript}())`,
manifest: {
"name": "PageAction Extension",
"page_action": {
"default_title": "Page Action",
- "default_popup": "popup.html",
+ "default_popup": "default.html",
},
},
files: {
- "popup.html": `<html><head><meta charset="utf-8"><script src="popup.js"></${"script"}></head></html>`,
+ "default.html": `<html><head><meta charset="utf-8"><script src="popup.js"></${"script"}></head></html>`,
+ "a.html": `<html><head><meta charset="utf-8"><script src="popup.js"></${"script"}></head></html>`,
+ "b.html": `<html><head><meta charset="utf-8"><script src="popup.js"></${"script"}></head></html>`,
"popup.js": `(${popupScript})()`,
},
});
- let tabClosedPromise = new Promise(resolve => {
- let chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
- let BrowserApp = chromeWin.BrowserApp;
+ let tabClosedPromise = () => {
+ return new Promise(resolve => {
+ let chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
+ let BrowserApp = chromeWin.BrowserApp;
- let tabCloseListener = (event) => {
- BrowserApp.deck.removeEventListener("TabClose", tabCloseListener, false);
- let browser = event.target;
- let url = browser.currentURI.spec
- resolve(url);
+ let tabCloseListener = (event) => {
+ BrowserApp.deck.removeEventListener("TabClose", tabCloseListener, false);
+ let browser = event.target;
+ let url = browser.currentURI.spec;
+ resolve(url);
+ };
+
+ BrowserApp.deck.addEventListener("TabClose", tabCloseListener, false);
+ });
+ };
+
+ function* testPopup(name) {
+ // We don't need to set the popup when testing default_popup.
+ if (name != "default.html") {
+ extension.sendMessage("page-action-set-popup", {name});
+ yield extension.awaitMessage("page-action-popup-set");
}
- BrowserApp.deck.addEventListener("TabClose", tabCloseListener, false);
- });
+ extension.sendMessage("page-action-get-popup");
+ let url = yield extension.awaitMessage("page-action-got-popup");
+
+ if (name == "") {
+ ok(url == name, "Calling pageAction.getPopup should return an empty string when the popup is not set.");
+
+ // The onClicked listener should get called when the popup is set to an empty string.
+ extension.sendMessage("page-action-enable-onClicked-listener");
+ yield extension.awaitMessage("page-action-onClicked-listener-enabled");
+
+ clickPageAction(extension.id);
+ yield extension.awaitMessage("page-action-onClicked-fired");
+
+ extension.sendMessage("page-action-disable-onClicked-listener");
+ yield extension.awaitMessage("page-action-onClicked-listener-disabled");
+ } else {
+ ok(url.includes(name), "Calling pageAction.getPopup should return the correct popup URL when the popup is set.");
+
+ clickPageAction(extension.id);
+ let location = yield extension.awaitMessage("page-action-from-popup");
+ ok(location.includes(name), "The popup with the correct URL should be shown.");
+
+ extension.sendMessage("page-action-close-popup", {location});
+
+ url = yield tabClosedPromise();
+ ok(url.includes(name), "The tab for the popup should be closed.");
+ }
+ }
yield extension.startup();
yield extension.awaitMessage("ready");
extension.sendMessage("page-action-show");
yield extension.awaitMessage("page-action-shown");
- ok(isPageActionShown(extension.id), "The PageAction should be shown");
-
- clickPageAction(extension.id);
- yield extension.awaitMessage("from-page-action-popup-shown");
+ ok(isPageActionShown(extension.id), "The PageAction should be shown.");
- extension.sendMessage("page-action-close-popup");
-
- let url = yield tabClosedPromise;
- ok(url.includes("popup.html"), "The tab for the popup should be closed");
+ yield testPopup("default.html");
+ yield testPopup("a.html");
+ yield testPopup("");
+ yield testPopup("b.html");
yield extension.unload();
- ok(!isPageActionShown(extension.id), "The PageAction should be removed after unload");
+ ok(!isPageActionShown(extension.id), "The PageAction should be removed after unload.");
});
</script>
</body>
</html>