summaryrefslogtreecommitdiffstats
path: root/browser/components/urlbar/QuickActionsLoaderDefault.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/urlbar/QuickActionsLoaderDefault.sys.mjs')
-rw-r--r--browser/components/urlbar/QuickActionsLoaderDefault.sys.mjs314
1 files changed, 314 insertions, 0 deletions
diff --git a/browser/components/urlbar/QuickActionsLoaderDefault.sys.mjs b/browser/components/urlbar/QuickActionsLoaderDefault.sys.mjs
new file mode 100644
index 0000000000..9752c878e5
--- /dev/null
+++ b/browser/components/urlbar/QuickActionsLoaderDefault.sys.mjs
@@ -0,0 +1,314 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
+
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ ClientEnvironment: "resource://normandy/lib/ClientEnvironment.sys.mjs",
+ DevToolsShim: "chrome://devtools-startup/content/DevToolsShim.sys.mjs",
+ ResetProfile: "resource://gre/modules/ResetProfile.sys.mjs",
+ UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
+ UrlbarProviderQuickActions:
+ "resource:///modules/UrlbarProviderQuickActions.sys.mjs",
+});
+
+import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
+
+XPCOMUtils.defineLazyModuleGetters(lazy, {
+ BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
+});
+
+if (AppConstants.MOZ_UPDATER) {
+ XPCOMUtils.defineLazyServiceGetter(
+ lazy,
+ "AUS",
+ "@mozilla.org/updates/update-service;1",
+ "nsIApplicationUpdateService"
+ );
+}
+
+XPCOMUtils.defineLazyPreferenceGetter(
+ lazy,
+ "SCREENSHOT_BROWSER_COMPONENT",
+ "screenshots.browser.component.enabled",
+ false
+);
+
+let openUrlFun = url => () => openUrl(url);
+let openUrl = url => {
+ let window = lazy.BrowserWindowTracker.getTopWindow();
+
+ if (url.startsWith("about:")) {
+ window.switchToTabHavingURI(Services.io.newURI(url), true, {
+ ignoreFragment: "whenComparing",
+ });
+ } else {
+ window.gBrowser.addTab(url, {
+ inBackground: false,
+ triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
+ });
+ }
+ return { focusContent: true };
+};
+
+let openAddonsUrl = url => {
+ return () => {
+ let window = lazy.BrowserWindowTracker.getTopWindow();
+ window.BrowserOpenAddonsMgr(url, { selectTabByViewId: true });
+ };
+};
+
+let currentBrowser = () =>
+ lazy.BrowserWindowTracker.getTopWindow()?.gBrowser.selectedBrowser;
+let currentTab = () =>
+ lazy.BrowserWindowTracker.getTopWindow()?.gBrowser.selectedTab;
+
+XPCOMUtils.defineLazyGetter(lazy, "gFluentStrings", function () {
+ return new Localization(["branding/brand.ftl", "browser/browser.ftl"], true);
+});
+
+const DEFAULT_ACTIONS = {
+ addons: {
+ l10nCommands: ["quickactions-cmd-addons2", "quickactions-addons"],
+ icon: "chrome://mozapps/skin/extensions/category-extensions.svg",
+ label: "quickactions-addons",
+ onPick: openAddonsUrl("addons://discover/"),
+ },
+ bookmarks: {
+ l10nCommands: ["quickactions-cmd-bookmarks", "quickactions-bookmarks2"],
+ icon: "chrome://browser/skin/bookmark.svg",
+ label: "quickactions-bookmarks2",
+ onPick: () => {
+ lazy.BrowserWindowTracker.getTopWindow().top.PlacesCommandHook.showPlacesOrganizer(
+ "BookmarksToolbar"
+ );
+ },
+ },
+ clear: {
+ l10nCommands: [
+ "quickactions-cmd-clearhistory",
+ "quickactions-clearhistory",
+ ],
+ label: "quickactions-clearhistory",
+ onPick: () => {
+ lazy.BrowserWindowTracker.getTopWindow()
+ .document.getElementById("Tools:Sanitize")
+ .doCommand();
+ },
+ },
+ downloads: {
+ l10nCommands: ["quickactions-cmd-downloads", "quickactions-downloads2"],
+ icon: "chrome://browser/skin/downloads/downloads.svg",
+ label: "quickactions-downloads2",
+ onPick: openUrlFun("about:downloads"),
+ },
+ extensions: {
+ l10nCommands: ["quickactions-cmd-extensions", "quickactions-extensions"],
+ icon: "chrome://mozapps/skin/extensions/category-extensions.svg",
+ label: "quickactions-extensions",
+ onPick: openAddonsUrl("addons://list/extension"),
+ },
+ inspect: {
+ l10nCommands: ["quickactions-cmd-inspector", "quickactions-inspector2"],
+ icon: "chrome://devtools/skin/images/open-inspector.svg",
+ label: "quickactions-inspector2",
+ isVisible: () =>
+ lazy.DevToolsShim.isEnabled() || lazy.DevToolsShim.isDevToolsUser(),
+ isActive: () => {
+ // The inspect action is available if:
+ // 1. DevTools is enabled.
+ // 2. The user can be considered as a DevTools user.
+ // 3. The url is not about:devtools-toolbox.
+ // 4. The inspector is not opened yet on the page.
+ return (
+ lazy.DevToolsShim.isEnabled() &&
+ lazy.DevToolsShim.isDevToolsUser() &&
+ !currentBrowser()?.currentURI.spec.startsWith(
+ "about:devtools-toolbox"
+ ) &&
+ !lazy.DevToolsShim.hasToolboxForTab(currentTab())
+ );
+ },
+ onPick: openInspector,
+ },
+ logins: {
+ l10nCommands: ["quickactions-cmd-logins", "quickactions-logins2"],
+ label: "quickactions-logins2",
+ onPick: openUrlFun("about:logins"),
+ },
+ plugins: {
+ l10nCommands: ["quickactions-cmd-plugins", "quickactions-plugins"],
+ icon: "chrome://mozapps/skin/extensions/category-extensions.svg",
+ label: "quickactions-plugins",
+ onPick: openAddonsUrl("addons://list/plugin"),
+ },
+ print: {
+ l10nCommands: ["quickactions-cmd-print", "quickactions-print2"],
+ label: "quickactions-print2",
+ icon: "chrome://global/skin/icons/print.svg",
+ onPick: () => {
+ lazy.BrowserWindowTracker.getTopWindow()
+ .document.getElementById("cmd_print")
+ .doCommand();
+ },
+ },
+ private: {
+ l10nCommands: ["quickactions-cmd-private", "quickactions-private2"],
+ label: "quickactions-private2",
+ icon: "chrome://global/skin/icons/indicator-private-browsing.svg",
+ onPick: () => {
+ lazy.BrowserWindowTracker.getTopWindow().OpenBrowserWindow({
+ private: true,
+ });
+ },
+ },
+ refresh: {
+ l10nCommands: ["quickactions-cmd-refresh", "quickactions-refresh"],
+ label: "quickactions-refresh",
+ onPick: () => {
+ lazy.ResetProfile.openConfirmationDialog(
+ lazy.BrowserWindowTracker.getTopWindow()
+ );
+ },
+ },
+ restart: {
+ l10nCommands: ["quickactions-cmd-restart", "quickactions-restart"],
+ label: "quickactions-restart",
+ onPick: restartBrowser,
+ },
+ screenshot: {
+ l10nCommands: ["quickactions-cmd-screenshot", "quickactions-screenshot3"],
+ label: "quickactions-screenshot3",
+ icon: "chrome://browser/skin/screenshot.svg",
+ isActive: () => {
+ return !lazy.BrowserWindowTracker.getTopWindow().gScreenshots.shouldScreenshotsButtonBeDisabled();
+ },
+ onPick: () => {
+ if (lazy.SCREENSHOT_BROWSER_COMPONENT) {
+ Services.obs.notifyObservers(
+ lazy.BrowserWindowTracker.getTopWindow(),
+ "menuitem-screenshot",
+ "quick_actions"
+ );
+ } else {
+ Services.obs.notifyObservers(
+ null,
+ "menuitem-screenshot-extension",
+ "quickaction"
+ );
+ }
+ return { focusContent: true };
+ },
+ },
+ settings: {
+ l10nCommands: ["quickactions-cmd-settings", "quickactions-settings2"],
+ icon: "chrome://global/skin/icons/settings.svg",
+ label: "quickactions-settings2",
+ onPick: openUrlFun("about:preferences"),
+ },
+ themes: {
+ l10nCommands: ["quickactions-cmd-themes", "quickactions-themes"],
+ icon: "chrome://mozapps/skin/extensions/category-extensions.svg",
+ label: "quickactions-themes",
+ onPick: openAddonsUrl("addons://list/theme"),
+ },
+ update: {
+ l10nCommands: ["quickactions-cmd-update", "quickactions-update"],
+ label: "quickactions-update",
+ isActive: () => {
+ if (!AppConstants.MOZ_UPDATER) {
+ return false;
+ }
+ return (
+ lazy.AUS.currentState == Ci.nsIApplicationUpdateService.STATE_PENDING
+ );
+ },
+ onPick: restartBrowser,
+ },
+ viewsource: {
+ l10nCommands: ["quickactions-cmd-viewsource", "quickactions-viewsource2"],
+ icon: "chrome://global/skin/icons/settings.svg",
+ label: "quickactions-viewsource2",
+ isActive: () => currentBrowser()?.currentURI.scheme !== "view-source",
+ onPick: () => openUrl("view-source:" + currentBrowser().currentURI.spec),
+ },
+};
+
+function openInspector() {
+ lazy.DevToolsShim.showToolboxForTab(
+ lazy.BrowserWindowTracker.getTopWindow().gBrowser.selectedTab,
+ { toolId: "inspector" }
+ );
+}
+
+// TODO: We likely want a prompt to confirm with the user that they want to restart
+// the browser.
+function restartBrowser() {
+ // Notify all windows that an application quit has been requested.
+ let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(
+ Ci.nsISupportsPRBool
+ );
+ Services.obs.notifyObservers(
+ cancelQuit,
+ "quit-application-requested",
+ "restart"
+ );
+ // Something aborted the quit process.
+ if (cancelQuit.data) {
+ return;
+ }
+ // If already in safe mode restart in safe mode.
+ if (Services.appinfo.inSafeMode) {
+ Services.startup.restartInSafeMode(Ci.nsIAppStartup.eAttemptQuit);
+ } else {
+ Services.startup.quit(
+ Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart
+ );
+ }
+}
+
+function random(seed) {
+ let x = Math.sin(seed) * 10000;
+ return x - Math.floor(x);
+}
+
+function shuffle(array, seed) {
+ for (let i = array.length - 1; i > 0; i--) {
+ const j = Math.floor(random(seed) * (i + 1));
+ [array[i], array[j]] = [array[j], array[i]];
+ }
+}
+
+/**
+ * Loads the default QuickActions.
+ */
+export class QuickActionsLoaderDefault {
+ static async load() {
+ let keys = Object.keys(DEFAULT_ACTIONS);
+ if (lazy.UrlbarPrefs.get("quickactions.randomOrderActions")) {
+ // We insert the actions in a random order which means they will be returned
+ // in a random but consistent order (the order of results for "view" and "views"
+ // should be the same).
+ // We use the Nimbus randomizationId as the seed as the order should not change
+ // for the user between restarts, it should be random between users but a user should
+ // see actions the same order.
+ let seed = [...lazy.ClientEnvironment.randomizationId]
+ .map(x => x.charCodeAt(0))
+ .reduce((sum, a) => sum + a, 0);
+ shuffle(keys, seed);
+ }
+ for (const key of keys) {
+ let actionData = DEFAULT_ACTIONS[key];
+ let messages = await lazy.gFluentStrings.formatMessages(
+ actionData.l10nCommands.map(id => ({ id }))
+ );
+ actionData.commands = messages
+ .map(({ value }) => value.split(",").map(x => x.trim().toLowerCase()))
+ .flat();
+ lazy.UrlbarProviderQuickActions.addAction(key, actionData);
+ }
+ }
+}