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 }