Backed out changeset 2dd9568a9044 (bug 1636463) for perma failures on browser_asrouter_cfr.js. CLOSED TREE

This commit is contained in:
Razvan Maries 2020-05-20 18:13:24 +03:00
Родитель cf5da96e9f
Коммит b1b900f50c
14 изменённых файлов: 680 добавлений и 169 удалений

Просмотреть файл

@ -161,6 +161,28 @@ for (const type of [
actionTypes[type] = type;
}
// These are acceptable actions for AS Router messages to have. They can show up
// as call-to-action buttons in snippets, onboarding tour, etc.
const ASRouterActions = {};
for (const type of [
"HIGHLIGHT_FEATURE",
"INSTALL_ADDON_FROM_URL",
"OPEN_APPLICATIONS_MENU",
"OPEN_PRIVATE_BROWSER_WINDOW",
"OPEN_URL",
"OPEN_ABOUT_PAGE",
"OPEN_PREFERENCES_PAGE",
"SHOW_FIREFOX_ACCOUNTS",
"PIN_CURRENT_TAB",
"ENABLE_FIREFOX_MONITOR",
"OPEN_PROTECTION_PANEL",
"OPEN_PROTECTION_REPORT",
"DISABLE_STP_DOORHANGERS",
"SHOW_MIGRATION_WIZARD",
]) {
ASRouterActions[type] = type;
}
// Helper function for creating routed actions between content and main
// Not intended to be used by consumers
function _RouteMessage(action, options) {
@ -415,6 +437,7 @@ function WebExtEvent(type, data, importContext = globalImportContext) {
}
this.actionTypes = actionTypes;
this.ASRouterActions = ASRouterActions;
this.actionCreators = {
BroadcastToContent,
@ -492,6 +515,7 @@ const EXPORTED_SYMBOLS = [
"actionTypes",
"actionCreators",
"actionUtils",
"ASRouterActions",
"globalImportContext",
"UI_CODE",
"BACKGROUND_PROCESS",

Просмотреть файл

@ -2,7 +2,11 @@
* 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 { actionCreators as ac, actionTypes as at } from "common/Actions.jsm";
import {
actionCreators as ac,
actionTypes as at,
ASRouterActions as ra,
} from "common/Actions.jsm";
import { OUTGOING_MESSAGE_NAME as AS_GENERAL_OUTGOING_MESSAGE_NAME } from "content-src/lib/init-store";
import { generateBundles } from "./rich-text-strings";
import { ImpressionsWrapper } from "./components/ImpressionsWrapper/ImpressionsWrapper";
@ -345,9 +349,9 @@ export class ASRouterUISurface extends React.PureComponent {
async onUserAction(action) {
switch (action.type) {
// This needs to be handled locally because its
case "ENABLE_FIREFOX_MONITOR":
case ra.ENABLE_FIREFOX_MONITOR:
const url = await this.getMonitorUrl(action.data.args);
ASRouterUtils.executeAction({ type: "OPEN_URL", data: { args: url } });
ASRouterUtils.executeAction({ type: ra.OPEN_URL, data: { args: url } });
break;
default:
ASRouterUtils.executeAction(action);

Просмотреть файл

@ -210,6 +210,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BACKGROUND_PROCESS", function() { return BACKGROUND_PROCESS; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "globalImportContext", function() { return globalImportContext; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "actionTypes", function() { return actionTypes; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ASRouterActions", function() { return ASRouterActions; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "actionCreators", function() { return actionCreators; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "actionUtils", function() { return actionUtils; });
/* This Source Code Form is subject to the terms of the Mozilla Public
@ -239,6 +240,14 @@ const actionTypes = {};
for (const type of ["ADDONS_INFO_REQUEST", "ADDONS_INFO_RESPONSE", "ARCHIVE_FROM_POCKET", "AS_ROUTER_INITIALIZED", "AS_ROUTER_PREF_CHANGED", "AS_ROUTER_TARGETING_UPDATE", "AS_ROUTER_TELEMETRY_USER_EVENT", "BLOCK_URL", "BOOKMARK_URL", "CLEAR_PREF", "COPY_DOWNLOAD_LINK", "DELETE_BOOKMARK_BY_ID", "DELETE_FROM_POCKET", "DELETE_HISTORY_URL", "DIALOG_CANCEL", "DIALOG_OPEN", "DISCOVERY_STREAM_COLLECTION_DISMISSIBLE_TOGGLE", "DISCOVERY_STREAM_CONFIG_CHANGE", "DISCOVERY_STREAM_CONFIG_RESET", "DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS", "DISCOVERY_STREAM_CONFIG_SETUP", "DISCOVERY_STREAM_CONFIG_SET_VALUE", "DISCOVERY_STREAM_DEV_EXPIRE_CACHE", "DISCOVERY_STREAM_DEV_IDLE_DAILY", "DISCOVERY_STREAM_DEV_SYNC_RS", "DISCOVERY_STREAM_DEV_SYSTEM_TICK", "DISCOVERY_STREAM_FEEDS_UPDATE", "DISCOVERY_STREAM_FEED_UPDATE", "DISCOVERY_STREAM_IMPRESSION_STATS", "DISCOVERY_STREAM_LAYOUT_RESET", "DISCOVERY_STREAM_LAYOUT_UPDATE", "DISCOVERY_STREAM_LINK_BLOCKED", "DISCOVERY_STREAM_LOADED_CONTENT", "DISCOVERY_STREAM_PERSONALIZATION_INIT", "DISCOVERY_STREAM_PERSONALIZATION_LAST_UPDATED", "DISCOVERY_STREAM_PERSONALIZATION_VERSION", "DISCOVERY_STREAM_PERSONALIZATION_VERSION_TOGGLE", "DISCOVERY_STREAM_RETRY_FEED", "DISCOVERY_STREAM_SPOCS_CAPS", "DISCOVERY_STREAM_SPOCS_ENDPOINT", "DISCOVERY_STREAM_SPOCS_FILL", "DISCOVERY_STREAM_SPOCS_PLACEMENTS", "DISCOVERY_STREAM_SPOCS_UPDATE", "DISCOVERY_STREAM_SPOC_BLOCKED", "DISCOVERY_STREAM_SPOC_IMPRESSION", "DOWNLOAD_CHANGED", "FAKE_FOCUS_SEARCH", "FILL_SEARCH_TERM", "HANDOFF_SEARCH_TO_AWESOMEBAR", "HIDE_PRIVACY_INFO", "HIDE_SEARCH", "INIT", "NEW_TAB_INIT", "NEW_TAB_INITIAL_STATE", "NEW_TAB_LOAD", "NEW_TAB_REHYDRATED", "NEW_TAB_STATE_REQUEST", "NEW_TAB_UNLOAD", "OPEN_DOWNLOAD_FILE", "OPEN_LINK", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "OPEN_WEBEXT_SETTINGS", "PLACES_BOOKMARK_ADDED", "PLACES_BOOKMARK_REMOVED", "PLACES_HISTORY_CLEARED", "PLACES_LINKS_CHANGED", "PLACES_LINK_BLOCKED", "PLACES_LINK_DELETED", "PLACES_SAVED_TO_POCKET", "POCKET_CTA", "POCKET_LINK_DELETED_OR_ARCHIVED", "POCKET_LOGGED_IN", "POCKET_WAITING_FOR_SPOC", "PREFS_INITIAL_VALUES", "PREF_CHANGED", "PREVIEW_REQUEST", "PREVIEW_REQUEST_CANCEL", "PREVIEW_RESPONSE", "REMOVE_DOWNLOAD_FILE", "RICH_ICON_MISSING", "SAVE_SESSION_PERF_DATA", "SAVE_TO_POCKET", "SCREENSHOT_UPDATED", "SECTION_DEREGISTER", "SECTION_DISABLE", "SECTION_ENABLE", "SECTION_MOVE", "SECTION_OPTIONS_CHANGED", "SECTION_REGISTER", "SECTION_UPDATE", "SECTION_UPDATE_CARD", "SETTINGS_CLOSE", "SETTINGS_OPEN", "SET_PREF", "SHOW_DOWNLOAD_FILE", "SHOW_FIREFOX_ACCOUNTS", "SHOW_PRIVACY_INFO", "SHOW_SEARCH", "SKIPPED_SIGNIN", "SNIPPETS_BLOCKLIST_CLEARED", "SNIPPETS_BLOCKLIST_UPDATED", "SNIPPETS_DATA", "SNIPPETS_PREVIEW_MODE", "SNIPPETS_RESET", "SNIPPET_BLOCKED", "SUBMIT_EMAIL", "SUBMIT_SIGNIN", "SYSTEM_TICK", "TELEMETRY_IMPRESSION_STATS", "TELEMETRY_PERFORMANCE_EVENT", "TELEMETRY_UNDESIRED_EVENT", "TELEMETRY_USER_EVENT", "TOP_SITES_CANCEL_EDIT", "TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_EDIT", "TOP_SITES_INSERT", "TOP_SITES_OPEN_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_PIN", "TOP_SITES_PREFS_UPDATED", "TOP_SITES_UNPIN", "TOP_SITES_UPDATED", "TOTAL_BOOKMARKS_REQUEST", "TOTAL_BOOKMARKS_RESPONSE", "TRAILHEAD_ENROLL_EVENT", "UNINIT", "UPDATE_PINNED_SEARCH_SHORTCUTS", "UPDATE_SEARCH_SHORTCUTS", "UPDATE_SECTION_PREFS", "WEBEXT_CLICK", "WEBEXT_DISMISS"]) {
actionTypes[type] = type;
} // These are acceptable actions for AS Router messages to have. They can show up
// as call-to-action buttons in snippets, onboarding tour, etc.
const ASRouterActions = {};
for (const type of ["HIGHLIGHT_FEATURE", "INSTALL_ADDON_FROM_URL", "OPEN_APPLICATIONS_MENU", "OPEN_PRIVATE_BROWSER_WINDOW", "OPEN_URL", "OPEN_ABOUT_PAGE", "OPEN_PREFERENCES_PAGE", "SHOW_FIREFOX_ACCOUNTS", "PIN_CURRENT_TAB", "ENABLE_FIREFOX_MONITOR", "OPEN_PROTECTION_PANEL", "OPEN_PROTECTION_REPORT", "DISABLE_STP_DOORHANGERS", "SHOW_MIGRATION_WIZARD"]) {
ASRouterActions[type] = type;
} // Helper function for creating routed actions between content and main
// Not intended to be used by consumers
@ -2576,10 +2585,10 @@ class ASRouterUISurface extends react__WEBPACK_IMPORTED_MODULE_6___default.a.Pur
async onUserAction(action) {
switch (action.type) {
// This needs to be handled locally because its
case "ENABLE_FIREFOX_MONITOR":
case common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["ASRouterActions"].ENABLE_FIREFOX_MONITOR:
const url = await this.getMonitorUrl(action.data.args);
ASRouterUtils.executeAction({
type: "OPEN_URL",
type: common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["ASRouterActions"].OPEN_URL,
data: {
args: url
}

Просмотреть файл

@ -9,6 +9,9 @@ const { XPCOMUtils } = ChromeUtils.import(
);
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
XPCOMUtils.defineLazyModuleGetters(this, {
AddonManager: "resource://gre/modules/AddonManager.jsm",
UITour: "resource:///modules/UITour.jsm",
FxAccounts: "resource://gre/modules/FxAccounts.jsm",
AppConstants: "resource://gre/modules/AppConstants.jsm",
OS: "resource://gre/modules/osfile.jsm",
BookmarkPanelHub: "resource://activity-stream/lib/BookmarkPanelHub.jsm",
@ -31,16 +34,17 @@ XPCOMUtils.defineLazyModuleGetters(this, {
KintoHttpClient: "resource://services-common/kinto-http-client.js",
Downloader: "resource://services-settings/Attachments.jsm",
RemoteL10n: "resource://activity-stream/lib/RemoteL10n.jsm",
MigrationUtils: "resource:///modules/MigrationUtils.jsm",
ExperimentAPI: "resource://messaging-system/experiments/ExperimentAPI.jsm",
SpecialMessageActions:
"resource://messaging-system/lib/SpecialMessageActions.jsm",
});
XPCOMUtils.defineLazyServiceGetters(this, {
BrowserHandler: ["@mozilla.org/browser/clh;1", "nsIBrowserHandler"],
});
const { actionTypes: at, actionCreators: ac } = ChromeUtils.import(
"resource://activity-stream/common/Actions.jsm"
);
const {
ASRouterActions: ra,
actionTypes: at,
actionCreators: ac,
} = ChromeUtils.import("resource://activity-stream/common/Actions.jsm");
const { CFRMessageProvider } = ChromeUtils.import(
"resource://activity-stream/lib/CFRMessageProvider.jsm"
@ -471,6 +475,54 @@ const MessageLoaderUtils = {
};
},
/**
* _loadAddonIconInURLBar - load addons-notification icon by displaying
* box containing addons icon in urlbar. See Bug 1513882
*
* @param {XULElement} Target 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";
}
},
async installAddonFromURL(browser, url, telemetrySource = "amo") {
try {
MessageLoaderUtils._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);
}
},
/**
* cleanupCache - Removes cached data of removed providers.
*
@ -910,6 +962,7 @@ class _ASRouter {
ToolbarPanelHub.init(this.waitForInitialized, {
getMessages: this.handleMessageRequest,
dispatch: this.dispatch,
handleUserAction: this.handleUserAction,
});
MomentsPageHub.init(this.waitForInitialized, {
handleMessageRequest: this.handleMessageRequest,
@ -966,7 +1019,6 @@ class _ASRouter {
})
);
SpecialMessageActions.blockMessageById = this.blockMessageById;
Services.obs.addObserver(this._onLocaleChanged, TOPIC_INTL_LOCALE_CHANGED);
Services.prefs.addObserver(USE_REMOTE_L10N_PREF, this);
// sets .initialized to true and resolves .waitForInitialized promise
@ -1873,6 +1925,110 @@ class _ASRouter {
await this.loadMessagesFromAllProviders();
}
async handleUserAction({ data: action, target }) {
switch (action.type) {
case ra.SHOW_MIGRATION_WIZARD:
MigrationUtils.showMigrationWizard(target.browser.ownerGlobal, [
MigrationUtils.MIGRATION_ENTRYPOINT_NEWTAB,
]);
break;
case ra.OPEN_PRIVATE_BROWSER_WINDOW:
// Forcefully open about:privatebrowsing
target.browser.ownerGlobal.OpenBrowserWindow({ private: true });
break;
case ra.OPEN_URL:
target.browser.ownerGlobal.openLinkIn(
Services.urlFormatter.formatURL(action.data.args),
action.data.where || "current",
{
private: false,
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal(
{}
),
csp: null,
}
);
break;
case ra.OPEN_ABOUT_PAGE:
let aboutPageURL = new URL(`about:${action.data.args}`);
if (action.data.entrypoint) {
aboutPageURL.search = action.data.entrypoint;
}
target.browser.ownerGlobal.openTrustedLinkIn(
aboutPageURL.toString(),
"tab"
);
break;
case ra.OPEN_PREFERENCES_PAGE:
target.browser.ownerGlobal.openPreferences(
action.data.category || action.data.args,
action.data.entrypoint && {
urlParams: { entrypoint: action.data.entrypoint },
}
);
break;
case ra.OPEN_APPLICATIONS_MENU:
UITour.showMenu(target.browser.ownerGlobal, action.data.args);
break;
case ra.HIGHLIGHT_FEATURE:
const highlight = await UITour.getTarget(
target.browser.ownerGlobal,
action.data.args
);
if (highlight) {
await UITour.showHighlight(
target.browser.ownerGlobal,
highlight,
"none",
{ autohide: true }
);
}
break;
case ra.INSTALL_ADDON_FROM_URL:
this._updateOnboardingState();
await MessageLoaderUtils.installAddonFromURL(
target.browser,
action.data.url,
action.data.telemetrySource
);
break;
case ra.PIN_CURRENT_TAB:
let tab = target.browser.ownerGlobal.gBrowser.selectedTab;
target.browser.ownerGlobal.gBrowser.pinTab(tab);
target.browser.ownerGlobal.ConfirmationHint.show(tab, "pinTab", {
showDescription: true,
});
break;
case ra.SHOW_FIREFOX_ACCOUNTS:
const url = await FxAccounts.config.promiseConnectAccountURI(
"snippets"
);
// We want to replace the current tab.
target.browser.ownerGlobal.openLinkIn(url, "current", {
private: false,
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal(
{}
),
csp: null,
});
break;
case ra.OPEN_PROTECTION_PANEL:
let { gProtectionsHandler } = target.browser.ownerGlobal;
gProtectionsHandler.showProtectionsPopup({});
break;
case ra.OPEN_PROTECTION_REPORT:
target.browser.ownerGlobal.gProtectionsHandler.openProtections();
break;
case ra.DISABLE_STP_DOORHANGERS:
await this.blockMessageById([
"SOCIAL_TRACKING_PROTECTION",
"FINGERPRINTERS_PROTECTION",
"CRYPTOMINERS_PROTECTION",
]);
break;
}
}
/**
* sendAsyncMessageToPreloaded - Sends an action to each preloaded browser, if any
*
@ -2001,11 +2157,9 @@ class _ASRouter {
async onMessage({ data: action, target }) {
switch (action.type) {
case "USER_ACTION":
// This is to support ReturnToAMO
if (action.data.type === "INSTALL_ADDON_FROM_URL") {
this._updateOnboardingState();
if (action.data.type in ra) {
await this.handleUserAction({ data: action.data, target });
}
await SpecialMessageActions.handleAction(action.data, target.browser);
break;
case "NEWTAB_MESSAGE_REQUEST":
await this.waitForInitialized;

Просмотреть файл

@ -7,6 +7,9 @@ const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { ASRouterActions: ra } = ChromeUtils.import(
"resource://activity-stream/common/Actions.jsm"
);
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
@ -872,7 +875,7 @@ class PageAction {
{
type: "USER_ACTION",
data: {
type: "OPEN_URL",
type: ra.OPEN_URL,
data: {
args: message.content.action.url,
where: message.content.action.where,

Просмотреть файл

@ -11,8 +11,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
EveryWindow: "resource:///modules/EveryWindow.jsm",
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
Preferences: "resource://gre/modules/Preferences.jsm",
SpecialMessageActions:
"resource://messaging-system/lib/SpecialMessageActions.jsm",
});
XPCOMUtils.defineLazyServiceGetter(
this,
@ -53,9 +51,10 @@ class _ToolbarPanelHub {
this.state = {};
}
async init(waitForInitialized, { getMessages, dispatch }) {
async init(waitForInitialized, { getMessages, dispatch, handleUserAction }) {
this._getMessages = getMessages;
this._dispatch = dispatch;
this._handleUserAction = handleUserAction;
// Wait for ASRouter messages to become available in order to know
// if we can show the What's New panel
await waitForInitialized;
@ -240,16 +239,16 @@ class _ToolbarPanelHub {
Cu.reportError(e);
url = message.content.cta_url;
}
SpecialMessageActions.handleAction(
{
this._handleUserAction({
target: win,
data: {
type: message.content.cta_type,
data: {
args: url,
where: "tabshifted",
},
},
win.browser
);
});
this.sendUserEventTelemetry(win, "CLICK", message);
}

Просмотреть файл

@ -61,7 +61,9 @@ const createDummyRecommendation = ({
value: "Cancel",
attributes: { accesskey: "C" },
},
action: { type: "CANCEL" },
action: {
type: "CANCEL",
},
},
{
label: {
@ -149,10 +151,11 @@ function checkCFRTrackingProtectionMilestone(notification) {
}
function clearNotifications() {
CFRPageActions.clearRecommendations();
for (let notification of PopupNotifications._currentNotifications) {
notification.remove();
}
// Clicking the primary action also removes the notification
Assert.equal(
PopupNotifications._currentNotifications.length,
0,
@ -164,7 +167,7 @@ function trigger_cfr_panel(
browser,
trigger,
{
action = { type: "OPEN_APPLICATIONS_MENU", data: { args: "fake" } },
action = { type: "FOO" },
heading_text,
category = "cfrAddons",
layout,
@ -191,6 +194,7 @@ function trigger_cfr_panel(
];
}
clearNotifications();
if (recommendation.template === "milestone_message") {
return CFRPageActions.showMilestone(
browser,
@ -217,6 +221,7 @@ add_task(async function setup() {
registerCleanupFunction(() => {
CFRPageActions._fetchLatestAddonVersion = _fetchLatestAddonVersion;
clearNotifications();
CFRPageActions.clearRecommendations();
});
});
@ -327,13 +332,17 @@ add_task(async function test_cfr_notification_show() {
PopupNotifications.panel,
"popuphidden"
);
// Clicking the primary action also removes the notification
document
.getElementById("contextual-feature-recommendation-notification")
.button.click();
await hidePanel;
clearNotifications();
// Clicking the primary action also removes the notification
Assert.equal(
PopupNotifications._currentNotifications.length,
0,
"Should have removed the notification"
);
});
add_task(async function test_cfr_notification_minimize() {
@ -381,7 +390,6 @@ add_task(async function test_cfr_notification_minimize() {
.getElementById("contextual-feature-recommendation-notification")
.button.click();
await hidePanel;
clearNotifications();
});
add_task(async function test_cfr_notification_minimize_2() {
@ -443,6 +451,7 @@ add_task(async function test_cfr_notification_minimize_2() {
);
clearNotifications();
CFRPageActions.clearRecommendations();
});
add_task(async function test_cfr_addon_install() {
@ -506,25 +515,15 @@ add_task(async function test_cfr_addon_install() {
add_task(async function test_cfr_pin_tab_notification_show() {
// addRecommendation checks that scheme starts with http and host matches
await BrowserTestUtils.loadURI(
gBrowser.selectedBrowser,
"http://example.com/"
);
await BrowserTestUtils.browserLoaded(
gBrowser.selectedBrowser,
false,
"http://example.com/"
);
let browser = gBrowser.selectedBrowser;
await BrowserTestUtils.loadURI(browser, "http://example.com/");
await BrowserTestUtils.browserLoaded(browser, false, "http://example.com/");
const response = await trigger_cfr_panel(
gBrowser.selectedBrowser,
"example.com",
{
action: { type: "PIN_CURRENT_TAB" },
category: "cfrFeatures",
layout: "message_and_animation",
}
);
const response = await trigger_cfr_panel(browser, "example.com", {
action: { type: "PIN_CURRENT_TAB" },
category: "cfrFeatures",
layout: "message_and_animation",
});
Assert.ok(
response,
"Should return true if addRecommendation checks were successful"

Просмотреть файл

@ -210,9 +210,6 @@ describe("ASRouter", () => {
getExperiment: sandbox.stub().returns({ branch: { value: [] } }),
ready: sandbox.stub().resolves(),
},
SpecialMessageActions: {
handleAction: sandbox.stub(),
},
});
await createRouterAndInit();
});
@ -286,6 +283,7 @@ describe("ASRouter", () => {
{
getMessages: Router.handleMessageRequest,
dispatch: Router.dispatch,
handleUserAction: Router.handleUserAction,
}
);
@ -2601,6 +2599,264 @@ describe("ASRouter", () => {
});
});
describe("#onMessage: Onboarding actions", () => {
it("should call OpenBrowserWindow with a private window on OPEN_PRIVATE_BROWSER_WINDOW", async () => {
let [testMessage] = Router.state.messages;
const msg = fakeExecuteUserAction({
type: "OPEN_PRIVATE_BROWSER_WINDOW",
data: testMessage,
});
await Router.onMessage(msg);
assert.calledWith(msg.target.browser.ownerGlobal.OpenBrowserWindow, {
private: true,
});
});
it("should call openLinkIn with the correct params on OPEN_URL", async () => {
let [testMessage] = Router.state.messages;
testMessage.button_action = {
type: "OPEN_URL",
data: { args: "some/url.com", where: "tabshifted" },
};
const msg = fakeExecuteUserAction(testMessage.button_action);
await Router.onMessage(msg);
assert.calledOnce(msg.target.browser.ownerGlobal.openLinkIn);
assert.calledWith(
msg.target.browser.ownerGlobal.openLinkIn,
"some/url.com",
"tabshifted",
{ private: false, triggeringPrincipal: undefined, csp: null }
);
});
it("should call openLinkIn with the correct params on OPEN_ABOUT_PAGE", async () => {
let [testMessage] = Router.state.messages;
testMessage.button_action = {
type: "OPEN_ABOUT_PAGE",
data: { args: "something" },
};
const msg = fakeExecuteUserAction(testMessage.button_action);
await Router.onMessage(msg);
assert.calledOnce(msg.target.browser.ownerGlobal.openTrustedLinkIn);
assert.calledWith(
msg.target.browser.ownerGlobal.openTrustedLinkIn,
"about:something",
"tab"
);
});
it("should call openLinkIn with the entrypoint params on OPEN_ABOUT_PAGE", async () => {
let [testMessage] = Router.state.messages;
testMessage.button_action = {
type: "OPEN_ABOUT_PAGE",
data: { args: "something", entrypoint: "entryPoint=foo" },
};
const msg = fakeExecuteUserAction(testMessage.button_action);
await Router.onMessage(msg);
assert.calledOnce(msg.target.browser.ownerGlobal.openTrustedLinkIn);
assert.calledWith(
msg.target.browser.ownerGlobal.openTrustedLinkIn,
"about:something?entryPoint=foo",
"tab"
);
});
it("should call MigrationUtils.showMigrationWizard on SHOW_MIGRATION_WIZARD", async () => {
let [testMessage] = Router.state.messages;
testMessage.button_action = {
type: "SHOW_MIGRATION_WIZARD",
};
const msg = fakeExecuteUserAction(testMessage.button_action);
globals.set("MigrationUtils", {
showMigrationWizard: sandbox
.stub()
.withArgs(msg.target.browser.ownerGlobal, ["test"]),
MIGRATION_ENTRYPOINT_NEWTAB: "test",
});
await Router.onMessage(msg);
assert.calledOnce(MigrationUtils.showMigrationWizard);
assert.calledWith(
MigrationUtils.showMigrationWizard,
msg.target.browser.ownerGlobal,
[MigrationUtils.MIGRATION_ENTRYPOINT_NEWTAB]
);
});
});
describe("#onMessage: SHOW_FIREFOX_ACCOUNTS", () => {
beforeEach(() => {
globals.set("FxAccounts", {
config: {
promiseConnectAccountURI: sandbox.stub().resolves("some/url"),
},
});
});
it("should call openLinkIn with the correct params on OPEN_URL", async () => {
let [testMessage] = Router.state.messages;
testMessage.button_action = { type: "SHOW_FIREFOX_ACCOUNTS" };
const msg = fakeExecuteUserAction(testMessage.button_action);
await Router.onMessage(msg);
assert.calledOnce(msg.target.browser.ownerGlobal.openLinkIn);
assert.calledWith(
msg.target.browser.ownerGlobal.openLinkIn,
"some/url",
"current",
{ private: false, triggeringPrincipal: undefined, csp: null }
);
});
});
describe("#onMessage: OPEN_PREFERENCES_PAGE", () => {
it("should call openPreferences with the correct params on OPEN_PREFERENCES_PAGE", async () => {
let [testMessage] = Router.state.messages;
testMessage.button_action = {
type: "OPEN_PREFERENCES_PAGE",
data: { category: "something" },
};
const msg = fakeExecuteUserAction(testMessage.button_action);
await Router.onMessage(msg);
assert.calledOnce(msg.target.browser.ownerGlobal.openPreferences);
assert.calledWith(
msg.target.browser.ownerGlobal.openPreferences,
"something"
);
});
it("should call openPreferences with the correct params on OPEN_PREFERENCES_PAGE (snippets payload)", async () => {
let [testMessage] = Router.state.messages;
testMessage.button_action = {
type: "OPEN_PREFERENCES_PAGE",
data: { args: "arg_from_snippets" },
};
const msg = fakeExecuteUserAction(testMessage.button_action);
await Router.onMessage(msg);
assert.calledOnce(msg.target.browser.ownerGlobal.openPreferences);
assert.calledWith(
msg.target.browser.ownerGlobal.openPreferences,
"arg_from_snippets"
);
});
it("should call openPreferences with the correct entrypoint if defined", async () => {
let [testMessage] = Router.state.messages;
testMessage.button_action = {
type: "OPEN_PREFERENCES_PAGE",
data: { category: "something", entrypoint: "unittest" },
};
const msg = fakeExecuteUserAction(testMessage.button_action);
await Router.onMessage(msg);
assert.calledOnce(msg.target.browser.ownerGlobal.openPreferences);
assert.calledWithExactly(
msg.target.browser.ownerGlobal.openPreferences,
"something",
{ urlParams: { entrypoint: "unittest" } }
);
});
});
describe("#onMessage: INSTALL_ADDON_FROM_URL", () => {
it("should call installAddonFromURL with correct arguments", async () => {
sandbox.stub(MessageLoaderUtils, "installAddonFromURL").resolves(null);
const msg = fakeExecuteUserAction({
type: "INSTALL_ADDON_FROM_URL",
data: { url: "foo.com", telemetrySource: "foo" },
});
await Router.onMessage(msg);
assert.calledOnce(MessageLoaderUtils.installAddonFromURL);
assert.calledWithExactly(
MessageLoaderUtils.installAddonFromURL,
msg.target.browser,
"foo.com",
"foo"
);
});
it("should add/remove observers for `webextension-install-notify`", async () => {
sandbox.spy(global.Services.obs, "addObserver");
sandbox.spy(global.Services.obs, "removeObserver");
sandbox.stub(MessageLoaderUtils, "installAddonFromURL").resolves(null);
const msg = fakeExecuteUserAction({
type: "INSTALL_ADDON_FROM_URL",
data: { url: "foo.com" },
});
await Router.onMessage(msg);
assert.calledOnce(global.Services.obs.addObserver);
const [cb] = global.Services.obs.addObserver.firstCall.args;
cb();
assert.calledOnce(global.Services.obs.removeObserver);
assert.calledOnce(channel.sendAsyncMessage);
});
});
describe("#onMessage: PIN_CURRENT_TAB", () => {
it("should call pin tab with the selectedTab", async () => {
const msg = fakeExecuteUserAction({ type: "PIN_CURRENT_TAB" });
const { gBrowser, ConfirmationHint } = msg.target.browser.ownerGlobal;
await Router.onMessage(msg);
assert.calledOnce(gBrowser.pinTab);
assert.calledWithExactly(gBrowser.pinTab, gBrowser.selectedTab);
assert.calledOnce(ConfirmationHint.show);
assert.calledWithExactly(
ConfirmationHint.show,
gBrowser.selectedTab,
"pinTab",
{ showDescription: true }
);
});
});
describe("#onMessage: OPEN_PROTECTION_PANEL", () => {
it("should open protection panel", async () => {
const msg = fakeExecuteUserAction({ type: "OPEN_PROTECTION_PANEL" });
let { gProtectionsHandler } = msg.target.browser.ownerGlobal;
await Router.onMessage(msg);
assert.calledOnce(gProtectionsHandler.showProtectionsPopup);
assert.calledWithExactly(gProtectionsHandler.showProtectionsPopup, {});
});
});
describe("#onMessage: OPEN_PROTECTION_REPORT", () => {
it("should open protection report", async () => {
const msg = fakeExecuteUserAction({ type: "OPEN_PROTECTION_REPORT" });
let { gProtectionsHandler } = msg.target.browser.ownerGlobal;
await Router.onMessage(msg);
assert.calledOnce(gProtectionsHandler.openProtections);
});
});
describe("#onMessage: DISABLE_STP_DOORHANGERS", () => {
it("should block STP related messages", async () => {
const msg = fakeExecuteUserAction({ type: "DISABLE_STP_DOORHANGERS" });
assert.deepEqual(Router.state.messageBlockList, []);
await Router.onMessage(msg);
assert.deepEqual(Router.state.messageBlockList, [
"SOCIAL_TRACKING_PROTECTION",
"FINGERPRINTERS_PROTECTION",
"CRYPTOMINERS_PROTECTION",
]);
});
});
describe("#dispatch(action, target)", () => {
it("should an action and target to onMessage", async () => {
// use the IMPRESSION action to make sure actions are actually getting processed
@ -2902,50 +3158,6 @@ describe("ASRouter", () => {
assert.calledOnce(Cu.reportError);
});
});
describe("#onMessage: USER_ACTION", () => {
it("should dispatch to SpecialMessageActions", async () => {
const msg = fakeExecuteUserAction({
type: "OPEN_URL",
data: {
args: "foo",
},
});
await Router.onMessage(msg);
assert.calledOnce(global.SpecialMessageActions.handleAction);
assert.calledWithExactly(
global.SpecialMessageActions.handleAction,
msg.data.data,
msg.target.browser
);
});
it("should call update onboarding state on INSTALL_ADDON_FROM_URL", async () => {
const spy = sandbox.spy(global.Services.obs, "addObserver");
const msg = fakeExecuteUserAction({
type: "INSTALL_ADDON_FROM_URL",
});
await Router.onMessage(msg);
assert.calledOnce(spy);
assert.calledWithExactly(
spy,
sinon.match.func,
"webextension-install-notify"
);
const [eventCb] = spy.firstCall.args;
// Call the observer cb
eventCb();
assert.calledOnce(Router.messageChannel.sendAsyncMessage);
assert.calledWithExactly(
Router.messageChannel.sendAsyncMessage,
OUTGOING_MESSAGE_NAME,
{ type: "CLEAR_INTERRUPT" }
);
});
});
});
describe("_triggerHandler", () => {
@ -2978,6 +3190,51 @@ describe("ASRouter", () => {
});
});
describe("#UITour", () => {
let showMenuStub;
const highlightTarget = { target: "target" };
beforeEach(() => {
showMenuStub = sandbox.stub();
globals.set("UITour", {
showMenu: showMenuStub,
getTarget: sandbox
.stub()
.withArgs(sinon.match.object, "pageAaction-sendToDevice")
.resolves(highlightTarget),
showHighlight: sandbox.stub(),
});
});
it("should call UITour.showMenu with the correct params on OPEN_APPLICATIONS_MENU", async () => {
const msg = fakeExecuteUserAction({
type: "OPEN_APPLICATIONS_MENU",
data: { args: "appMenu" },
});
await Router.onMessage(msg);
assert.calledOnce(showMenuStub);
assert.calledWith(
showMenuStub,
msg.target.browser.ownerGlobal,
"appMenu"
);
});
it("should call UITour.showHighlight with the correct params on HIGHLIGHT_FEATURE", async () => {
const msg = fakeExecuteUserAction({
type: "HIGHLIGHT_FEATURE",
data: { args: "pageAction-sendToDevice" },
});
await Router.onMessage(msg);
assert.calledOnce(UITour.getTarget);
assert.calledOnce(UITour.showHighlight);
assert.calledWith(
UITour.showHighlight,
msg.target.browser.ownerGlobal,
highlightTarget
);
});
});
describe("valid preview endpoint", () => {
it("should report an error if url protocol is not https", () => {
sandbox.stub(Cu, "reportError");

Просмотреть файл

@ -41,7 +41,6 @@ describe("ASRouterFeed", () => {
ToolbarBadgeHub: FakeToolbarBadgeHub,
ToolbarPanelHub: FakeToolbarPanelHub,
MomentsPageHub: FakeMomentsPageHub,
SpecialMessageActions: {},
});
Router = new _ASRouter({ providers: [FAKE_LOCAL_PROVIDER] });

Просмотреть файл

@ -1,3 +1,4 @@
import { GlobalOverrider } from "test/unit/utils";
import { MessageLoaderUtils } from "lib/ASRouter.jsm";
const { STARTPAGE_VERSION } = MessageLoaderUtils;
@ -429,6 +430,111 @@ describe("MessageLoaderUtils", () => {
});
});
describe("#_loadAddonIconInURLBar", () => {
let notificationContainerEl;
let browser;
let getContainerStub;
beforeEach(() => {
notificationContainerEl = { style: {} };
browser = {
ownerDocument: {
getElementById() {
return {};
},
},
};
getContainerStub = sandbox.stub(browser.ownerDocument, "getElementById");
});
it("should return for empty args", () => {
MessageLoaderUtils._loadAddonIconInURLBar();
assert.notCalled(getContainerStub);
});
it("should return if notification popup box not found", () => {
getContainerStub.returns(null);
MessageLoaderUtils._loadAddonIconInURLBar(browser);
assert.calledOnce(getContainerStub);
});
it("should unhide notification popup box with display style as none", () => {
getContainerStub.returns(notificationContainerEl);
notificationContainerEl.style.display = "none";
MessageLoaderUtils._loadAddonIconInURLBar(browser);
assert.calledWith(
browser.ownerDocument.getElementById,
"notification-popup-box"
);
assert.equal(notificationContainerEl.style.display, "block");
});
it("should unhide notification popup box with display style empty", () => {
getContainerStub.returns(notificationContainerEl);
notificationContainerEl.style.display = "";
MessageLoaderUtils._loadAddonIconInURLBar(browser);
assert.calledWith(
browser.ownerDocument.getElementById,
"notification-popup-box"
);
assert.equal(notificationContainerEl.style.display, "block");
});
});
describe("#installAddonFromURL", () => {
let globals;
let getInstallStub;
let installAddonStub;
beforeEach(() => {
globals = new GlobalOverrider();
getInstallStub = sandbox.stub();
installAddonStub = sandbox.stub();
sandbox.stub(MessageLoaderUtils, "_loadAddonIconInURLBar").returns(null);
globals.set("AddonManager", {
getInstallForURL: getInstallStub,
installAddonFromWebpage: installAddonStub,
});
});
afterEach(() => {
globals.restore();
});
it("should call the Addons API when passed a valid URL", async () => {
getInstallStub.resolves(null);
installAddonStub.resolves(null);
await MessageLoaderUtils.installAddonFromURL({}, "foo.com");
assert.calledOnce(getInstallStub);
assert.calledOnce(installAddonStub);
// Verify that the expected installation source has been passed to the getInstallForURL
// method (See Bug 1496167 for a rationale).
assert.calledWithExactly(getInstallStub, "foo.com", {
telemetryInfo: { source: "amo" },
});
});
it("should optionally pass a custom telemetrySource to the Addons API if specified", async () => {
getInstallStub.resolves(null);
installAddonStub.resolves(null);
await MessageLoaderUtils.installAddonFromURL({}, "foo.com", "foo");
assert.calledOnce(getInstallStub);
assert.calledOnce(installAddonStub);
// Verify that a custom installation source can be passed to the getInstallForURL
// method (See Bug 1549770 for a rationale).
assert.calledWithExactly(getInstallStub, "foo.com", {
telemetryInfo: { source: "foo" },
});
});
it("should not call the Addons API on invalid URLs", async () => {
sandbox
.stub(global.Services.scriptSecurityManager, "getSystemPrincipal")
.throws();
await MessageLoaderUtils.installAddonFromURL({}, "https://foo.com");
assert.notCalled(getInstallStub);
assert.notCalled(installAddonStub);
});
});
describe("#cleanupCache", () => {
it("should remove data for providers no longer active", async () => {
const fakeStorage = {

Просмотреть файл

@ -25,6 +25,7 @@ describe("ToolbarPanelHub", () => {
let fakeDispatch;
let getEarliestRecordedDateStub;
let getEventsByDateRangeStub;
let handleUserActionStub;
let defaultSearchStub;
let scriptloaderStub;
@ -141,6 +142,7 @@ describe("ToolbarPanelHub", () => {
new Date() - 500
);
getEventsByDateRangeStub = sandbox.stub().returns([]);
handleUserActionStub = sandbox.stub();
defaultSearchStub = { defaultEngine: { name: "DDG" } };
globals.set({
EveryWindow: everyWindowStub,
@ -163,9 +165,6 @@ describe("ToolbarPanelHub", () => {
getEarliestRecordedDate: getEarliestRecordedDateStub,
getEventsByDateRange: getEventsByDateRangeStub,
},
SpecialMessageActions: {
handleAction: sandbox.stub(),
},
});
});
afterEach(() => {
@ -355,6 +354,7 @@ describe("ToolbarPanelHub", () => {
instance.init(waitForInitializedStub, {
getMessages: getMessagesStub,
dispatch: fakeDispatch,
handleUserAction: handleUserActionStub,
});
});
it("should have correct state", async () => {
@ -431,7 +431,7 @@ describe("ToolbarPanelHub", () => {
}
// Call the click handler to make coverage happy.
eventListeners.mouseup();
assert.calledOnce(global.SpecialMessageActions.handleAction);
assert.calledOnce(handleUserActionStub);
});
it("should clear previous messages on 2nd renderMessages()", async () => {
const messages = (await PanelTestProvider.getMessages()).filter(
@ -549,12 +549,12 @@ describe("ToolbarPanelHub", () => {
const buttonEl = createdElements.find(el => el.tagName === "button");
const anchorEl = createdElements.find(el => el.tagName === "a");
assert.notCalled(global.SpecialMessageActions.handleAction);
assert.notCalled(handleUserActionStub);
buttonEl.doCommand();
anchorEl.doCommand();
assert.calledTwice(global.SpecialMessageActions.handleAction);
assert.calledTwice(handleUserActionStub);
});
it("should listen for panelhidden and remove the toolbar button", async () => {
getMessagesStub.returns([]);
@ -783,6 +783,7 @@ describe("ToolbarPanelHub", () => {
await instance.init(waitForInitializedStub, {
dispatch: fakeDispatch,
getMessages: getMessagesStub,
handleUserAction: handleUserActionStub,
});
});
it("should remember it showed", async () => {
@ -828,18 +829,17 @@ describe("ToolbarPanelHub", () => {
eventListeners.mouseup();
assert.calledOnce(global.SpecialMessageActions.handleAction);
assert.calledWithExactly(
global.SpecialMessageActions.handleAction,
{
assert.calledOnce(handleUserActionStub);
assert.calledWithExactly(handleUserActionStub, {
target: fakeWindow,
data: {
type: "OPEN_URL",
data: {
args: sinon.match.string,
where: "tabshifted",
},
},
fakeWindow.browser
);
});
});
it("should format the url", async () => {
const stub = sandbox
@ -854,18 +854,17 @@ describe("ToolbarPanelHub", () => {
assert.calledOnce(stub);
assert.calledWithExactly(stub, msg.content.cta_url);
assert.calledOnce(global.SpecialMessageActions.handleAction);
assert.calledWithExactly(
global.SpecialMessageActions.handleAction,
{
assert.calledOnce(handleUserActionStub);
assert.calledWithExactly(handleUserActionStub, {
target: fakeWindow,
data: {
type: "OPEN_URL",
data: {
args: "formattedURL",
where: "tabshifted",
},
},
fakeWindow.browser
);
});
});
it("should report format url errors", async () => {
const stub = sandbox
@ -881,18 +880,17 @@ describe("ToolbarPanelHub", () => {
assert.calledOnce(stub);
assert.calledOnce(global.Cu.reportError);
assert.calledOnce(global.SpecialMessageActions.handleAction);
assert.calledWithExactly(
global.SpecialMessageActions.handleAction,
{
assert.calledOnce(handleUserActionStub);
assert.calledWithExactly(handleUserActionStub, {
target: fakeWindow,
data: {
type: "OPEN_URL",
data: {
args: msg.content.cta_url,
where: "tabshifted",
},
},
fakeWindow.browser
);
});
});
it("should open link on click (directly attached to the message)", async () => {
const onboardingMsgs = await OnboardingMessageProvider.getUntranslatedMessages();
@ -905,26 +903,25 @@ describe("ToolbarPanelHub", () => {
eventListeners.mouseup();
assert.calledOnce(global.SpecialMessageActions.handleAction);
assert.calledWithExactly(
global.SpecialMessageActions.handleAction,
{
assert.calledOnce(handleUserActionStub);
assert.calledWithExactly(handleUserActionStub, {
target: fakeWindow,
data: {
type: "OPEN_URL",
data: {
args: sinon.match.string,
where: "tabshifted",
},
},
fakeWindow.browser
);
});
});
it("should handle user actions from mouseup and keyup", async () => {
it("should handleUserAction from mouseup and keyup", async () => {
await fakeInsert();
eventListeners.mouseup();
eventListeners.keyup({ key: "Enter" });
eventListeners.keyup({ key: " " });
assert.calledThrice(global.SpecialMessageActions.handleAction);
assert.calledThrice(handleUserActionStub);
});
});
});

Просмотреть файл

@ -18,11 +18,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
});
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
@ -147,8 +142,8 @@ const SpecialMessageActions = {
);
break;
case "PIN_CURRENT_TAB":
let tab = window.gBrowser.selectedTab;
window.gBrowser.pinTab(tab);
let tab = browser.selectedTab;
browser.pinTab(tab);
window.ConfirmationHint.show(tab, "pinTab", {
showDescription: true,
});
@ -176,17 +171,6 @@ const SpecialMessageActions = {
case "OPEN_AWESOME_BAR":
window.gURLBar.search("");
break;
case "DISABLE_STP_DOORHANGERS":
await this.blockMessageById([
"SOCIAL_TRACKING_PROTECTION",
"FINGERPRINTERS_PROTECTION",
"CRYPTOMINERS_PROTECTION",
]);
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;
default:
throw new Error(
`Special message action with type ${action.type} is unsupported.`

Просмотреть файл

@ -233,14 +233,4 @@ const SpecialMessageActionSchemas = {
},
type: "object",
},
CANCEL: {
description: "Cancel (dismiss) the CFR doorhanger.",
properties: {
type: {
enum: ["CANCEL"],
type: "string",
},
},
type: "object",
},
};

Просмотреть файл

@ -1,14 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
add_task(async function test_cancel_event() {
let error = null;
try {
await SMATestUtils.executeAndValidateAction({ type: "CANCEL" });
} catch (e) {
error = e;
}
ok(!error, "should not throw for CANCEL");
});