Backed out changeset 496886cb30a5 (bug 1867152) for bc failures on browser_user_input...
[gecko.git] / browser / modules / PartnerLinkAttribution.sys.mjs
blob019341c7dbbf63d17a61b5b9c639432aa4e765ee
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 const lazy = {};
7 ChromeUtils.defineESModuleGetters(lazy, {
8   Region: "resource://gre/modules/Region.sys.mjs",
9 });
11 export const CONTEXTUAL_SERVICES_PING_TYPES = {
12   TOPSITES_IMPRESSION: "topsites-impression",
13   TOPSITES_SELECTION: "topsites-click",
14   QS_BLOCK: "quicksuggest-block",
15   QS_IMPRESSION: "quicksuggest-impression",
16   QS_SELECTION: "quicksuggest-click",
19 export var PartnerLinkAttribution = {
20   /**
21    * Sends an attribution request to an anonymizing proxy.
22    *
23    * @param {string} targetURL
24    *   The URL we are routing through the anonmyzing proxy.
25    * @param {string} source
26    *   The source of the anonmized request, e.g. "urlbar".
27    * @param {string} [campaignID]
28    *   The campaign ID for attribution. This should be a valid path on the
29    *   anonymizing proxy. For example, if `campaignID` was `foo`, we'd send an
30    *   attribution request to https://topsites.mozilla.com/cid/foo.
31    *   Optional. If it's not provided, we default to the topsites campaign.
32    */
33   async makeRequest({ targetURL, source, campaignID }) {
34     let partner = targetURL.match(/^https?:\/\/(?:www.)?([^.]*)/)[1];
36     function record(method, objectString) {
37       recordTelemetryEvent({
38         method,
39         objectString,
40         value: partner,
41       });
42     }
43     record("click", source);
45     let attributionUrl = Services.prefs.getStringPref(
46       "browser.partnerlink.attributionURL"
47     );
48     if (!attributionUrl) {
49       record("attribution", "abort");
50       return;
51     }
53     // The default campaign is topsites.
54     if (!campaignID) {
55       campaignID = Services.prefs.getStringPref(
56         "browser.partnerlink.campaign.topsites"
57       );
58     }
59     attributionUrl = attributionUrl + campaignID;
60     let result = await sendRequest(attributionUrl, source, targetURL);
61     record("attribution", result ? "success" : "failure");
62   },
64   /**
65    * Makes a request to the attribution URL for a search engine search.
66    *
67    * @param {nsISearchEngine} engine
68    *   The search engine to save the attribution for.
69    * @param {nsIURI} targetUrl
70    *   The target URL to filter and include in the attribution.
71    */
72   async makeSearchEngineRequest(engine, targetUrl) {
73     let cid;
74     if (engine.attribution?.cid) {
75       cid = engine.attribution.cid;
76     } else if (engine.sendAttributionRequest) {
77       cid = Services.prefs.getStringPref(
78         "browser.partnerlink.campaign.topsites"
79       );
80     } else {
81       return;
82     }
84     let searchUrlQueryParamName = engine.searchUrlQueryParamName;
85     if (!searchUrlQueryParamName) {
86       console.error("makeSearchEngineRequest can't find search terms key");
87       return;
88     }
90     let url = targetUrl;
91     if (typeof url == "string") {
92       url = Services.io.newURI(url);
93     }
95     let targetParams = new URLSearchParams(url.query);
96     if (!targetParams.has(searchUrlQueryParamName)) {
97       console.error("makeSearchEngineRequest can't remove target search terms");
98       return;
99     }
101     let attributionUrl = Services.prefs.getStringPref(
102       "browser.partnerlink.attributionURL",
103       ""
104     );
105     attributionUrl = attributionUrl + cid;
107     targetParams.delete(searchUrlQueryParamName);
108     let strippedTargetUrl = `${url.prePath}${url.filePath}`;
109     let newParams = targetParams.toString();
110     if (newParams) {
111       strippedTargetUrl += "?" + newParams;
112     }
114     await sendRequest(attributionUrl, "searchurl", strippedTargetUrl);
115   },
118 async function sendRequest(attributionUrl, source, targetURL) {
119   const request = new Request(attributionUrl);
120   request.headers.set("X-Region", lazy.Region.home);
121   request.headers.set("X-Source", source);
122   request.headers.set("X-Target-URL", targetURL);
123   const response = await fetch(request);
124   return response.ok;
127 function recordTelemetryEvent({ method, objectString, value }) {
128   Services.telemetry.setEventRecordingEnabled("partner_link", true);
129   Services.telemetry.recordEvent("partner_link", method, objectString, value);