tor-browser

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

adnexus-ast.js (4636B)


      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 1734130 - Shim AdNexus AST
      9 *
     10 * Some sites expect AST to successfully load, or they break.
     11 * This shim mitigates that breakage.
     12 */
     13 
     14 if (!window.apntag?.loaded) {
     15  const anq = window.apntag?.anq || [];
     16 
     17  const gTags = new Map();
     18  const gAds = new Map();
     19  const gEventHandlers = {};
     20 
     21  const Ad = class {
     22    adType = "banner";
     23    auctionId = "-";
     24    banner = {
     25      width: 1,
     26      height: 1,
     27      content: "",
     28      trackers: {
     29        impression_urls: [],
     30        video_events: {},
     31      },
     32    };
     33    brandCategoryId = 0;
     34    buyerMemberId = 0;
     35    cpm = 0.1;
     36    cpm_publisher_currency = 0.1;
     37    creativeId = 0;
     38    dealId = undefined;
     39    height = 1;
     40    mediaSubtypeId = 1;
     41    mediaTypeId = 1;
     42    publisher_currency_code = "US";
     43    source = "-";
     44    tagId = -1;
     45    targetId = "";
     46    width = 1;
     47 
     48    constructor(tagId, targetId) {
     49      this.tagId = tagId;
     50      this.targetId = targetId;
     51    }
     52  };
     53 
     54  const fireAdEvent = (type, adObj) => {
     55    const { targetId } = adObj;
     56    const handlers = gEventHandlers[type]?.[targetId];
     57    if (!handlers) {
     58      return Promise.resolve();
     59    }
     60    const evt = { adObj, type };
     61    return new Promise(done => {
     62      setTimeout(() => {
     63        for (const cb of handlers) {
     64          try {
     65            cb(evt);
     66          } catch (e) {
     67            console.error(e);
     68          }
     69        }
     70        done();
     71      }, 1);
     72    });
     73  };
     74 
     75  const refreshTag = targetId => {
     76    const tag = gTags.get(targetId);
     77    if (!tag) {
     78      return;
     79    }
     80    if (!gAds.has(targetId)) {
     81      gAds.set(targetId, new Ad(tag.tagId, targetId));
     82    }
     83    const adObj = gAds.get(targetId);
     84    fireAdEvent("adRequested", adObj).then(() => {
     85      // TODO: do some sites expect adAvailable+adLoaded instead of adNoBid?
     86      fireAdEvent("adNoBid", adObj);
     87    });
     88  };
     89 
     90  const off = (type, targetId, cb) => {
     91    gEventHandlers[type]?.[targetId]?.delete(cb);
     92  };
     93 
     94  const on = (type, targetId, cb) => {
     95    gEventHandlers[type] = gEventHandlers[type] || {};
     96    gEventHandlers[type][targetId] =
     97      gEventHandlers[type][targetId] || new Set();
     98    gEventHandlers[type][targetId].add(cb);
     99  };
    100 
    101  const Tag = class {
    102    static #nextId = 0;
    103    debug = undefined;
    104    displayed = false;
    105    initialHeight = 1;
    106    initialWidth = 1;
    107    keywords = {};
    108    member = 0;
    109    showTagCalled = false;
    110    sizes = [];
    111    targetId = "";
    112    utCalled = true;
    113    utDivId = "";
    114    utiframeId = "";
    115    uuid = "";
    116 
    117    constructor(raw) {
    118      const { keywords, sizes, targetId } = raw;
    119      this.tagId = Tag.#nextId++;
    120      this.keywords = keywords || {};
    121      this.sizes = sizes || [];
    122      this.targetId = targetId || "";
    123    }
    124    modifyTag() {}
    125    off(type, cb) {
    126      off(type, this.targetId, cb);
    127    }
    128    on(type, cb) {
    129      on(type, this.targetId, cb);
    130    }
    131    setKeywords(kw) {
    132      this.keywords = kw;
    133    }
    134  };
    135 
    136  window.apntag = {
    137    anq,
    138    attachClickTrackers() {},
    139    checkAdAvailable() {},
    140    clearPageTargeting() {},
    141    clearRequest() {},
    142    collapseAd() {},
    143    debug: false,
    144    defineTag(dfn) {
    145      const { targetId } = dfn;
    146      if (!targetId) {
    147        return;
    148      }
    149      gTags.set(targetId, new Tag(dfn));
    150    },
    151    disableDebug() {},
    152    dongle: undefined,
    153    emitEvent(adObj, type) {
    154      fireAdEvent(type, adObj);
    155    },
    156    enableCookieSet() {},
    157    enableDebug() {},
    158    fireImpressionTrackers() {},
    159    getAdMarkup: () => "",
    160    getAdWrap() {},
    161    getAstVersion: () => "0.49.0",
    162    getPageTargeting() {},
    163    getTag(targetId) {
    164      return gTags.get(targetId);
    165    },
    166    handleCb() {},
    167    handleMediationBid() {},
    168    highlightAd() {},
    169    loaded: true,
    170    loadTags() {
    171      for (const tagName of gTags.keys()) {
    172        refreshTag(tagName);
    173      }
    174    },
    175    modifyTag() {},
    176    notify() {},
    177    offEvent(type, target, cb) {
    178      off(type, target, cb);
    179    },
    180    onEvent(type, target, cb) {
    181      on(type, target, cb);
    182    },
    183    recordErrorEvent() {},
    184    refresh() {},
    185    registerRenderer() {},
    186    requests: {},
    187    resizeAd() {},
    188    setEndpoint() {},
    189    setKeywords() {},
    190    setPageOpts() {},
    191    setPageTargeting() {},
    192    setSafeFrameConfig() {},
    193    setSizes() {},
    194    showTag() {},
    195  };
    196 
    197  const push = function (fn) {
    198    if (typeof fn === "function") {
    199      try {
    200        fn();
    201      } catch (e) {
    202        console.trace(e);
    203      }
    204    }
    205  };
    206 
    207  anq.push = push;
    208 
    209  anq.forEach(push);
    210 }