forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			338 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			338 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "use strict";
 | |
| 
 | |
| // Initialization. Must run first.
 | |
| add_setup(async function() {
 | |
|   // The page action urlbar button, and therefore the panel, is only shown when
 | |
|   // the current tab is actionable -- i.e., a normal web page.  about:blank is
 | |
|   // not, so open a new tab first thing, and close it when this test is done.
 | |
|   let tab = await BrowserTestUtils.openNewForegroundTab({
 | |
|     gBrowser,
 | |
|     // eslint-disable-next-line @microsoft/sdl/no-insecure-url
 | |
|     url: "http://example.com/",
 | |
|   });
 | |
| 
 | |
|   // The prompt service is mocked later, so set it up to be restored.
 | |
|   let { prompt } = Services;
 | |
| 
 | |
|   registerCleanupFunction(async () => {
 | |
|     BrowserTestUtils.removeTab(tab);
 | |
|     Services.prompt = prompt;
 | |
|   });
 | |
| });
 | |
| 
 | |
| add_task(async function contextMenu_removeExtension_panel() {
 | |
|   // We use an extension that shows a page action so that we can test the
 | |
|   // "remove extension" item in the context menu.
 | |
|   let extension = ExtensionTestUtils.loadExtension({
 | |
|     manifest: {
 | |
|       name: "Test contextMenu",
 | |
|       page_action: { show_matches: ["<all_urls>"] },
 | |
|     },
 | |
| 
 | |
|     useAddonManager: "temporary",
 | |
|   });
 | |
| 
 | |
|   await extension.startup();
 | |
| 
 | |
|   let actionId = ExtensionCommon.makeWidgetId(extension.id);
 | |
| 
 | |
|   const url = "data:text/html,<h1>A Page</h1>";
 | |
|   let win = await BrowserTestUtils.openNewBrowserWindow();
 | |
|   await SimpleTest.promiseFocus(win);
 | |
|   BrowserTestUtils.loadURIString(win.gBrowser, url);
 | |
|   await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
 | |
| 
 | |
|   info("Shrink the window if necessary, check the meatball menu is visible");
 | |
|   let originalOuterWidth = win.outerWidth;
 | |
|   await promiseStableResize(500, win);
 | |
| 
 | |
|   // The pageAction implementation enables the button at the next animation
 | |
|   // frame, so before we look for the button we should wait one animation frame
 | |
|   // as well.
 | |
|   await promiseAnimationFrame(win);
 | |
| 
 | |
|   let meatballButton = win.document.getElementById("pageActionButton");
 | |
|   Assert.ok(BrowserTestUtils.is_visible(meatballButton));
 | |
| 
 | |
|   // Open the panel.
 | |
|   await promisePageActionPanelOpen(win);
 | |
| 
 | |
|   info("Open the context menu");
 | |
|   let panelButton = win.BrowserPageActions.panelButtonNodeForActionID(actionId);
 | |
|   let contextMenuPromise = promisePanelShown("pageActionContextMenu", win);
 | |
|   EventUtils.synthesizeMouseAtCenter(
 | |
|     panelButton,
 | |
|     {
 | |
|       type: "contextmenu",
 | |
|       button: 2,
 | |
|     },
 | |
|     win
 | |
|   );
 | |
|   let contextMenu = await contextMenuPromise;
 | |
| 
 | |
|   let removeExtensionItem = getRemoveExtensionItem(win);
 | |
|   Assert.ok(removeExtensionItem, "'Remove' item exists");
 | |
|   Assert.ok(!removeExtensionItem.hidden, "'Remove' item is visible");
 | |
|   Assert.ok(!removeExtensionItem.disabled, "'Remove' item is not disabled");
 | |
| 
 | |
|   // Click the "remove extension" item, a prompt should be displayed and then
 | |
|   // the add-on should be uninstalled. We mock the prompt service to confirm
 | |
|   // the removal of the add-on.
 | |
|   contextMenuPromise = promisePanelHidden("pageActionContextMenu", win);
 | |
|   let addonUninstalledPromise = promiseAddonUninstalled(extension.id);
 | |
|   mockPromptService();
 | |
|   contextMenu.activateItem(removeExtensionItem);
 | |
|   await Promise.all([contextMenuPromise, addonUninstalledPromise]);
 | |
| 
 | |
|   // Done, clean up.
 | |
|   await extension.unload();
 | |
| 
 | |
|   await promiseStableResize(originalOuterWidth, win);
 | |
|   await BrowserTestUtils.closeWindow(win);
 | |
| });
 | |
