fune/toolkit/components/messaging-system/lib/SpecialMessageActions.jsm
Andrei Oprea 459f8ef74c Bug 1702000 - Add pin to taskbar action to the primary button r=andreio
Share needPin and pin methods from ShellService and reuse from default prompt, upgrade dialog and special message actions. Use these to show "primary" vs "default" in the prompt.

Differential Revision: https://phabricator.services.mozilla.com/D111244
2021-04-14 15:09:34 +00:00

317 lines
10 KiB
JavaScript

/* 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/. */
"use strict";
const EXPORTED_SYMBOLS = ["SpecialMessageActions"];
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
const DOH_DOORHANGER_DECISION_PREF = "doh-rollout.doorhanger-decision";
const NETWORK_TRR_MODE_PREF = "network.trr.mode";
XPCOMUtils.defineLazyModuleGetters(this, {
AddonManager: "resource://gre/modules/AddonManager.jsm",
UITour: "resource:///modules/UITour.jsm",
FxAccounts: "resource://gre/modules/FxAccounts.jsm",
MigrationUtils: "resource:///modules/MigrationUtils.jsm",
});
const SpecialMessageActions = {
// This is overridden by ASRouter.init
blockMessageById() {
throw new Error("ASRouter not intialized yet");
},
/**
* loadAddonIconInURLBar - load addons-notification icon by displaying
* box containing addons icon in urlbar. See Bug 1513882
*
* @param {Browser} browser browser element for showing addons icon
*/
loadAddonIconInURLBar(browser) {
if (!browser) {
return;
}
const chromeDoc = browser.ownerDocument;
let notificationPopupBox = chromeDoc.getElementById(
"notification-popup-box"
);
if (!notificationPopupBox) {
return;
}
if (
notificationPopupBox.style.display === "none" ||
notificationPopupBox.style.display === ""
) {
notificationPopupBox.style.display = "block";
}
},
/**
*
* @param {Browser} browser The revelant Browser
* @param {string} url URL to look up install location
* @param {string} telemetrySource Telemetry information to pass to getInstallForURL
*/
async installAddonFromURL(browser, url, telemetrySource = "amo") {
try {
this.loadAddonIconInURLBar(browser);
const aUri = Services.io.newURI(url);
const systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
// AddonManager installation source associated to the addons installed from activitystream's CFR
// and RTAMO (source is going to be "amo" if not configured explicitly in the message provider).
const telemetryInfo = { source: telemetrySource };
const install = await AddonManager.getInstallForURL(aUri.spec, {
telemetryInfo,
});
await AddonManager.installAddonFromWebpage(
"application/x-xpinstall",
browser,
systemPrincipal,
install
);
} catch (e) {
Cu.reportError(e);
}
},
/**
* Pin Firefox to taskbar.
*
* @param {Window} window Reference to a window object
*/
pinFirefoxToTaskbar(window) {
window.getShellService().pinToTaskbar();
},
/**
* Set browser as the operating system default browser.
*
* @param {Window} window Reference to a window object
*/
setDefaultBrowser(window) {
window.getShellService().setAsDefault();
},
/**
* Reset browser homepage and newtab to default with a certain section configuration
*
* @param {"default"|null} home Value to set for browser homepage
* @param {"default"|null} newtab Value to set for browser newtab
* @param {obj} layout Configuration options for newtab sections
* @returns {undefined}
*/
configureHomepage({ homePage = null, newtab = null, layout = null }) {
// Homepage can be default, blank or a custom url
if (homePage === "default") {
Services.prefs.clearUserPref("browser.startup.homepage");
}
// Newtab page can only be default or blank
if (newtab === "default") {
Services.prefs.clearUserPref("browser.newtabpage.enabled");
}
if (layout) {
// Existing prefs that interact with the newtab page layout, we default to true
// or payload configuration
let newtabConfigurations = [
[
// controls the search bar
"browser.newtabpage.activity-stream.showSearch",
layout.search,
],
[
// controls the topsites
"browser.newtabpage.activity-stream.feeds.topsites",
layout.topsites,
// User can control number of topsite rows
["browser.newtabpage.activity-stream.topSitesRows"],
],
[
// controls the highlights section
"browser.newtabpage.activity-stream.feeds.section.highlights",
layout.highlights,
// User can control number of rows and highlight sources
[
"browser.newtabpage.activity-stream.section.highlights.rows",
"browser.newtabpage.activity-stream.section.highlights.includeVisited",
"browser.newtabpage.activity-stream.section.highlights.includePocket",
"browser.newtabpage.activity-stream.section.highlights.includeDownloads",
"browser.newtabpage.activity-stream.section.highlights.includeBookmarks",
],
],
[
// controls the snippets section
"browser.newtabpage.activity-stream.feeds.snippets",
layout.snippets,
],
[
// controls the topstories section
"browser.newtabpage.activity-stream.feeds.system.topstories",
layout.topstories,
],
].filter(
// If a section has configs that the user changed we will skip that section
([, , sectionConfigs]) =>
!sectionConfigs ||
sectionConfigs.every(
prefName => !Services.prefs.prefHasUserValue(prefName)
)
);
for (let [prefName, prefValue] of newtabConfigurations) {
Services.prefs.setBoolPref(prefName, prefValue);
}
}
},
/**
* Processes "Special Message Actions", which are definitions of behaviors such as opening tabs
* installing add-ons, or focusing the awesome bar that are allowed to can be triggered from
* Messaging System interactions.
*
* @param {{type: string, data?: any}} action User action defined in message JSON.
* @param browser {Browser} The browser most relvant to the message.
*/
async handleAction(action, browser) {
const window = browser.ownerGlobal;
switch (action.type) {
case "SHOW_MIGRATION_WIZARD":
MigrationUtils.showMigrationWizard(window, [
MigrationUtils.MIGRATION_ENTRYPOINT_NEWTAB,
action.data?.source,
]);
break;
case "OPEN_PRIVATE_BROWSER_WINDOW":
// Forcefully open about:privatebrowsing
window.OpenBrowserWindow({ private: true });
break;
case "OPEN_URL":
window.openLinkIn(
Services.urlFormatter.formatURL(action.data.args),
action.data.where || "current",
{
private: false,
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal(
{}
),
csp: null,
}
);
break;
case "OPEN_ABOUT_PAGE":
let aboutPageURL = new URL(`about:${action.data.args}`);
if (action.data.entrypoint) {
aboutPageURL.search = action.data.entrypoint;
}
window.openTrustedLinkIn(
aboutPageURL.toString(),
action.data.where || "tab"
);
break;
case "OPEN_PREFERENCES_PAGE":
window.openPreferences(
action.data.category || action.data.args,
action.data.entrypoint && {
urlParams: { entrypoint: action.data.entrypoint },
}
);
break;
case "OPEN_APPLICATIONS_MENU":
UITour.showMenu(window, action.data.args);
break;
case "HIGHLIGHT_FEATURE":
const highlight = await UITour.getTarget(window, action.data.args);
if (highlight) {
await UITour.showHighlight(window, highlight, "none", {
autohide: true,
});
}
break;
case "INSTALL_ADDON_FROM_URL":
await this.installAddonFromURL(
browser,
action.data.url,
action.data.telemetrySource
);
break;
case "PIN_FIREFOX_TO_TASKBAR":
this.pinFirefoxToTaskbar(window);
break;
case "PIN_AND_DEFAULT":
this.pinFirefoxToTaskbar(window);
this.setDefaultBrowser(window);
break;
case "SET_DEFAULT_BROWSER":
this.setDefaultBrowser(window);
break;
case "PIN_CURRENT_TAB":
let tab = window.gBrowser.selectedTab;
window.gBrowser.pinTab(tab);
window.ConfirmationHint.show(tab, "pinTab", {
showDescription: true,
});
break;
case "SHOW_FIREFOX_ACCOUNTS":
const data = action.data;
const url = await FxAccounts.config.promiseConnectAccountURI(
(data && data.entrypoint) || "snippets",
(data && data.extraParams) || {}
);
// We want to replace the current tab.
window.openLinkIn(url, "current", {
private: false,
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal(
{}
),
csp: null,
});
break;
case "OPEN_PROTECTION_PANEL":
let { gProtectionsHandler } = window;
gProtectionsHandler.showProtectionsPopup({});
break;
case "OPEN_PROTECTION_REPORT":
window.gProtectionsHandler.openProtections();
break;
case "OPEN_AWESOME_BAR":
window.gURLBar.search("");
break;
case "DISABLE_STP_DOORHANGERS":
await this.blockMessageById([
"SOCIAL_TRACKING_PROTECTION",
"FINGERPRINTERS_PROTECTION",
"CRYPTOMINERS_PROTECTION",
]);
break;
case "DISABLE_DOH":
Services.prefs.setStringPref(
DOH_DOORHANGER_DECISION_PREF,
"UIDisabled"
);
Services.prefs.setIntPref(NETWORK_TRR_MODE_PREF, 5);
break;
case "ACCEPT_DOH":
Services.prefs.setStringPref(DOH_DOORHANGER_DECISION_PREF, "UIOk");
break;
case "CANCEL":
// A no-op used by CFRs that minimizes the notification but does not
// trigger a dismiss or block (it keeps the notification around)
break;
case "CONFIGURE_HOMEPAGE":
this.configureHomepage(action.data);
const topWindow = browser.ownerGlobal.window.BrowserWindowTracker.getTopWindow();
if (topWindow) {
topWindow.BrowserHome();
}
break;
default:
throw new Error(
`Special message action with type ${action.type} is unsupported.`
);
}
},
};