1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 // This file is accessed from both content and system scopes.
7 export const MAIN_MESSAGE_TYPE = "ActivityStream:Main";
8 export const CONTENT_MESSAGE_TYPE = "ActivityStream:Content";
9 export const PRELOAD_MESSAGE_TYPE = "ActivityStream:PreloadedBrowser";
10 export const UI_CODE = 1;
11 export const BACKGROUND_PROCESS = 2;
14 * globalImportContext - Are we in UI code (i.e. react, a dom) or some kind of background process?
15 * Use this in action creators if you need different logic
16 * for ui/background processes.
18 export const globalImportContext =
19 typeof Window === "undefined" ? BACKGROUND_PROCESS : UI_CODE;
21 // Create an object that avoids accidental differing key/value pairs:
26 export const actionTypes = {};
29 "ABOUT_SPONSORED_TOP_SITES",
30 "ADDONS_INFO_REQUEST",
31 "ADDONS_INFO_RESPONSE",
32 "ARCHIVE_FROM_POCKET",
33 "AS_ROUTER_INITIALIZED",
34 "AS_ROUTER_PREF_CHANGED",
35 "AS_ROUTER_TARGETING_UPDATE",
36 "AS_ROUTER_TELEMETRY_USER_EVENT",
41 "DELETE_BOOKMARK_BY_ID",
47 "DISCOVERY_STREAM_COLLECTION_DISMISSIBLE_TOGGLE",
48 "DISCOVERY_STREAM_CONFIG_CHANGE",
49 "DISCOVERY_STREAM_CONFIG_RESET",
50 "DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS",
51 "DISCOVERY_STREAM_CONFIG_SETUP",
52 "DISCOVERY_STREAM_CONFIG_SET_VALUE",
53 "DISCOVERY_STREAM_DEV_EXPIRE_CACHE",
54 "DISCOVERY_STREAM_DEV_IDLE_DAILY",
55 "DISCOVERY_STREAM_DEV_SYNC_RS",
56 "DISCOVERY_STREAM_DEV_SYSTEM_TICK",
57 "DISCOVERY_STREAM_EXPERIMENT_DATA",
58 "DISCOVERY_STREAM_FEEDS_UPDATE",
59 "DISCOVERY_STREAM_FEED_UPDATE",
60 "DISCOVERY_STREAM_IMPRESSION_STATS",
61 "DISCOVERY_STREAM_LAYOUT_RESET",
62 "DISCOVERY_STREAM_LAYOUT_UPDATE",
63 "DISCOVERY_STREAM_LINK_BLOCKED",
64 "DISCOVERY_STREAM_LOADED_CONTENT",
65 "DISCOVERY_STREAM_PERSONALIZATION_INIT",
66 "DISCOVERY_STREAM_PERSONALIZATION_LAST_UPDATED",
67 "DISCOVERY_STREAM_PERSONALIZATION_OVERRIDE",
68 "DISCOVERY_STREAM_PERSONALIZATION_RESET",
69 "DISCOVERY_STREAM_PERSONALIZATION_TOGGLE",
70 "DISCOVERY_STREAM_PERSONALIZATION_UPDATED",
71 "DISCOVERY_STREAM_POCKET_STATE_INIT",
72 "DISCOVERY_STREAM_POCKET_STATE_SET",
73 "DISCOVERY_STREAM_PREFS_SETUP",
74 "DISCOVERY_STREAM_RECENT_SAVES",
75 "DISCOVERY_STREAM_RETRY_FEED",
76 "DISCOVERY_STREAM_SPOCS_CAPS",
77 "DISCOVERY_STREAM_SPOCS_ENDPOINT",
78 "DISCOVERY_STREAM_SPOCS_PLACEMENTS",
79 "DISCOVERY_STREAM_SPOCS_UPDATE",
80 "DISCOVERY_STREAM_SPOC_BLOCKED",
81 "DISCOVERY_STREAM_SPOC_IMPRESSION",
82 "DISCOVERY_STREAM_USER_EVENT",
86 "HANDOFF_SEARCH_TO_AWESOMEBAR",
91 "NEW_TAB_INITIAL_STATE",
94 "NEW_TAB_STATE_REQUEST",
99 "OPEN_PRIVATE_WINDOW",
100 "OPEN_WEBEXT_SETTINGS",
101 "PARTNER_LINK_ATTRIBUTION",
102 "PLACES_BOOKMARKS_REMOVED",
103 "PLACES_BOOKMARK_ADDED",
104 "PLACES_HISTORY_CLEARED",
105 "PLACES_LINKS_CHANGED",
106 "PLACES_LINKS_DELETED",
107 "PLACES_LINK_BLOCKED",
108 "PLACES_SAVED_TO_POCKET",
110 "POCKET_LINK_DELETED_OR_ARCHIVED",
112 "POCKET_WAITING_FOR_SPOC",
113 "PREFS_INITIAL_VALUES",
116 "PREVIEW_REQUEST_CANCEL",
118 "REMOVE_DOWNLOAD_FILE",
120 "SAVE_SESSION_PERF_DATA",
122 "SCREENSHOT_UPDATED",
123 "SECTION_DEREGISTER",
127 "SECTION_OPTIONS_CHANGED",
130 "SECTION_UPDATE_CARD",
134 "SHOW_DOWNLOAD_FILE",
135 "SHOW_FIREFOX_ACCOUNTS",
144 "TELEMETRY_IMPRESSION_STATS",
145 "TELEMETRY_USER_EVENT",
146 "TOP_SITES_CANCEL_EDIT",
147 "TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL",
150 "TOP_SITES_OPEN_SEARCH_SHORTCUTS_MODAL",
151 "TOP_SITES_ORGANIC_IMPRESSION_STATS",
153 "TOP_SITES_PREFS_UPDATED",
154 "TOP_SITES_SPONSORED_IMPRESSION_STATS",
157 "TOTAL_BOOKMARKS_REQUEST",
158 "TOTAL_BOOKMARKS_RESPONSE",
160 "UPDATE_PINNED_SEARCH_SHORTCUTS",
161 "UPDATE_SEARCH_SHORTCUTS",
162 "UPDATE_SECTION_PREFS",
167 actionTypes[type] = type;
170 // Helper function for creating routed actions between content and main
171 // Not intended to be used by consumers
172 function _RouteMessage(action, options) {
173 const meta = action.meta ? { ...action.meta } : {};
174 if (!options || !options.from || !options.to) {
176 "Routed Messages must have options as the second parameter, and must at least include a .from and .to property."
179 // For each of these fields, if they are passed as an option,
180 // add them to the action. If they are not defined, remove them.
181 ["from", "to", "toTarget", "fromTarget", "skipMain", "skipLocal"].forEach(
183 if (typeof options[o] !== "undefined") {
184 meta[o] = options[o];
185 } else if (meta[o]) {
190 return { ...action, meta };
194 * AlsoToMain - Creates a message that will be dispatched locally and also sent to the Main process.
196 * @param {object} action Any redux action (required)
197 * @param {object} options
198 * @param {bool} skipLocal Used by OnlyToMain to skip the main reducer
199 * @param {string} fromTarget The id of the content port from which the action originated. (optional)
200 * @return {object} An action with added .meta properties
202 function AlsoToMain(action, fromTarget, skipLocal) {
203 return _RouteMessage(action, {
204 from: CONTENT_MESSAGE_TYPE,
205 to: MAIN_MESSAGE_TYPE,
212 * OnlyToMain - Creates a message that will be sent to the Main process and skip the local reducer.
214 * @param {object} action Any redux action (required)
215 * @param {object} options
216 * @param {string} fromTarget The id of the content port from which the action originated. (optional)
217 * @return {object} An action with added .meta properties
219 function OnlyToMain(action, fromTarget) {
220 return AlsoToMain(action, fromTarget, true);
224 * BroadcastToContent - Creates a message that will be dispatched to main and sent to ALL content processes.
226 * @param {object} action Any redux action (required)
227 * @return {object} An action with added .meta properties
229 function BroadcastToContent(action) {
230 return _RouteMessage(action, {
231 from: MAIN_MESSAGE_TYPE,
232 to: CONTENT_MESSAGE_TYPE,
237 * AlsoToOneContent - Creates a message that will be will be dispatched to the main store
238 * and also sent to a particular Content process.
240 * @param {object} action Any redux action (required)
241 * @param {string} target The id of a content port
242 * @param {bool} skipMain Used by OnlyToOneContent to skip the main process
243 * @return {object} An action with added .meta properties
245 function AlsoToOneContent(action, target, skipMain) {
248 "You must provide a target ID as the second parameter of AlsoToOneContent. If you want to send to all content processes, use BroadcastToContent"
251 return _RouteMessage(action, {
252 from: MAIN_MESSAGE_TYPE,
253 to: CONTENT_MESSAGE_TYPE,
260 * OnlyToOneContent - Creates a message that will be sent to a particular Content process
261 * and skip the main reducer.
263 * @param {object} action Any redux action (required)
264 * @param {string} target The id of a content port
265 * @return {object} An action with added .meta properties
267 function OnlyToOneContent(action, target) {
268 return AlsoToOneContent(action, target, true);
272 * AlsoToPreloaded - Creates a message that dispatched to the main reducer and also sent to the preloaded tab.
274 * @param {object} action Any redux action (required)
275 * @return {object} An action with added .meta properties
277 function AlsoToPreloaded(action) {
278 return _RouteMessage(action, {
279 from: MAIN_MESSAGE_TYPE,
280 to: PRELOAD_MESSAGE_TYPE,
285 * UserEvent - A telemetry ping indicating a user action. This should only
286 * be sent from the UI during a user session.
288 * @param {object} data Fields to include in the ping (source, etc.)
289 * @return {object} An AlsoToMain action
291 function UserEvent(data) {
293 type: actionTypes.TELEMETRY_USER_EVENT,
299 * DiscoveryStreamUserEvent - A telemetry ping indicating a user action from Discovery Stream. This should only
300 * be sent from the UI during a user session.
302 * @param {object} data Fields to include in the ping (source, etc.)
303 * @return {object} An AlsoToMain action
305 function DiscoveryStreamUserEvent(data) {
307 type: actionTypes.DISCOVERY_STREAM_USER_EVENT,
313 * ASRouterUserEvent - A telemetry ping indicating a user action from AS router. This should only
314 * be sent from the UI during a user session.
316 * @param {object} data Fields to include in the ping (source, etc.)
317 * @return {object} An AlsoToMain action
319 function ASRouterUserEvent(data) {
321 type: actionTypes.AS_ROUTER_TELEMETRY_USER_EVENT,
327 * ImpressionStats - A telemetry ping indicating an impression stats.
329 * @param {object} data Fields to include in the ping
330 * @param {int} importContext (For testing) Override the import context for testing.
331 * #return {object} An action. For UI code, a AlsoToMain action.
333 function ImpressionStats(data, importContext = globalImportContext) {
335 type: actionTypes.TELEMETRY_IMPRESSION_STATS,
338 return importContext === UI_CODE ? AlsoToMain(action) : action;
342 * DiscoveryStreamImpressionStats - A telemetry ping indicating an impression stats in Discovery Stream.
344 * @param {object} data Fields to include in the ping
345 * @param {int} importContext (For testing) Override the import context for testing.
346 * #return {object} An action. For UI code, a AlsoToMain action.
348 function DiscoveryStreamImpressionStats(
350 importContext = globalImportContext
353 type: actionTypes.DISCOVERY_STREAM_IMPRESSION_STATS,
356 return importContext === UI_CODE ? AlsoToMain(action) : action;
360 * DiscoveryStreamLoadedContent - A telemetry ping indicating a content gets loaded in Discovery Stream.
362 * @param {object} data Fields to include in the ping
363 * @param {int} importContext (For testing) Override the import context for testing.
364 * #return {object} An action. For UI code, a AlsoToMain action.
366 function DiscoveryStreamLoadedContent(
368 importContext = globalImportContext
371 type: actionTypes.DISCOVERY_STREAM_LOADED_CONTENT,
374 return importContext === UI_CODE ? AlsoToMain(action) : action;
377 function SetPref(prefName, value, importContext = globalImportContext) {
379 type: actionTypes.SET_PREF,
380 data: { name: prefName, value },
382 return importContext === UI_CODE ? AlsoToMain(action) : action;
385 function WebExtEvent(type, data, importContext = globalImportContext) {
386 if (!data || !data.source) {
388 'WebExtEvent actions should include a property "source", the id of the webextension that should receive the event.'
391 const action = { type, data };
392 return importContext === UI_CODE ? AlsoToMain(action) : action;
395 export const actionCreators = {
398 DiscoveryStreamUserEvent,
408 DiscoveryStreamImpressionStats,
409 DiscoveryStreamLoadedContent,
412 // These are helpers to test for certain kinds of actions
413 export const actionUtils = {
414 isSendToMain(action) {
419 action.meta.to === MAIN_MESSAGE_TYPE &&
420 action.meta.from === CONTENT_MESSAGE_TYPE
423 isBroadcastToContent(action) {
427 if (action.meta.to === CONTENT_MESSAGE_TYPE && !action.meta.toTarget) {
432 isSendToOneContent(action) {
436 if (action.meta.to === CONTENT_MESSAGE_TYPE && action.meta.toTarget) {
441 isSendToPreloaded(action) {
446 action.meta.to === PRELOAD_MESSAGE_TYPE &&
447 action.meta.from === MAIN_MESSAGE_TYPE
455 action.meta.from === MAIN_MESSAGE_TYPE &&
456 action.meta.to === CONTENT_MESSAGE_TYPE
459 getPortIdOfSender(action) {
460 return (action.meta && action.meta.fromTarget) || null;