| 
 | |
| add_task(async function contextMenu_removeExtension_urlbar() {
 | |
|   // We use an extension that shows a page action so that we can test the
 | |
|   // "remove extension" item in the context menu.
 | |
|   let extension = ExtensionTestUtils.loadExtension({
 | |
|     manifest: {
 | |
|       name: "Test contextMenu",
 | |
|       page_action: { show_matches: ["<all_urls>"] },
 | |
|     },
 | |
| 
 | |
|     useAddonManager: "temporary",
 | |
|   });
 | |
| 
 | |
|   await extension.startup();
 | |
|   // The pageAction implementation enables the button at the next animation
 | |
|   // frame, so before we look for the button we should wait one animation frame
 | |
|   // as well.
 | |
|   await promiseAnimationFrame();
 | |
| 
 | |
|   let actionId = ExtensionCommon.makeWidgetId(extension.id);
 | |
| 
 | |
|   // Open the context menu on the action's urlbar button.
 | |
|   let urlbarButton = BrowserPageActions.urlbarButtonNodeForActionID(actionId);
 | |
|   let contextMenuPromise = promisePanelShown("pageActionContextMenu");
 | |
|   EventUtils.synthesizeMouseAtCenter(urlbarButton, {
 | |
|     type: "contextmenu",
 | |
|     button: 2,
 | |
|   });
 | |
|   let contextMenu = await contextMenuPromise;
 | |
| 
 | |
|   let menuItems = collectContextMenuItems();
 | |
|   Assert.equal(menuItems.length, 2, "Context menu has two children");
 | |
|   let removeExtensionItem = getRemoveExtensionItem();
 | |
|   Assert.ok(removeExtensionItem, "'Remove' item exists");
 | |
|   Assert.ok(!removeExtensionItem.hidden, "'Remove' item is visible");
 | |
|   Assert.ok(!removeExtensionItem.disabled, "'Remove' item is not disabled");
 | |
|   let manageExtensionItem = getManageExtensionItem();
 | |
|   Assert.ok(manageExtensionItem, "'Manage' item exists");
 | |
|   Assert.ok(!manageExtensionItem.hidden, "'Manage' item is visible");
 | |
|   Assert.ok(!manageExtensionItem.disabled, "'Manage' item is not disabled");
 | |
| 
 | |
|   // Click the "remove extension" item, a prompt should be displayed and then
 | |
|   // the add-on should be uninstalled. We mock the prompt service to cancel the
 | |
|   // removal of the add-on.
 | |
|   contextMenuPromise = promisePanelHidden("pageActionContextMenu");
 | |
|   let promptService = mockPromptService();
 | |
|   let promptCancelledPromise = new Promise(resolve => {
 | |
|     promptService.confirmEx = () => resolve();
 | |
|   });
 | |
|   contextMenu.activateItem(removeExtensionItem);
 | |
|   await Promise.all([contextMenuPromise, promptCancelledPromise]);
 | |
| 
 | |
|   // Done, clean up.
 | |
|   await extension.unload();
 | |
| 
 | |
|   // urlbar tests that run after this one can break if the mouse is left over
 | |
|   // the area where the urlbar popup appears, which seems to happen due to the
 | |
|   // above synthesized mouse events.  Move it over the urlbar.
 | |
|   EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, { type: "mousemove" });
 | |
|   gURLBar.focus();
 | |
| });
 | |
| 
 | |
