Bug 1548520 - Add user telemetry for Bookmark Panel messages r=nanj

Differential Revision: https://phabricator.services.mozilla.com/D30176

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andrei Oprea 2019-05-08 15:46:42 +00:00
Родитель fabb0dc4d5
Коммит 0380dc1228
2 изменённых файлов: 49 добавлений и 20 удалений

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

@ -9,6 +9,8 @@ ChromeUtils.defineModuleGetter(this, "FxAccounts",
"resource://gre/modules/FxAccounts.jsm"); "resource://gre/modules/FxAccounts.jsm");
ChromeUtils.defineModuleGetter(this, "Services", ChromeUtils.defineModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm"); "resource://gre/modules/Services.jsm");
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
class _BookmarkPanelHub { class _BookmarkPanelHub {
constructor() { constructor() {
@ -62,7 +64,7 @@ class _BookmarkPanelHub {
* @returns {obj|null} response object or null if no messages matched * @returns {obj|null} response object or null if no messages matched
*/ */
async messageRequest(target, win) { async messageRequest(target, win) {
if (this._response && this._response.url === target.url && this._response.content) { if (this._response && this._response.win === win && this._response.url === target.url && this._response.content) {
this.showMessage(this._response.content, target, win); this.showMessage(this._response.content, target, win);
return true; return true;
} }
@ -88,7 +90,7 @@ class _BookmarkPanelHub {
if (response && response.content) { if (response && response.content) {
this.showMessage(response.content, target, win); this.showMessage(response.content, target, win);
this.sendImpression(); this.sendImpression();
this.sendUserEventTelemetry("IMPRESSION"); this.sendUserEventTelemetry("IMPRESSION", win);
} else { } else {
this.hideMessage(target); this.hideMessage(target);
} }
@ -117,7 +119,7 @@ class _BookmarkPanelHub {
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({}), triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({}),
csp: null, csp: null,
}); });
this.sendUserEventTelemetry("CLICK"); this.sendUserEventTelemetry("CLICK", win);
}); });
recommendation.style.color = message.color; recommendation.style.color = message.color;
recommendation.style.background = `-moz-linear-gradient(-45deg, ${message.background_color_1} 0%, ${message.background_color_2} 70%)`; recommendation.style.background = `-moz-linear-gradient(-45deg, ${message.background_color_1} 0%, ${message.background_color_2} 70%)`;
@ -126,7 +128,7 @@ class _BookmarkPanelHub {
close.setAttribute("aria-label", "close"); close.setAttribute("aria-label", "close");
this._l10n.setAttributes(close, message.close_button.tooltiptext); this._l10n.setAttributes(close, message.close_button.tooltiptext);
close.addEventListener("click", e => { close.addEventListener("click", e => {
this.sendUserEventTelemetry("DISMISS"); this.sendUserEventTelemetry("DISMISS", win);
this.collapseMessage(); this.collapseMessage();
target.close(e); target.close(e);
}); });
@ -190,9 +192,12 @@ class _BookmarkPanelHub {
this._addImpression(this._response); this._addImpression(this._response);
} }
sendUserEventTelemetry(event) { sendUserEventTelemetry(event, win) {
// Only send pings for non private browsing windows
if (!PrivateBrowsingUtils.isBrowserPrivate(win.ownerGlobal.gBrowser.selectedBrowser)) {
this._sendTelemetry({message_id: this._response.id, bucket_id: this._response.id, event}); this._sendTelemetry({message_id: this._response.id, bucket_id: this._response.id, event});
} }
}
_sendTelemetry(ping) { _sendTelemetry(ping) {
this._dispatch({ this._dispatch({

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

@ -12,6 +12,8 @@ describe("BookmarkPanelHub", () => {
let fakeTarget; let fakeTarget;
let fakeContainer; let fakeContainer;
let fakeDispatch; let fakeDispatch;
let fakeWindow;
let isBrowserPrivateStub;
beforeEach(() => { beforeEach(() => {
sandbox = sinon.createSandbox(); sandbox = sinon.createSandbox();
globals = new GlobalOverrider(); globals = new GlobalOverrider();
@ -19,6 +21,8 @@ describe("BookmarkPanelHub", () => {
fakeL10n = {setAttributes: sandbox.stub(), translateElements: sandbox.stub()}; fakeL10n = {setAttributes: sandbox.stub(), translateElements: sandbox.stub()};
globals.set("DOMLocalization", function() { return fakeL10n; }); // eslint-disable-line prefer-arrow-callback globals.set("DOMLocalization", function() { return fakeL10n; }); // eslint-disable-line prefer-arrow-callback
globals.set("FxAccounts", {config: {promiseEmailFirstURI: sandbox.stub()}}); globals.set("FxAccounts", {config: {promiseEmailFirstURI: sandbox.stub()}});
isBrowserPrivateStub = sandbox.stub().returns(false);
globals.set("PrivateBrowsingUtils", {isBrowserPrivate: isBrowserPrivateStub});
instance = new _BookmarkPanelHub(); instance = new _BookmarkPanelHub();
fakeAddImpression = sandbox.stub(); fakeAddImpression = sandbox.stub();
@ -57,6 +61,7 @@ describe("BookmarkPanelHub", () => {
close: sandbox.stub(), close: sandbox.stub(),
}; };
fakeDispatch = sandbox.stub(); fakeDispatch = sandbox.stub();
fakeWindow = {ownerGlobal: {openLinkIn: sandbox.stub(), gBrowser: {selectedBrowser: "browser"}}};
}); });
afterEach(() => { afterEach(() => {
instance.uninit(); instance.uninit();
@ -126,19 +131,19 @@ describe("BookmarkPanelHub", () => {
fakeTarget = {infoButton: {disabled: true}}; fakeTarget = {infoButton: {disabled: true}};
}); });
it("should show a message when called with a response", () => { it("should show a message when called with a response", () => {
instance.onResponse({content: "content"}, fakeTarget, {}); instance.onResponse({content: "content"}, fakeTarget, fakeWindow);
assert.calledOnce(instance.showMessage); assert.calledOnce(instance.showMessage);
assert.calledWithExactly(instance.showMessage, "content", fakeTarget, {}); assert.calledWithExactly(instance.showMessage, "content", fakeTarget, fakeWindow);
assert.calledOnce(instance.sendImpression); assert.calledOnce(instance.sendImpression);
}); });
it("should dispatch a user impression", () => { it("should dispatch a user impression", () => {
sandbox.spy(instance, "sendUserEventTelemetry"); sandbox.spy(instance, "sendUserEventTelemetry");
instance.onResponse({content: "content"}, fakeTarget, {}); instance.onResponse({content: "content"}, fakeTarget, fakeWindow);
assert.calledOnce(instance.sendUserEventTelemetry); assert.calledOnce(instance.sendUserEventTelemetry);
assert.calledWithExactly(instance.sendUserEventTelemetry, "IMPRESSION"); assert.calledWithExactly(instance.sendUserEventTelemetry, "IMPRESSION", fakeWindow);
assert.calledOnce(fakeDispatch); assert.calledOnce(fakeDispatch);
const [ping] = fakeDispatch.firstCall.args; const [ping] = fakeDispatch.firstCall.args;
@ -146,6 +151,16 @@ describe("BookmarkPanelHub", () => {
assert.equal(ping.type, "DOORHANGER_TELEMETRY"); assert.equal(ping.type, "DOORHANGER_TELEMETRY");
assert.equal(ping.data.event, "IMPRESSION"); assert.equal(ping.data.event, "IMPRESSION");
}); });
it("should not dispatch a user impression if the window is private", () => {
isBrowserPrivateStub.returns(true);
sandbox.spy(instance, "sendUserEventTelemetry");
instance.onResponse({content: "content"}, fakeTarget, fakeWindow);
assert.calledOnce(instance.sendUserEventTelemetry);
assert.calledWithExactly(instance.sendUserEventTelemetry, "IMPRESSION", fakeWindow);
assert.notCalled(fakeDispatch);
});
it("should hide existing messages if no response is provided", () => { it("should hide existing messages if no response is provided", () => {
instance.onResponse(null, fakeTarget); instance.onResponse(null, fakeTarget);
@ -175,33 +190,42 @@ describe("BookmarkPanelHub", () => {
assert.notCalled(fakeTarget.container.appendChild); assert.notCalled(fakeTarget.container.appendChild);
}); });
it("should open a tab with FxA signup", async () => { it("should open a tab with FxA signup", async () => {
const windowStub = {ownerGlobal: {openLinkIn: sandbox.stub()}};
fakeTarget.container.querySelector.returns(false); fakeTarget.container.querySelector.returns(false);
instance.showMessage(fakeMessage, fakeTarget, windowStub); instance.showMessage(fakeMessage, fakeTarget, fakeWindow);
// Call the event listener cb // Call the event listener cb
await fakeContainer.addEventListener.firstCall.args[1](); await fakeContainer.addEventListener.firstCall.args[1]();
assert.calledOnce(windowStub.ownerGlobal.openLinkIn); assert.calledOnce(fakeWindow.ownerGlobal.openLinkIn);
}); });
it("should send a click event", async () => { it("should send a click event", async () => {
const windowStub = {ownerGlobal: {openLinkIn: sandbox.stub()}};
sandbox.stub(instance, "sendUserEventTelemetry"); sandbox.stub(instance, "sendUserEventTelemetry");
fakeTarget.container.querySelector.returns(false); fakeTarget.container.querySelector.returns(false);
instance.showMessage(fakeMessage, fakeTarget, windowStub); instance.showMessage(fakeMessage, fakeTarget, fakeWindow);
// Call the event listener cb // Call the event listener cb
await fakeContainer.addEventListener.firstCall.args[1](); await fakeContainer.addEventListener.firstCall.args[1]();
assert.calledOnce(instance.sendUserEventTelemetry); assert.calledOnce(instance.sendUserEventTelemetry);
assert.calledWithExactly(instance.sendUserEventTelemetry, "CLICK"); assert.calledWithExactly(instance.sendUserEventTelemetry, "CLICK", fakeWindow);
});
it("should send a click event", async () => {
sandbox.stub(instance, "sendUserEventTelemetry");
fakeTarget.container.querySelector.returns(false);
instance.showMessage(fakeMessage, fakeTarget, fakeWindow);
// Call the event listener cb
await fakeContainer.addEventListener.firstCall.args[1]();
assert.calledOnce(instance.sendUserEventTelemetry);
assert.calledWithExactly(instance.sendUserEventTelemetry, "CLICK", fakeWindow);
}); });
it("should collapse the message", () => { it("should collapse the message", () => {
fakeTarget.container.querySelector.returns(false); fakeTarget.container.querySelector.returns(false);
sandbox.spy(instance, "collapseMessage"); sandbox.spy(instance, "collapseMessage");
instance._response.collapsed = false; instance._response.collapsed = false;
instance.showMessage(fakeMessage, fakeTarget); instance.showMessage(fakeMessage, fakeTarget, fakeWindow);
// Show message calls it once so we need to reset // Show message calls it once so we need to reset
instance.toggleRecommendation.reset(); instance.toggleRecommendation.reset();
// Call the event listener cb // Call the event listener cb
@ -217,15 +241,15 @@ describe("BookmarkPanelHub", () => {
sandbox.spy(instance, "collapseMessage"); sandbox.spy(instance, "collapseMessage");
instance._response.collapsed = false; instance._response.collapsed = false;
instance.showMessage(fakeMessage, fakeTarget); instance.showMessage(fakeMessage, fakeTarget, fakeWindow);
// Call the event listener cb // Call the event listener cb
fakeContainer.addEventListener.secondCall.args[1](); fakeContainer.addEventListener.secondCall.args[1]();
assert.calledOnce(instance.sendUserEventTelemetry); assert.calledOnce(instance.sendUserEventTelemetry);
assert.calledWithExactly(instance.sendUserEventTelemetry, "DISMISS"); assert.calledWithExactly(instance.sendUserEventTelemetry, "DISMISS", fakeWindow);
}); });
it("should call toggleRecommendation `true`", () => { it("should call toggleRecommendation `true`", () => {
instance.showMessage(fakeMessage, fakeTarget); instance.showMessage(fakeMessage, fakeTarget, fakeWindow);
assert.calledOnce(instance.toggleRecommendation); assert.calledOnce(instance.toggleRecommendation);
assert.calledWithExactly(instance.toggleRecommendation, true); assert.calledWithExactly(instance.toggleRecommendation, true);