Source code

Revision control

Copy as Markdown

Other Tools

/* 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 https://mozilla.org/MPL/2.0/. */
import {
actionTypes as at,
actionCreators as ac,
export class NewTabMessaging {
constructor() {
this.initialized = false;
this.ASRouterDispatch = null;
}
init() {
if (!this.initialized) {
Services.obs.addObserver(this, "newtab-message");
this.initialized = true;
}
}
uninit() {
Services.obs.removeObserver(this, "newtab-message");
}
observe(subject, topic, _data) {
if (topic === "newtab-message") {
let { targetBrowser, message, dispatch } = subject.wrappedJSObject;
this.ASRouterDispatch = dispatch;
this.showMessage(targetBrowser, message);
}
}
async showMessage(targetBrowser, message) {
if (targetBrowser) {
let actor =
targetBrowser.browsingContext.currentWindowGlobal.getActor(
"AboutNewTab"
);
if (actor) {
let tabDetails = actor.getTabDetails();
if (tabDetails) {
// Only send the message for the tab that triggered the message
this.store.dispatch(
ac.OnlyToOneContent(
{
type: at.MESSAGE_SET,
// send along portID as well so that the child process can easily just update the single tab
data: {
message,
portID: tabDetails.portID,
},
},
tabDetails.portID
)
);
}
}
} else {
// if targetBrowser is null, send to the preloaded tab / main process
// This should only run if message is triggered from asrouter during dev
this.store.dispatch(
ac.AlsoToPreloaded({
type: at.MESSAGE_SET,
data: {
message,
},
})
);
// Also force visibility for messages sent from about:asrouter during dev
this.store.dispatch(
ac.AlsoToPreloaded({
type: at.MESSAGE_TOGGLE_VISIBILITY,
data: false,
})
);
}
}
/**
*
* @param {string} id ID of message to be blocked
*/
blockMessage(id) {
if (id) {
this.ASRouterDispatch?.({
type: "BLOCK_MESSAGE_BY_ID",
data: {
id,
},
});
}
}
/**
* Send impression to ASRouter
* @param {Object} message
*/
handleImpression(message) {
this.sendTelemetry("IMPRESSION", message);
this.ASRouterDispatch?.({
type: "IMPRESSION",
data: message,
});
}
/**
* Sends telemetry data through ASRouter to
* match pattern with ASRouterTelemetry
*/
sendTelemetry(event, message, source = "newtab") {
const data = {
action: "newtab_message_user_event",
event,
event_context: { source, page: "about:newtab" },
message_id: message.id,
};
this.ASRouterDispatch?.({
type: "NEWTAB_MESSAGE_TELEMETRY",
data,
});
}
async onAction(action) {
switch (action.type) {
case at.INIT:
this.init();
break;
case at.UNINIT:
this.uninit();
break;
case at.MESSAGE_IMPRESSION:
this.handleImpression(action.data);
break;
case at.MESSAGE_DISMISS:
this.sendTelemetry("DISMISS", action.data.message);
break;
case at.MESSAGE_CLICK:
this.sendTelemetry("CLICK", action.data.message, action.data.source);
break;
case at.MESSAGE_BLOCK:
this.blockMessage(action.data);
break;
}
}
}