| add_task(async function contextMenu_removeExtension_disabled_in_urlbar() {
 | |
|   // We use an extension that shows a page action so that we can test the
 | |
|   // "remove extension" item in the context menu.
 | |
|   let extension = ExtensionTestUtils.loadExtension({
 | |
|     manifest: {
 | |
|       name: "Test contextMenu",
 | |
|       page_action: { show_matches: ["<all_urls>"] },
 | |
|     },
 | |
| 
 | |
|     useAddonManager: "temporary",
 | |
|   });
 | |
| 
 | |
|   await extension.startup();
 | |
|   // The pageAction implementation enables the button at the next animation
 | |
|   // frame, so before we look for the button we should wait one animation frame
 | |
|   // as well.
 | |
|   await promiseAnimationFrame();
 | |
|   // Add a policy to prevent the add-on from being uninstalled.
 | |
|   await EnterprisePolicyTesting.setupPolicyEngineWithJson({
 | |
|     policies: {
 | |
|       Extensions: {
 | |
|         Locked: [extension.id],
 | |
|       },
 | |
|     },
 | |
|   });
 | |
| 
 | |
|   let actionId = ExtensionCommon.makeWidgetId(extension.id);
 | |
| 
 | |
|   // Open the context menu on the action's urlbar button.
 | |
|   let urlbarButton = BrowserPageActions.urlbarButtonNodeForActionID(actionId);
 | |
|   let contextMenuPromise = promisePanelShown("pageActionContextMenu");
 | |
|   EventUtils.synthesizeMouseAtCenter(urlbarButton, {
 | |
|     type: "contextmenu",
 | |
|     button: 2,
 | |
|   });
 | |
|   let contextMenu = await contextMenuPromise;
 | |
| 
 | |
|   let menuItems = collectContextMenuItems();
 | |
|   Assert.equal(menuItems.length, 2, "Context menu has two children");
 | |
|   let removeExtensionItem = getRemoveExtensionItem();
 | |
|   Assert.ok(removeExtensionItem, "'Remove' item exists");
 | |
|   Assert.ok(!removeExtensionItem.hidden, "'Remove' item is visible");
 | |
|   Assert.ok(removeExtensionItem.disabled, "'Remove' item is disabled");
 | |
|   let manageExtensionItem = getManageExtensionItem();
 | |
|   Assert.ok(manageExtensionItem, "'Manage' item exists");
 | |
|   Assert.ok(!manageExtensionItem.hidden, "'Manage' item is visible");
 | |
|   Assert.ok(!manageExtensionItem.disabled, "'Manage' item is not disabled");
 | |
| 
 | |
|   // Hide the context menu.
 | |
|   contextMenuPromise = promisePanelHidden("pageActionContextMenu");
 | |
|   contextMenu.hidePopup();
 | |
|   await contextMenuPromise;
 | |
| 
 | |
|   // Done, clean up.
 | |
|   await extension.unload();
 | |
|   await EnterprisePolicyTesting.setupPolicyEngineWithJson("");
 | |
| 
 | |
|   // urlbar tests that run after this one can break if the mouse is left over
 | |
|   // the area where the urlbar popup appears, which seems to happen due to the
 | |
|   // above synthesized mouse events.  Move it over the urlbar.
 | |
|   EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, { type: "mousemove" });
 | |
|   gURLBar.focus();
 | |
| });
 | |
| 
 | |
