From f19a0f3bc5e1e87d3c663cc2b147c5c0831519c5 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: <05ec1aa0d5e8806dd0c5c6d08c82846a1389b599.1512038840.git.jan.steffens@gmail.com> References: <05ec1aa0d5e8806dd0c5c6d08c82846a1389b599.1512038840.git.jan.steffens@gmail.com> From: Bob Silverberg Date: Fri, 24 Nov 2017 07:45:03 -0500 Subject: [PATCH 2/2] Bug 1419426 - Implement browserSettings.contextMenuShowEvent, r=kmag a=gchang Uplift for 58. --- .../components/extensions/ext-browserSettings.js | 45 ++++++++++++++++ .../extensions/schemas/browser_settings.json | 10 ++++ .../test/xpcshell/test_ext_browserSettings.js | 62 ++++++++++++++++++++-- 3 files changed, 114 insertions(+), 3 deletions(-) diff --git a/toolkit/components/extensions/ext-browserSettings.js b/toolkit/components/extensions/ext-browserSettings.js index f3212f351baf6975..2b24bcc1d09091f2 100644 --- a/toolkit/components/extensions/ext-browserSettings.js +++ b/toolkit/components/extensions/ext-browserSettings.js @@ -2,17 +2,23 @@ /* vim: set sts=2 sw=2 et tw=80: */ "use strict"; +XPCOMUtils.defineLazyModuleGetter(this, "AppConstants", + "resource://gre/modules/AppConstants.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "ExtensionSettingsStore", "resource://gre/modules/ExtensionSettingsStore.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService", "@mozilla.org/browser/aboutnewtab-service;1", "nsIAboutNewTabService"); Cu.import("resource://gre/modules/ExtensionPreferencesManager.jsm"); +var { + ExtensionError, +} = ExtensionUtils; + const HOMEPAGE_OVERRIDE_SETTING = "homepage_override"; const HOMEPAGE_URL_PREF = "browser.startup.homepage"; const URL_STORE_TYPE = "url_overrides"; @@ -82,6 +88,16 @@ ExtensionPreferencesManager.addSetting("imageAnimationBehavior", { }, }); +ExtensionPreferencesManager.addSetting("contextMenuShowEvent", { + prefNames: [ + "ui.context_menus.after_mouseup", + ], + + setCallback(value) { + return {[this.prefNames[0]]: value === "mouseup"}; + }, +}); + this.browserSettings = class extends ExtensionAPI { getAPI(context) { let {extension} = context; @@ -114,6 +130,35 @@ this.browserSettings = class extends ExtensionAPI { () => { return aboutNewTabService.newTabURL; }, URL_STORE_TYPE, true), + contextMenuShowEvent: Object.assign( + getSettingsAPI( + extension, + "contextMenuShowEvent", + () => { + if (AppConstants.platform === "win") { + return "mouseup"; + } + let prefValue = Services.prefs.getBoolPref( + "ui.context_menus.after_mouseup", null); + return prefValue ? "mouseup" : "mousedown"; + } + ), + { + set: details => { + if (!["mouseup", "mousedown"].includes(details.value)) { + throw new ExtensionError( + `${details.value} is not a valid value for contextMenuShowEvent.`); + } + if (AppConstants.platform === "android" || + (AppConstants.platform === "win" && + details.value === "mousedown")) { + return false; + } + return ExtensionPreferencesManager.setSetting( + extension, "contextMenuShowEvent", details.value); + }, + } + ), }, }; } diff --git a/toolkit/components/extensions/schemas/browser_settings.json b/toolkit/components/extensions/schemas/browser_settings.json index af073d933723cbd5..4f354e69dfedaf96 100644 --- a/toolkit/components/extensions/schemas/browser_settings.json +++ b/toolkit/components/extensions/schemas/browser_settings.json @@ -27,28 +27,38 @@ "type": "string", "enum": ["normal", "none", "once"], "description": "How images should be animated in the browser." + }, + { + "id": "ContextMenuMouseEvent", + "type": "string", + "enum": ["mouseup", "mousedown"], + "description": "After which mouse event context menus should popup." } ], "properties": { "allowPopupsForUserEvents": { "$ref": "types.Setting", "description": "Allows or disallows pop-up windows from opening in response to user events." }, "cacheEnabled": { "$ref": "types.Setting", "description": "Enables or disables the browser cache." }, "homepageOverride": { "$ref": "types.Setting", "description": "Returns the value of the overridden home page. Read-only." }, "imageAnimationBehavior": { "$ref": "types.Setting", "description": "Controls the behaviour of image animation in the browser. This setting's value is of type ImageAnimationBehavior, defaulting to normal." }, "newTabPageOverride": { "$ref": "types.Setting", "description": "Returns the value of the overridden new tab page. Read-only." + }, + "contextMenuShowEvent": { + "$ref": "types.Setting", + "description": "Controls after which mouse event context menus popup. This setting's value is of type ContextMenuMouseEvent, which has possible values of mouseup and mousedown." } } } diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_browserSettings.js b/toolkit/components/extensions/test/xpcshell/test_ext_browserSettings.js index 5c441df3e4198671..7e9c1576a723dfc6 100644 --- a/toolkit/components/extensions/test/xpcshell/test_ext_browserSettings.js +++ b/toolkit/components/extensions/test/xpcshell/test_ext_browserSettings.js @@ -24,13 +24,20 @@ add_task(async function test_browser_settings() { "browser.cache.memory.enable": true, "dom.popup_allowed_events": Preferences.get("dom.popup_allowed_events"), "image.animation_mode": "none", + "ui.context_menus.after_mouseup": false, }; async function background() { browser.test.onMessage.addListener(async (msg, apiName, value) => { let apiObj = browser.browserSettings[apiName]; - await apiObj.set({value}); - browser.test.sendMessage("settingData", await apiObj.get({})); + let result = await apiObj.set({value}); + if (msg === "set") { + browser.test.assertTrue(result, "set returns true."); + browser.test.sendMessage("settingData", await apiObj.get({})); + } else { + browser.test.assertFalse(result, "set returns false for a no-op."); + browser.test.sendMessage("no-op set"); + } }); } @@ -69,33 +76,82 @@ add_task(async function test_browser_settings() { } } + async function testNoOpSetting(setting, value, expected) { + extension.sendMessage("setNoOp", setting, value); + await extension.awaitMessage("no-op set"); + for (let pref in expected) { + equal(Preferences.get(pref), expected[pref], `${pref} set correctly for ${value}`); + } + } + await testSetting( "cacheEnabled", false, { "browser.cache.disk.enable": false, "browser.cache.memory.enable": false, }); await testSetting( "cacheEnabled", true, { "browser.cache.disk.enable": true, "browser.cache.memory.enable": true, }); await testSetting( "allowPopupsForUserEvents", false, {"dom.popup_allowed_events": ""}); await testSetting( "allowPopupsForUserEvents", true, {"dom.popup_allowed_events": PREFS["dom.popup_allowed_events"]}); for (let value of ["normal", "none", "once"]) { await testSetting( "imageAnimationBehavior", value, {"image.animation_mode": value}); } - await extension.unload(); + // This setting is a no-op on Android. + if (AppConstants.platform === "android") { + await testNoOpSetting("contextMenuShowEvent", "mouseup", + {"ui.context_menus.after_mouseup": false}); + } else { + await testSetting( + "contextMenuShowEvent", "mouseup", + {"ui.context_menus.after_mouseup": true}); + } + // "mousedown" is also a no-op on Windows. + if (["android", "win"].includes(AppConstants.platform)) { + await testNoOpSetting("contextMenuShowEvent", "mousedown", + {"ui.context_menus.after_mouseup": AppConstants.platform === "win"}); + } else { + await testSetting( + "contextMenuShowEvent", "mousedown", + {"ui.context_menus.after_mouseup": false}); + } + + await extension.unload(); await promiseShutdownManager(); }); + +add_task(async function test_bad_value() { + async function background() { + await browser.test.assertRejects( + browser.browserSettings.contextMenuShowEvent.set({value: "bad"}), + /bad is not a valid value for contextMenuShowEvent/, + "contextMenuShowEvent.set rejects with an invalid value."); + + browser.test.sendMessage("done"); + } + + let extension = ExtensionTestUtils.loadExtension({ + background, + manifest: { + permissions: ["browserSettings"], + }, + }); + + await extension.startup(); + await extension.awaitMessage("done"); + await extension.unload(); +}); -- 2.15.1