tor-browser

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

google-ima.js (13793B)


      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 /**
      6 * Bug 1713690 - Shim Google Interactive Media Ads ima3.js
      7 *
      8 * Many sites use ima3.js for ad bidding and placement, often in conjunction
      9 * with Google Publisher Tags, Prebid.js and/or other scripts. This shim
     10 * provides a stubbed-out version of the API which helps work around related
     11 * site breakage, such as black bxoes where videos ought to be placed.
     12 */
     13 
     14 if (!window.google?.ima?.VERSION) {
     15  const VERSION = "3.517.2";
     16 
     17  const CheckCanAutoplay = (function () {
     18    // Sourced from: https://searchfox.org/mozilla-central/source/dom/media/gtest/negative_duration.mp4
     19    const TEST_VIDEO = new Blob(
     20      [
     21        new Uint32Array([
     22          469762048, 1887007846, 1752392036, 0, 913273705, 1717987696,
     23          828601953, -1878917120, 1987014509, 1811939328, 1684567661, 0, 0, 0,
     24          -402456576, 0, 256, 1, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 64, 0, 0, 0,
     25          0, 0, 0, 33554432, -201261056, 1801548404, 1744830464, 1684564852,
     26          251658241, 0, 0, 0, 0, 16777216, 0, -1, -1, 0, 0, 0, 0, 256, 0, 0, 0,
     27          256, 0, 0, 0, 64, 5, 53250, -2080309248, 1634296941, 738197504,
     28          1684563053, 1, 0, 0, 0, 0, -2137614336, -1, -1, 50261, 754974720,
     29          1919706216, 0, 0, 1701079414, 0, 0, 0, 1701079382, 1851869295,
     30          1919249508, 16777216, 1852402979, 102, 1752004116, 100, 1, 0, 0,
     31          1852400676, 102, 1701995548, 102, 0, 1, 1819440396, 32, 1, 1651799011,
     32          108, 1937011607, 100, 0, 1, 1668702599, 49, 0, 1, 0, 0, 0, 33555712,
     33          4718800, 4718592, 0, 65536, 0, 0, 0, 0, 0, 0, 0, 0, 16776984,
     34          1630601216, 21193590, -14745500, 1729626337, -1407254428, 89161945,
     35          1049019, 9453056, -251611125, 27269507, -379058688, -1329024392,
     36          268435456, 1937011827, 0, 0, 268435456, 1668510835, 0, 0, 335544320,
     37          2054386803, 0, 0, 0, 268435456, 1868788851, 0, 0, 671088640,
     38          2019915373, 536870912, 2019914356, 0, 16777216, 16777216, 0, 0, 0,
     39        ]),
     40      ],
     41      { type: "video/mp4" }
     42    );
     43 
     44    let testVideo = undefined;
     45 
     46    return function () {
     47      if (!testVideo) {
     48        testVideo = document.createElement("video");
     49        testVideo.style =
     50          "position:absolute; width:0; height:0; left:0; right:0; z-index:-1; border:0";
     51        testVideo.setAttribute("muted", "muted");
     52        testVideo.setAttribute("playsinline", "playsinline");
     53        testVideo.src = URL.createObjectURL(TEST_VIDEO);
     54        document.body.appendChild(testVideo);
     55      }
     56      return testVideo.play();
     57    };
     58  })();
     59 
     60  let ima = {};
     61 
     62  class AdDisplayContainer {
     63    destroy() {}
     64    initialize() {}
     65  }
     66 
     67  class ImaSdkSettings {
     68    #c = true;
     69    #f = {};
     70    #i = false;
     71    #l = "";
     72    #p = "";
     73    #r = 0;
     74    #t = "";
     75    #v = "";
     76    getCompanionBackfill() {}
     77    getDisableCustomPlaybackForIOS10Plus() {
     78      return this.#i;
     79    }
     80    getFeatureFlags() {
     81      return this.#f;
     82    }
     83    getLocale() {
     84      return this.#l;
     85    }
     86    getNumRedirects() {
     87      return this.#r;
     88    }
     89    getPlayerType() {
     90      return this.#t;
     91    }
     92    getPlayerVersion() {
     93      return this.#v;
     94    }
     95    getPpid() {
     96      return this.#p;
     97    }
     98    isCookiesEnabled() {
     99      return this.#c;
    100    }
    101    setAutoPlayAdBreaks() {}
    102    setCompanionBackfill() {}
    103    setCookiesEnabled(c) {
    104      this.#c = !!c;
    105    }
    106    setDisableCustomPlaybackForIOS10Plus(i) {
    107      this.#i = !!i;
    108    }
    109    setFeatureFlags(f) {
    110      this.#f = f;
    111    }
    112    setLocale(l) {
    113      this.#l = l;
    114    }
    115    setNumRedirects(r) {
    116      this.#r = r;
    117    }
    118    setPlayerType(t) {
    119      this.#t = t;
    120    }
    121    setPlayerVersion(v) {
    122      this.#v = v;
    123    }
    124    setPpid(p) {
    125      this.#p = p;
    126    }
    127    setSessionId(_s) {}
    128    setVpaidAllowed(_a) {}
    129    setVpaidMode(_m) {}
    130  }
    131  ImaSdkSettings.CompanionBackfillMode = {
    132    ALWAYS: "always",
    133    ON_MASTER_AD: "on_master_ad",
    134  };
    135  ImaSdkSettings.VpaidMode = {
    136    DISABLED: 0,
    137    ENABLED: 1,
    138    INSECURE: 2,
    139  };
    140 
    141  class EventHandler {
    142    #listeners = new Map();
    143 
    144    _dispatch(e) {
    145      const listeners = this.#listeners.get(e.type) || [];
    146      for (const listener of Array.from(listeners)) {
    147        try {
    148          listener(e);
    149        } catch (r) {
    150          console.error(r);
    151        }
    152      }
    153    }
    154 
    155    addEventListener(t, c) {
    156      if (!this.#listeners.has(t)) {
    157        this.#listeners.set(t, new Set());
    158      }
    159      this.#listeners.get(t).add(c);
    160    }
    161 
    162    removeEventListener(t, c) {
    163      this.#listeners.get(t)?.delete(c);
    164    }
    165  }
    166 
    167  class AdsLoader extends EventHandler {
    168    #settings = new ImaSdkSettings();
    169    contentComplete() {}
    170    destroy() {}
    171    getSettings() {
    172      return this.#settings;
    173    }
    174    getVersion() {
    175      return VERSION;
    176    }
    177    requestAds(_r, _c) {
    178      // If autoplay is disabled and the page is trying to autoplay a tracking
    179      // ad, then IMA fails with an error, and the page is expected to request
    180      // ads again later when the user clicks to play.
    181      CheckCanAutoplay().then(
    182        () => {
    183          const { ADS_MANAGER_LOADED } = AdsManagerLoadedEvent.Type;
    184          this._dispatch(new ima.AdsManagerLoadedEvent(ADS_MANAGER_LOADED));
    185        },
    186        () => {
    187          const e = new ima.AdError(
    188            "adPlayError",
    189            1205,
    190            1205,
    191            "The browser prevented playback initiated without user interaction."
    192          );
    193          this._dispatch(new ima.AdErrorEvent(e));
    194        }
    195      );
    196    }
    197  }
    198 
    199  class AdsManager extends EventHandler {
    200    #volume = 1;
    201    collapse() {}
    202    configureAdsManager() {}
    203    destroy() {}
    204    discardAdBreak() {}
    205    expand() {}
    206    focus() {}
    207    getAdSkippableState() {
    208      return false;
    209    }
    210    getCuePoints() {
    211      return [0];
    212    }
    213    getCurrentAd() {
    214      return currentAd;
    215    }
    216    getCurrentAdCuePoints() {
    217      return [];
    218    }
    219    getRemainingTime() {
    220      return 0;
    221    }
    222    getVolume() {
    223      return this.#volume;
    224    }
    225    init(_w, _h, _m, _e) {}
    226    isCustomClickTrackingUsed() {
    227      return false;
    228    }
    229    isCustomPlaybackUsed() {
    230      return false;
    231    }
    232    pause() {}
    233    requestNextAdBreak() {}
    234    resize(_w, _h, _m) {}
    235    resume() {}
    236    setVolume(v) {
    237      this.#volume = v;
    238    }
    239    skip() {}
    240    start() {
    241      requestAnimationFrame(() => {
    242        for (const type of [
    243          AdEvent.Type.LOADED,
    244          AdEvent.Type.STARTED,
    245          AdEvent.Type.CONTENT_RESUME_REQUESTED,
    246          AdEvent.Type.AD_BUFFERING,
    247          AdEvent.Type.FIRST_QUARTILE,
    248          AdEvent.Type.MIDPOINT,
    249          AdEvent.Type.THIRD_QUARTILE,
    250          AdEvent.Type.COMPLETE,
    251          AdEvent.Type.ALL_ADS_COMPLETED,
    252        ]) {
    253          try {
    254            this._dispatch(new ima.AdEvent(type));
    255          } catch (e) {
    256            console.error(e);
    257          }
    258        }
    259      });
    260    }
    261    stop() {}
    262    updateAdsRenderingSettings(_s) {}
    263  }
    264 
    265  class AdsRenderingSettings {}
    266 
    267  class AdsRequest {
    268    setAdWillAutoPlay() {}
    269    setAdWillPlayMuted() {}
    270    setContinuousPlayback() {}
    271  }
    272 
    273  class AdPodInfo {
    274    getAdPosition() {
    275      return 1;
    276    }
    277    getIsBumper() {
    278      return false;
    279    }
    280    getMaxDuration() {
    281      return -1;
    282    }
    283    getPodIndex() {
    284      return 1;
    285    }
    286    getTimeOffset() {
    287      return 0;
    288    }
    289    getTotalAds() {
    290      return 1;
    291    }
    292  }
    293 
    294  class Ad {
    295    _pi = new AdPodInfo();
    296    getAdId() {
    297      return "";
    298    }
    299    getAdPodInfo() {
    300      return this._pi;
    301    }
    302    getAdSystem() {
    303      return "";
    304    }
    305    getAdvertiserName() {
    306      return "";
    307    }
    308    getApiFramework() {
    309      return null;
    310    }
    311    getCompanionAds() {
    312      return [];
    313    }
    314    getContentType() {
    315      return "";
    316    }
    317    getCreativeAdId() {
    318      return "";
    319    }
    320    getCreativeId() {
    321      return "";
    322    }
    323    getDealId() {
    324      return "";
    325    }
    326    getDescription() {
    327      return "";
    328    }
    329    getDuration() {
    330      return 8.5;
    331    }
    332    getHeight() {
    333      return 0;
    334    }
    335    getMediaUrl() {
    336      return null;
    337    }
    338    getMinSuggestedDuration() {
    339      return -2;
    340    }
    341    getSkipTimeOffset() {
    342      return -1;
    343    }
    344    getSurveyUrl() {
    345      return null;
    346    }
    347    getTitle() {
    348      return "";
    349    }
    350    getTraffickingParameters() {
    351      return {};
    352    }
    353    getTraffickingParametersString() {
    354      return "";
    355    }
    356    getUiElements() {
    357      return [""];
    358    }
    359    getUniversalAdIdRegistry() {
    360      return "unknown";
    361    }
    362    getUniversalAdIds() {
    363      return [""];
    364    }
    365    getUniversalAdIdValue() {
    366      return "unknown";
    367    }
    368    getVastMediaBitrate() {
    369      return 0;
    370    }
    371    getVastMediaHeight() {
    372      return 0;
    373    }
    374    getVastMediaWidth() {
    375      return 0;
    376    }
    377    getWidth() {
    378      return 0;
    379    }
    380    getWrapperAdIds() {
    381      return [""];
    382    }
    383    getWrapperAdSystems() {
    384      return [""];
    385    }
    386    getWrapperCreativeIds() {
    387      return [""];
    388    }
    389    isLinear() {
    390      return true;
    391    }
    392    isSkippable() {
    393      return true;
    394    }
    395  }
    396 
    397  class CompanionAd {
    398    getAdSlotId() {
    399      return "";
    400    }
    401    getContent() {
    402      return "";
    403    }
    404    getContentType() {
    405      return "";
    406    }
    407    getHeight() {
    408      return 1;
    409    }
    410    getWidth() {
    411      return 1;
    412    }
    413  }
    414 
    415  class AdError {
    416    #errorCode = -1;
    417    #message = "";
    418    #type = "";
    419    #vastErrorCode = -1;
    420    constructor(type, code, vast, message) {
    421      this.#errorCode = code;
    422      this.#message = message;
    423      this.#type = type;
    424      this.#vastErrorCode = vast;
    425    }
    426    getErrorCode() {
    427      return this.#errorCode;
    428    }
    429    getInnerError() {}
    430    getMessage() {
    431      return this.#message;
    432    }
    433    getType() {
    434      return this.#type;
    435    }
    436    getVastErrorCode() {
    437      return this.#vastErrorCode;
    438    }
    439    toString() {
    440      return `AdError ${this.#errorCode}: ${this.#message}`;
    441    }
    442  }
    443  AdError.ErrorCode = {};
    444  AdError.Type = {};
    445 
    446  const isEngadget = () => {
    447    try {
    448      for (const ctx of Object.values(window.vidible._getContexts())) {
    449        if (ctx.getPlayer()?.div?.innerHTML.includes("www.engadget.com")) {
    450          return true;
    451        }
    452      }
    453    } catch (_) {}
    454    return false;
    455  };
    456 
    457  const currentAd = isEngadget() ? undefined : new Ad();
    458 
    459  class AdEvent {
    460    constructor(type) {
    461      this.type = type;
    462    }
    463    getAd() {
    464      return currentAd;
    465    }
    466    getAdData() {
    467      return {};
    468    }
    469  }
    470  AdEvent.Type = {
    471    AD_BREAK_READY: "adBreakReady",
    472    AD_BUFFERING: "adBuffering",
    473    AD_CAN_PLAY: "adCanPlay",
    474    AD_METADATA: "adMetadata",
    475    AD_PROGRESS: "adProgress",
    476    ALL_ADS_COMPLETED: "allAdsCompleted",
    477    CLICK: "click",
    478    COMPLETE: "complete",
    479    CONTENT_PAUSE_REQUESTED: "contentPauseRequested",
    480    CONTENT_RESUME_REQUESTED: "contentResumeRequested",
    481    DURATION_CHANGE: "durationChange",
    482    EXPANDED_CHANGED: "expandedChanged",
    483    FIRST_QUARTILE: "firstQuartile",
    484    IMPRESSION: "impression",
    485    INTERACTION: "interaction",
    486    LINEAR_CHANGE: "linearChange",
    487    LINEAR_CHANGED: "linearChanged",
    488    LOADED: "loaded",
    489    LOG: "log",
    490    MIDPOINT: "midpoint",
    491    PAUSED: "pause",
    492    RESUMED: "resume",
    493    SKIPPABLE_STATE_CHANGED: "skippableStateChanged",
    494    SKIPPED: "skip",
    495    STARTED: "start",
    496    THIRD_QUARTILE: "thirdQuartile",
    497    USER_CLOSE: "userClose",
    498    VIDEO_CLICKED: "videoClicked",
    499    VIDEO_ICON_CLICKED: "videoIconClicked",
    500    VIEWABLE_IMPRESSION: "viewable_impression",
    501    VOLUME_CHANGED: "volumeChange",
    502    VOLUME_MUTED: "mute",
    503  };
    504 
    505  class AdErrorEvent {
    506    type = "adError";
    507    #error = "";
    508    constructor(error) {
    509      this.#error = error;
    510    }
    511    getError() {
    512      return this.#error;
    513    }
    514    getUserRequestContext() {
    515      return {};
    516    }
    517  }
    518  AdErrorEvent.Type = {
    519    AD_ERROR: "adError",
    520  };
    521 
    522  const manager = new AdsManager();
    523 
    524  class AdsManagerLoadedEvent {
    525    constructor(type) {
    526      this.type = type;
    527    }
    528    getAdsManager() {
    529      return manager;
    530    }
    531    getUserRequestContext() {
    532      return {};
    533    }
    534  }
    535  AdsManagerLoadedEvent.Type = {
    536    ADS_MANAGER_LOADED: "adsManagerLoaded",
    537  };
    538 
    539  class CustomContentLoadedEvent {}
    540  CustomContentLoadedEvent.Type = {
    541    CUSTOM_CONTENT_LOADED: "deprecated-event",
    542  };
    543 
    544  class CompanionAdSelectionSettings {}
    545  CompanionAdSelectionSettings.CreativeType = {
    546    ALL: "All",
    547    FLASH: "Flash",
    548    IMAGE: "Image",
    549  };
    550  CompanionAdSelectionSettings.ResourceType = {
    551    ALL: "All",
    552    HTML: "Html",
    553    IFRAME: "IFrame",
    554    STATIC: "Static",
    555  };
    556  CompanionAdSelectionSettings.SizeCriteria = {
    557    IGNORE: "IgnoreSize",
    558    SELECT_EXACT_MATCH: "SelectExactMatch",
    559    SELECT_NEAR_MATCH: "SelectNearMatch",
    560  };
    561 
    562  class AdCuePoints {
    563    getCuePoints() {
    564      return [];
    565    }
    566  }
    567 
    568  class AdProgressData {}
    569 
    570  class UniversalAdIdInfo {
    571    getAdIdRegistry() {
    572      return "";
    573    }
    574    getAdIsValue() {
    575      return "";
    576    }
    577  }
    578 
    579  Object.assign(ima, {
    580    AdCuePoints,
    581    AdDisplayContainer,
    582    AdError,
    583    AdErrorEvent,
    584    AdEvent,
    585    AdPodInfo,
    586    AdProgressData,
    587    AdsLoader,
    588    AdsManager: manager,
    589    AdsManagerLoadedEvent,
    590    AdsRenderingSettings,
    591    AdsRequest,
    592    CompanionAd,
    593    CompanionAdSelectionSettings,
    594    CustomContentLoadedEvent,
    595    gptProxyInstance: {},
    596    ImaSdkSettings,
    597    OmidAccessMode: {
    598      DOMAIN: "domain",
    599      FULL: "full",
    600      LIMITED: "limited",
    601    },
    602    settings: new ImaSdkSettings(),
    603    UiElements: {
    604      AD_ATTRIBUTION: "adAttribution",
    605      COUNTDOWN: "countdown",
    606    },
    607    UniversalAdIdInfo,
    608    VERSION,
    609    ViewMode: {
    610      FULLSCREEN: "fullscreen",
    611      NORMAL: "normal",
    612    },
    613  });
    614 
    615  if (!window.google) {
    616    window.google = {};
    617  }
    618 
    619  window.google.ima = ima;
    620 }