Bug 1264118 - Part 2: Implement {set|get}Popup for chrome.pageAction (Bug 1264118). r=kmag

MozReview-Commit-ID: 1ZyQgs8ktic

--HG--
extra : transplant_source : w%E4i%89%BC%B5%CA%3F%2B%84%9B%AF%024%28y%C9D-%01
This commit is contained in:
Matthew Wein 2016-05-30 19:42:03 -07:00
parent 14d859e41f
commit 3f806375a8
4 changed files with 111 additions and 34 deletions

View File

@ -26,14 +26,16 @@ function PageAction(options, extension) {
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"; 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 = { this.options = {
title: options.default_title || extension.name, title: options.default_title || extension.name,
icon: DEFAULT_ICON, icon: DEFAULT_ICON,
id: extension.id, id: extension.id,
clickCallback: () => { clickCallback: () => {
if (this.default_popup) { if (this.popupUrl) {
let win = Services.wm.getMostRecentWindow("navigator:browser"); let win = Services.wm.getMostRecentWindow("navigator:browser");
win.BrowserApp.addTab(this.default_popup, { win.BrowserApp.addTab(this.popupUrl, {
selected: true, selected: true,
parentId: win.BrowserApp.selectedTab.id parentId: win.BrowserApp.selectedTab.id
}); });
@ -61,6 +63,16 @@ PageAction.prototype = {
} }
}, },
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() { shutdown() {
this.hide(); this.hide();
}, },
@ -100,6 +112,20 @@ extensions.registerSchemaAPI("pageAction", null, (extension, context) => {
hide(tabId) { hide(tabId) {
pageActionMap.get(extension).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);
},
}, },
}; };
}); });

View File

@ -160,7 +160,6 @@
}, },
{ {
"name": "setPopup", "name": "setPopup",
"unsupported": true,
"type": "function", "type": "function",
"description": "Sets the html document to be opened as a popup when the user clicks on the page action's icon.", "description": "Sets the html document to be opened as a popup when the user clicks on the page action's icon.",
"parameters": [ "parameters": [
@ -179,7 +178,6 @@
}, },
{ {
"name": "getPopup", "name": "getPopup",
"unsupported": true,
"type": "function", "type": "function",
"description": "Gets the html document set as the popup for this page action.", "description": "Gets the html document set as the popup for this page action.",
"async": "callback", "async": "callback",

View File

@ -3,4 +3,4 @@ support-files =
head.js head.js
[test_ext_pageAction.html] [test_ext_pageAction.html]
[test_ext_pageAction_defaultPopup.html] [test_ext_pageAction_popup.html]

View File

@ -19,18 +19,32 @@ add_task(function* test_contentscript() {
function backgroundScript() { function backgroundScript() {
// TODO: Use the Tabs API to obtain the tab ids for showing pageActions. // TODO: Use the Tabs API to obtain the tab ids for showing pageActions.
let tabId = 1; let tabId = 1;
browser.test.onMessage.addListener(msg => { let onClickedListenerEnabled = false;
browser.test.onMessage.addListener((msg, details) => {
if (msg === "page-action-show") { if (msg === "page-action-show") {
// TODO: switch to using .show(tabId).then(...) once bug 1270742 lands. // TODO: switch to using .show(tabId).then(...) once bug 1270742 lands.
browser.pageAction.show(tabId); browser.pageAction.show(tabId);
browser.test.sendMessage("page-action-shown"); browser.test.sendMessage("page-action-shown");
} else if (msg == "page-action-close-popup") { } else if (msg == "page-action-set-popup") {
browser.runtime.sendMessage("close-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.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"); browser.test.sendMessage("ready");
@ -38,11 +52,13 @@ add_task(function* test_contentscript() {
function popupScript() { function popupScript() {
window.onload = () => { window.onload = () => {
browser.test.sendMessage("from-page-action-popup-shown"); browser.test.sendMessage("page-action-from-popup", location.href);
}; };
browser.runtime.onMessage.addListener(msg => { browser.test.onMessage.addListener((msg, details) => {
if (msg == "close-popup") { if (msg == "page-action-close-popup") {
window.close(); if (details.location == location.href) {
window.close();
}
} }
}); });
} }
@ -53,46 +69,83 @@ add_task(function* test_contentscript() {
"name": "PageAction Extension", "name": "PageAction Extension",
"page_action": { "page_action": {
"default_title": "Page Action", "default_title": "Page Action",
"default_popup": "popup.html", "default_popup": "default.html",
}, },
}, },
files: { 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})()`, "popup.js": `(${popupScript})()`,
}, },
}); });
let tabClosedPromise = new Promise(resolve => { let tabClosedPromise = () => {
let chromeWin = Services.wm.getMostRecentWindow("navigator:browser"); return new Promise(resolve => {
let BrowserApp = chromeWin.BrowserApp; let chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
let BrowserApp = chromeWin.BrowserApp;
let tabCloseListener = (event) => { let tabCloseListener = (event) => {
BrowserApp.deck.removeEventListener("TabClose", tabCloseListener, false); BrowserApp.deck.removeEventListener("TabClose", tabCloseListener, false);
let browser = event.target; let browser = event.target;
let url = browser.currentURI.spec let url = browser.currentURI.spec
resolve(url); 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.startup();
yield extension.awaitMessage("ready"); yield extension.awaitMessage("ready");
extension.sendMessage("page-action-show"); extension.sendMessage("page-action-show");
yield extension.awaitMessage("page-action-shown"); yield extension.awaitMessage("page-action-shown");
ok(isPageActionShown(extension.id), "The PageAction should be shown"); ok(isPageActionShown(extension.id), "The PageAction should be shown.");
clickPageAction(extension.id); yield testPopup("default.html");
yield extension.awaitMessage("from-page-action-popup-shown"); yield testPopup("a.html");
yield testPopup("");
extension.sendMessage("page-action-close-popup"); yield testPopup("b.html");
let url = yield tabClosedPromise;
ok(url.includes("popup.html"), "The tab for the popup should be closed");
yield extension.unload(); 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> </script>