| add_task(async function contextMenu_removeExtension_disabled_in_panel() {
 | |
|   // We use an extension that shows a page action so that we can test the
 | |
|   // "remove extension" item in the context menu.
 | |
|   let extension = ExtensionTestUtils.loadExtension({
 | |
|     manifest: {
 | |
|       name: "Test contextMenu",
 | |
|       page_action: { show_matches: ["<all_urls>"] },
 | |
|     },
 | |
| 
 | |
|     useAddonManager: "temporary",
 | |
|   });
 | |
| 
 | |
|   await extension.startup();
 | |
|   // Add a policy to prevent the add-on from being uninstalled.
 | |
|   await EnterprisePolicyTesting.setupPolicyEngineWithJson({
 | |
|     policies: {
 | |
|       Extensions: {
 | |
|         Locked: [extension.id],
 | |
|       },
 | |
|     },
 | |
|   });
 | |
| 
 | |
|   let actionId = ExtensionCommon.makeWidgetId(extension.id);
 | |
| 
 | |
|   const url = "data:text/html,<h1>A Page</h1>";
 | |
|   let win = await BrowserTestUtils.openNewBrowserWindow();
 | |
|   await SimpleTest.promiseFocus(win);
 | |
|   BrowserTestUtils.loadURIString(win.gBrowser, url);
 | |
|   await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
 | |
| 
 | |
|   info("Shrink the window if necessary, check the meatball menu is visible");
 | |
|   let originalOuterWidth = win.outerWidth;
 | |
|   await promiseStableResize(500, win);
 | |
| 
 | |
|   // The pageAction implementation enables the button at the next animation
 | |
|   // frame, so before we look for the button we should wait one animation frame
 | |
|   // as well.
 | |
|   await promiseAnimationFrame(win);
 | |
| 
 | |
|   let meatballButton = win.document.getElementById("pageActionButton");
 | |
|   Assert.ok(BrowserTestUtils.is_visible(meatballButton));
 | |
| 
 | |
|   // Open the panel.
 | |
|   await promisePageActionPanelOpen(win);
 | |
| 
 | |
|   info("Open the context menu");
 | |
|   let panelButton = win.BrowserPageActions.panelButtonNodeForActionID(actionId);
 | |
|   let contextMenuPromise = promisePanelShown("pageActionContextMenu", win);
 | |
|   EventUtils.synthesizeMouseAtCenter(
 | |
|     panelButton,
 | |
|     {
 | |
|       type: "contextmenu",
 | |
|       button: 2,
 | |
|     },
 | |
|     win
 | |
|   );
 | |
|   let contextMenu = await contextMenuPromise;
 | |
| 
 | |
|   let removeExtensionItem = getRemoveExtensionItem(win);
 | |
|   Assert.ok(removeExtensionItem, "'Remove' item exists");
 | |
|   Assert.ok(!removeExtensionItem.hidden, "'Remove' item is visible");
 | |
|   Assert.ok(removeExtensionItem.disabled, "'Remove' item is disabled");
 | |
| 
 | |
|   // Hide the context menu.
 | |
|   contextMenuPromise = promisePanelHidden("pageActionContextMenu", win);
 | |
|   contextMenu.hidePopup();
 | |
|   await contextMenuPromise;
 | |
| 
 | |
|   // Done, clean up.
 | |
|   await extension.unload();
 | |
|   await EnterprisePolicyTesting.setupPolicyEngineWithJson("");
 | |
| 
 | |
|   await promiseStableResize(originalOuterWidth, win);
 | |
|   await BrowserTestUtils.closeWindow(win);
 | |
| });
 | |
| 
 | |
| function promiseAddonUninstalled(addonId) {
 | |
|   return new Promise(resolve => {
 | |
|     let listener = {};
 | |
|     listener.onUninstalled = addon => {
 | |
|       if (addon.id == addonId) {
 | |
|         AddonManager.removeAddonListener(listener);
 | |
|         resolve();
 | |
|       }
 | |
|     };
 | |
|     AddonManager.addAddonListener(listener);
 | |
|   });
 | |
| }
 | |
| 
 | |
| function mockPromptService() {
 | |
|   let promptService = {
 | |
|     // The prompt returns 1 for cancelled and 0 for accepted.
 | |
|     _response: 0,
 | |
|     QueryInterface: ChromeUtils.generateQI(["nsIPromptService"]),
 | |
|     confirmEx: () => promptService._response,
 | |
|   };
 | |
| 
 | |
|   Services.prompt = promptService;
 | |
| 
 | |
|   return promptService;
 | |
| }
 | |
| 
 | |
| function getRemoveExtensionItem(win = window) {
 | |
|   return win.document.querySelector(
 | |
|     "#pageActionContextMenu > menuitem[label='Remove Extension']"
 | |
|   );
 | |
| }
 | |
| 
 | |
| function getManageExtensionItem(win = window) {
 | |
|   return win.document.querySelector(
 | |
|     "#pageActionContextMenu > menuitem[label='Manage Extension…']"
 | |
|   );
 | |
| }
 | |
| 
 | |
| function collectContextMenuItems(win = window) {
 | |
|   let contextMenu = win.document.getElementById("pageActionContextMenu");
 | |
|   return Array.prototype.filter.call(contextMenu.children, node => {
 | |
|     return win.getComputedStyle(node).visibility == "visible";
 | |
|   });
 | |
| }
 | 
