tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

cxense.js (16721B)


      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/. */
      4 
      5 "use strict";
      6 
      7 /**
      8 * Bug 1713721 - Shim Cxense
      9 *
     10 * Sites relying on window.cX can experience breakage if it is blocked.
     11 * Stubbing out the API in a shim can mitigate this breakage. There are
     12 * two versions of the API, one including window.cX.CCE, but both appear
     13 * to be very similar so we use one shim for both.
     14 */
     15 
     16 if (window.cX?.getUserSegmentIds === undefined) {
     17  const callQueue = window.cX?.callQueue || [];
     18  const callQueueCCE = window.cX?.CCE?.callQueue || [];
     19 
     20  function getRandomString(l = 16) {
     21    const v = crypto.getRandomValues(new Uint8Array(l));
     22    const s = Array.from(v, c => c.toString(16)).join("");
     23    return s.slice(0, l);
     24  }
     25 
     26  const call = (cb, ...args) => {
     27    if (typeof cb !== "function") {
     28      return;
     29    }
     30    try {
     31      cb(...args);
     32    } catch (e) {
     33      console.error(e);
     34    }
     35  };
     36 
     37  const invokeOn = lib => {
     38    return (fn, ...args) => {
     39      try {
     40        lib[fn](...args);
     41      } catch (e) {
     42        console.error(e);
     43      }
     44    };
     45  };
     46 
     47  const userId = getRandomString();
     48  const cxUserId = `cx:${getRandomString(25)}:${getRandomString(12)}`;
     49  const topLeft = { left: 0, top: 0 };
     50  const margins = { left: 0, top: 0, right: 0, bottom: 0 };
     51  const ccePushUrl =
     52    "https://comcluster.cxense.com/cce/push?callback={{callback}}";
     53  const displayWidget = (divId, a, ctx, callback) => call(callback, ctx, divId);
     54  const getUserSegmentIds = a => call(a?.callback, a?.defaultValue || []);
     55  const init = (a, b, c, d, callback) => call(callback);
     56  const render = (a, data, ctx, callback) => call(callback, data, ctx);
     57  const run = (params, ctx, callback) => call(callback, params, ctx);
     58  const runCtrlVersion = (a, b, callback) => call(callback);
     59  const runCxVersion = (a, data, b, ctx, callback) => call(callback, data, ctx);
     60  const runTest = (a, divId, b, c, ctx, callback) => call(callback, divId, ctx);
     61  const sendConversionEvent = (a, options) => call(options?.callback, {});
     62  const sendEvent = (a, b, args) => call(args?.callback, {});
     63 
     64  const getDivId = className => {
     65    const e = document.querySelector(`.${className}`);
     66    if (e) {
     67      return `${className}-01`;
     68    }
     69    return null;
     70  };
     71 
     72  const getDocumentSize = () => {
     73    const width = document.body.clientWidth;
     74    const height = document.body.clientHeight;
     75    return { width, height };
     76  };
     77 
     78  const getNowSeconds = () => {
     79    return Math.round(new Date().getTime() / 1000);
     80  };
     81 
     82  const getPageContext = () => {
     83    return {
     84      location: location.href,
     85      pageViewRandom: "",
     86      userId,
     87    };
     88  };
     89 
     90  const getWindowSize = () => {
     91    const width = window.innerWidth;
     92    const height = window.innerHeight;
     93    return { width, height };
     94  };
     95 
     96  const isObject = i => {
     97    return typeof i === "object" && i !== null && !Array.isArray(i);
     98  };
     99 
    100  const runMulti = widgets => {
    101    widgets?.forEach(({ widgetParams, widgetContext, widgetCallback }) => {
    102      call(widgetCallback, widgetParams, widgetContext);
    103    });
    104  };
    105 
    106  let testGroup = -1;
    107  let snapPoints = [];
    108  const startTime = new Date();
    109 
    110  const library = {
    111    addCustomerScript() {},
    112    addEventListener() {},
    113    addExternalId() {},
    114    afterInitializePage() {},
    115    allUserConsents() {},
    116    backends: {
    117      production: {
    118        baseAdDeliveryUrl: "http://adserver.cxad.cxense.com/adserver/search",
    119        secureBaseAdDeliveryUrl:
    120          "https://s-adserver.cxad.cxense.com/adserver/search",
    121      },
    122      sandbox: {
    123        baseAdDeliveryUrl:
    124          "http://adserver.sandbox.cxad.cxense.com/adserver/search",
    125        secureBaseAdDeliveryUrl:
    126          "https://s-adserver.sandbox.cxad.cxense.com/adserver/search",
    127      },
    128    },
    129    calculateAdSpaceSize(adCount, adUnitSize, marginA, marginB) {
    130      return adCount * (adUnitSize + marginA + marginB);
    131    },
    132    cdn: {
    133      template: {
    134        direct: {
    135          http: "http://cdn.cxpublic.com/",
    136          https: "https://cdn.cxpublic.com/",
    137        },
    138        mapped: {
    139          http: "http://cdn-templates.cxpublic.com/",
    140          https: "https://cdn-templates.cxpublic.com/",
    141        },
    142      },
    143    },
    144    cint() {},
    145    cleanUpGlobalIds: [],
    146    clearBaseUrl: "https://scdn.cxense.com/sclear.html",
    147    clearCustomParameters() {},
    148    clearIdUrl: "https://scomcluster.cxense.com/public/clearid",
    149    clearIds() {},
    150    clickTracker: (a, b, callback) => call(callback),
    151    clientStorageUrl: "https://clientstorage.cxense.com",
    152    combineArgs: () => Object.create(),
    153    combineKeywordsIntoArray: () => [],
    154    consentClasses: ["pv", "segment", "ad", "recs"],
    155    consentClassesV2: ["geo", "device"],
    156    cookieSyncRUrl: "csyn-r.cxense.com",
    157    createDelegate() {},
    158    csdUrls: {
    159      domainScriptUrl: "//csd.cxpublic.com/d/",
    160      customerScriptUrl: "//csd.cxpublic.com/t/",
    161    },
    162    cxenseGlobalIdIframeUrl: "https://scdn.cxense.com/sglobal.html",
    163    cxenseUserIdUrl: "https://id.cxense.com/public/user/id",
    164    decodeUrlEncodedNameValuePairs: () => Object.create(),
    165    defaultAdRenderer: () => "",
    166    deleteCookie() {},
    167    denyWithoutConsent: {
    168      addExternalId: "pv",
    169      getUserSegmentIds: "segment",
    170      insertAdSpace: "ad",
    171      insertMultipleAdSpaces: "ad",
    172      sendEvent: "pv",
    173      sendPageViewEvent: "pv",
    174      sync: "ad",
    175    },
    176    dmpPushUrl: "https://comcluster.cxense.com/dmp/push?callback={{callback}}",
    177    emptyWidgetUrl: "https://scdn.cxense.com/empty.html",
    178    eventReceiverBaseUrl: "https://scomcluster.cxense.com/Repo/rep.html",
    179    eventReceiverBaseUrlGif: "https://scomcluster.cxense.com/Repo/rep.gif",
    180    getAllText: () => "",
    181    getClientStorageVariable() {},
    182    getCookie: () => null,
    183    getCxenseUserId: () => cxUserId,
    184    getDocumentSize,
    185    getElementPosition: () => topLeft,
    186    getHashFragment: () => location.hash.substr(1),
    187    getLocalStats: () => Object.create(),
    188    getNodeValue: n => n.nodeValue,
    189    getNowSeconds,
    190    getPageContext,
    191    getRandomString,
    192    getScrollPos: () => topLeft,
    193    getSessionId: () => "",
    194    getSiteId: () => "",
    195    getTimezoneOffset: () => new Date().getTimezoneOffset(),
    196    getTopLevelDomain: () => location.hostname,
    197    getUserId: () => userId,
    198    getUserSegmentIds,
    199    getWindowSize,
    200    hasConsent: () => true,
    201    hasHistory: () => true,
    202    hasLocalStorage: () => true,
    203    hasPassiveEventListeners: () => true,
    204    hasPostMessage: () => true,
    205    hasSessionStorage() {},
    206    initializePage() {},
    207    insertAdSpace() {},
    208    insertMultipleAdSpaces() {},
    209    insertWidget() {},
    210    invoke: invokeOn(library),
    211    isAmpIFrame() {},
    212    isArray() {},
    213    isCompatModeActive() {},
    214    isConsentRequired() {},
    215    isEdge: () => false,
    216    isFirefox: () => true,
    217    isIE6Or7: () => false,
    218    isObject,
    219    isRecsDestination: () => false,
    220    isSafari: () => false,
    221    isTextNode: n => n?.nodeType === 3,
    222    isTopWindow: () => window === top,
    223    jsonpRequest: () => false,
    224    loadScript() {},
    225    m_accountId: "0",
    226    m_activityEvents: false,
    227    m_activityState: {
    228      activeTime: startTime,
    229      currScrollLeft: 0,
    230      currScrollTop: 0,
    231      exitLink: "",
    232      hadHIDActivity: false,
    233      maxViewLeft: 1,
    234      maxViewTop: 1,
    235      parentMetrics: undefined,
    236      prevActivityTime: startTime + 2,
    237      prevScreenX: 0,
    238      prevScreenY: 0,
    239      prevScrollLeft: 0,
    240      prevScrollTop: 0,
    241      prevTime: startTime + 1,
    242      prevWindowHeight: 1,
    243      prevWindowWidth: 1,
    244      scrollDepthPercentage: 0,
    245      scrollDepthPixels: 0,
    246    },
    247    m_atfr: null,
    248    m_c1xTpWait: 0,
    249    m_clientStorage: {
    250      iframeEl: null,
    251      iframeIsLoaded: false,
    252      iframeOrigin: "https://clientstorage.cxense.com",
    253      iframePath: "/clientstorage_v2.html",
    254      messageContexts: {},
    255      messageQueue: [],
    256    },
    257    m_compatMode: {},
    258    m_compatModeActive: false,
    259    m_compatPvSent: false,
    260    m_consentVersion: 1,
    261    m_customParameters: [],
    262    m_documentSizeRequestedFromChild: false,
    263    m_externalUserIds: [],
    264    m_globalIdLoading: {
    265      globalIdIFrameEl: null,
    266      globalIdIFrameElLoaded: false,
    267    },
    268    m_isSpaRecsDestination: false,
    269    m_knownMessageSources: [],
    270    m_p1Complete: false,
    271    m_prevLocationHash: "",
    272    m_previousPageViewReport: null,
    273    m_rawCustomParameters: {},
    274    m_rnd: getRandomString(),
    275    m_scriptStartTime: startTime,
    276    m_siteId: "0",
    277    m_spaRecsClickUrl: null,
    278    m_thirdPartyIds: true,
    279    m_usesConsent: false,
    280    m_usesIabConsent: false,
    281    m_usesSecureCookies: true,
    282    m_usesTcf20Consent: false,
    283    m_widgetSpecs: {},
    284    Object,
    285    onClearIds() {},
    286    onFFP1() {},
    287    onP1() {},
    288    p1BaseUrl: "https://scdn.cxense.com/sp1.html",
    289    p1JsUrl: "https://p1cluster.cxense.com/p1.js",
    290    parseHashArgs: () => Object.create(),
    291    parseMargins: () => margins,
    292    parseUrlArgs: () => Object.create(),
    293    postMessageToParent() {},
    294    publicWidgetDataUrl: "https://api.cxense.com/public/widget/data",
    295    removeClientStorageVariable() {},
    296    removeEventListener() {},
    297    renderContainedImage: () => "<div/>",
    298    renderTemplate: () => "<div/>",
    299    reportActivity() {},
    300    requireActivityEvents() {},
    301    requireConsent() {},
    302    requireOnlyFirstPartyIds() {},
    303    requireSecureCookies() {},
    304    requireTcf20() {},
    305    sendEvent,
    306    sendSpaRecsClick: (a, callback) => call(callback),
    307    setAccountId() {},
    308    setAllConsentsTo() {},
    309    setClientStorageVariable() {},
    310    setCompatMode() {},
    311    setConsent() {},
    312    setCookie() {},
    313    setCustomParameters() {},
    314    setEventAttributes() {},
    315    setGeoPosition() {},
    316    setNodeValue() {},
    317    setRandomId() {},
    318    setRestrictionsToConsentClasses() {},
    319    setRetargetingParameters() {},
    320    setSiteId() {},
    321    setUserProfileParameters() {},
    322    setupIabCmp() {},
    323    setupTcfApi() {},
    324    shouldPollActivity() {},
    325    startLocalStats() {},
    326    startSessionAnnotation() {},
    327    stopAllSessionAnnotations() {},
    328    stopSessionAnnotation() {},
    329    sync() {},
    330    trackAmpIFrame() {},
    331    trackElement() {},
    332    trim: s => s.trim(),
    333    tsridUrl: "https://tsrid.cxense.com/lookup?callback={{callback}}",
    334    userSegmentUrl:
    335      "https://api.cxense.com/profile/user/segment?callback={{callback}}",
    336  };
    337 
    338  const libraryCCE = {
    339    "__cx-toolkit__": {
    340      isShown: true,
    341      data: [],
    342    },
    343    activeSnapPoint: null,
    344    activeWidgets: [],
    345    ccePushUrl,
    346    clickTracker: () => "",
    347    displayResult() {},
    348    displayWidget,
    349    getDivId,
    350    getTestGroup: () => testGroup,
    351    init,
    352    insertMaster() {},
    353    instrumentClickLinks() {},
    354    invoke: invokeOn(libraryCCE),
    355    noCache: false,
    356    offerProductId: null,
    357    persistedQueryId: null,
    358    prefix: null,
    359    previewCampaign: null,
    360    previewDiv: null,
    361    previewId: null,
    362    previewTestId: null,
    363    processCxResult() {},
    364    render,
    365    reportTestImpression() {},
    366    run,
    367    runCtrlVersion,
    368    runCxVersion,
    369    runMulti,
    370    runTest,
    371    sendConversionEvent,
    372    sendPageViewEvent: (a, b, c, callback) => call(callback),
    373    setSnapPoints(x) {
    374      snapPoints = x;
    375    },
    376    setTestGroup(x) {
    377      testGroup = x;
    378    },
    379    setVisibilityField() {},
    380    get snapPoints() {
    381      return snapPoints;
    382    },
    383    startTime,
    384    get testGroup() {
    385      return testGroup;
    386    },
    387    testVariant: null,
    388    trackTime: 0.5,
    389    trackVisibility() {},
    390    updateRecsClickUrls() {},
    391    utmParams: [],
    392    version: "2.42",
    393    visibilityField: "timeHalf",
    394  };
    395 
    396  const CCE = {
    397    activeSnapPoint: null,
    398    activeWidgets: [],
    399    callQueue: callQueueCCE,
    400    ccePushUrl,
    401    clickTracker: () => "",
    402    displayResult() {},
    403    displayWidget,
    404    getDivId,
    405    getTestGroup: () => testGroup,
    406    init,
    407    insertMaster() {},
    408    instrumentClickLinks() {},
    409    invoke: invokeOn(libraryCCE),
    410    library: libraryCCE,
    411    noCache: false,
    412    offerProductId: null,
    413    persistedQueryId: null,
    414    prefix: null,
    415    previewCampaign: null,
    416    previewDiv: null,
    417    previewId: null,
    418    previewTestId: null,
    419    processCxResult() {},
    420    render,
    421    reportTestImpression() {},
    422    run,
    423    runCtrlVersion,
    424    runCxVersion,
    425    runMulti,
    426    runTest,
    427    sendConversionEvent,
    428    sendPageViewEvent: (a, b, c, callback) => call(callback),
    429    setSnapPoints(x) {
    430      snapPoints = x;
    431    },
    432    setTestGroup(x) {
    433      testGroup = x;
    434    },
    435    setVisibilityField() {},
    436    get snapPoints() {
    437      return snapPoints;
    438    },
    439    startTime,
    440    get testGroup() {
    441      return testGroup;
    442    },
    443    testVariant: null,
    444    trackTime: 0.5,
    445    trackVisibility() {},
    446    updateRecsClickUrls() {},
    447    utmParams: [],
    448    version: "2.42",
    449    visibilityField: "timeHalf",
    450  };
    451 
    452  window.cX = {
    453    addCustomerScript() {},
    454    addEventListener() {},
    455    addExternalId() {},
    456    afterInitializePage() {},
    457    allUserConsents: () => undefined,
    458    Array,
    459    calculateAdSpaceSize: () => 0,
    460    callQueue,
    461    CCE,
    462    cint: () => undefined,
    463    clearCustomParameters() {},
    464    clearIds() {},
    465    clickTracker: () => "",
    466    combineArgs: () => Object.create(),
    467    combineKeywordsIntoArray: () => [],
    468    createDelegate() {},
    469    decodeUrlEncodedNameValuePairs: () => Object.create(),
    470    defaultAdRenderer: () => "",
    471    deleteCookie() {},
    472    getAllText: () => "",
    473    getClientStorageVariable() {},
    474    getCookie: () => null,
    475    getCxenseUserId: () => cxUserId,
    476    getDocumentSize,
    477    getElementPosition: () => topLeft,
    478    getHashFragment: () => location.hash.substr(1),
    479    getLocalStats: () => Object.create(),
    480    getNodeValue: n => n.nodeValue,
    481    getNowSeconds,
    482    getPageContext,
    483    getRandomString,
    484    getScrollPos: () => topLeft,
    485    getSessionId: () => "",
    486    getSiteId: () => "",
    487    getTimezoneOffset: () => new Date().getTimezoneOffset(),
    488    getTopLevelDomain: () => location.hostname,
    489    getUserId: () => userId,
    490    getUserSegmentIds,
    491    getWindowSize,
    492    hasConsent: () => true,
    493    hasHistory: () => true,
    494    hasLocalStorage: () => true,
    495    hasPassiveEventListeners: () => true,
    496    hasPostMessage: () => true,
    497    hasSessionStorage() {},
    498    initializePage() {},
    499    insertAdSpace() {},
    500    insertMultipleAdSpaces() {},
    501    insertWidget() {},
    502    invoke: invokeOn(library),
    503    isAmpIFrame() {},
    504    isArray() {},
    505    isCompatModeActive() {},
    506    isConsentRequired() {},
    507    isEdge: () => false,
    508    isFirefox: () => true,
    509    isIE6Or7: () => false,
    510    isObject,
    511    isRecsDestination: () => false,
    512    isSafari: () => false,
    513    isTextNode: n => n?.nodeType === 3,
    514    isTopWindow: () => window === top,
    515    JSON,
    516    jsonpRequest: () => false,
    517    library,
    518    loadScript() {},
    519    Object,
    520    onClearIds() {},
    521    onFFP1() {},
    522    onP1() {},
    523    parseHashArgs: () => Object.create(),
    524    parseMargins: () => margins,
    525    parseUrlArgs: () => Object.create(),
    526    postMessageToParent() {},
    527    removeClientStorageVariable() {},
    528    removeEventListener() {},
    529    renderContainedImage: () => "<div/>",
    530    renderTemplate: () => "<div/>",
    531    reportActivity() {},
    532    requireActivityEvents() {},
    533    requireConsent() {},
    534    requireOnlyFirstPartyIds() {},
    535    requireSecureCookies() {},
    536    requireTcf20() {},
    537    sendEvent,
    538    sendPageViewEvent: (a, callback) => call(callback, {}),
    539    sendSpaRecsClick() {},
    540    setAccountId() {},
    541    setAllConsentsTo() {},
    542    setClientStorageVariable() {},
    543    setCompatMode() {},
    544    setConsent() {},
    545    setCookie() {},
    546    setCustomParameters() {},
    547    setEventAttributes() {},
    548    setGeoPosition() {},
    549    setNodeValue() {},
    550    setRandomId() {},
    551    setRestrictionsToConsentClasses() {},
    552    setRetargetingParameters() {},
    553    setSiteId() {},
    554    setUserProfileParameters() {},
    555    setupIabCmp() {},
    556    setupTcfApi() {},
    557    shouldPollActivity() {},
    558    startLocalStats() {},
    559    startSessionAnnotation() {},
    560    stopAllSessionAnnotations() {},
    561    stopSessionAnnotation() {},
    562    sync() {},
    563    trackAmpIFrame() {},
    564    trackElement() {},
    565    trim: s => s.trim(),
    566  };
    567 
    568  window.cxTest = window.cX;
    569 
    570  window.cx_pollActiveTime = () => undefined;
    571  window.cx_pollActivity = () => undefined;
    572  window.cx_pollFragmentMessage = () => undefined;
    573 
    574  const execQueue = (lib, queue) => {
    575    return () => {
    576      const invoke = invokeOn(lib);
    577      setTimeout(() => {
    578        queue.push = cmd => {
    579          setTimeout(() => invoke(...cmd), 1);
    580        };
    581        for (const cmd of queue) {
    582          invoke(...cmd);
    583        }
    584      }, 25);
    585    };
    586  };
    587 
    588  window.cx_callQueueExecute = execQueue(library, callQueue);
    589  window.cxCCE_callQueueExecute = execQueue(libraryCCE, callQueueCCE);
    590 
    591  window.cx_callQueueExecute();
    592  window.cxCCE_callQueueExecute();
    593 }