From b445f4f4cd470d4a7246b7c2e8cfbe2d14e3647e Mon Sep 17 00:00:00 2001 From: Dave Vandyke Date: Tue, 24 Oct 2023 16:16:14 +0100 Subject: [PATCH] Improve google-ima shim script (#3899) We made use of the google-ima shim script from uBlock in the DuckDuckGo Privacy Essentials extension recently, but found a few issues with website breakage. After debugging and fixing those[1], I thought it would be worth sharing the improvements back again. Issues we ran into: - The AdDisplayContainer[2] constructor usually creates some DOM elements inside the given container. They are all nested within a DIV and some websites break when at least that top DIV element isn't created. - While not documented (that I could see), the event listeners can be added using an array of event types. Some websites make use of that and then hang forever when the expected events aren't fired. This caused videos not to play on some websites. - The Ad.prototype.getUniversalAdIds()[3] method should return an array of UniversalAdIdInfo Objects, instead of an Array of strings. When an array of strings are returned, some websites then break when the UniversalAdIdInfo's methods are missing. - The UniversalAdIdInfo.prototype.getAdIdValue()[4] method had a typo in the name ("getAsIdValue") and was effectively missing. That caused some websites to break when the missing method was called. - The google.ima.OmidVerificationVendor[5] Object was missing, which broke some websites that attempted to access it. 1 - https://github.com/duckduckgo/tracker-surrogates/commit/52f2999523ae0aeacaeb57937b2f790b886d12c1 2 - https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/js/google.ima.AdDisplayContainer 3 - https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/js/google.ima.Ad#getUniversalAdIds 4 - https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/js/google.ima.UniversalAdIdInfo#getAdIdValue 5 - https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/js/google.ima#.OmidVerificationVendor --- src/web_accessible_resources/google-ima.js | 51 +++++++++++++++------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/src/web_accessible_resources/google-ima.js b/src/web_accessible_resources/google-ima.js index ad1277289..53fc78d0b 100644 --- a/src/web_accessible_resources/google-ima.js +++ b/src/web_accessible_resources/google-ima.js @@ -233,6 +233,12 @@ if (!window.google || !window.google.ima || !window.google.ima.VERSION) { const ima = {}; class AdDisplayContainer { + constructor(containerElement) { + const divElement = document.createElement("div"); + divElement.style.setProperty("display", "none", "important"); + divElement.style.setProperty("visibility", "collapse", "important"); + containerElement.appendChild(divElement); + } destroy() {} initialize() {} } @@ -335,17 +341,30 @@ if (!window.google || !window.google.ima || !window.google.ima.VERSION) { } } - addEventListener(t, c) { - if (!this.listeners.has(t)) { - this.listeners.set(t, new Set()); + addEventListener(types, c) { + if (!Array.isArray(types)) { + types = [types]; + } + + for (const t of types) { + if (!this.listeners.has(t)) { + this.listeners.set(t, new Set()); + } + this.listeners.get(t).add(c); } - this.listeners.get(t).add(c); } - removeEventListener(t, c) { - const typeSet = this.listeners.get(t); - if (!typeSet) { return; } - typeSet.delete(c); + removeEventListener(types, c) { + if (!Array.isArray(types)) { + types = [types]; + } + + for (const t of types) { + const typeSet = this.listeners.get(t); + if (typeSet) { + typeSet.delete(c); + } + } } } @@ -553,7 +572,7 @@ if (!window.google || !window.google.ima || !window.google.ima.VERSION) { return "unknown"; } getUniversalAdIds() { - return [""]; + return [new UniversalAdIdInfo()]; } getUniversalAdIdValue() { return "unknown"; @@ -765,7 +784,7 @@ if (!window.google || !window.google.ima || !window.google.ima.VERSION) { getAdIdRegistry() { return ""; } - getAdIsValue() { + getAdIdValue() { return ""; } } @@ -793,12 +812,12 @@ if (!window.google || !window.google.ima || !window.google.ima.VERSION) { FULL: "full", LIMITED: "limited", }, - OmidVerificationVendor: new Proxy({}, { - get(target, prop) { - if ( typeof prop === 'number' ) { return ''; } - return 0; - } - }), + OmidVerificationVendor: { + 1: "OTHER", + 2: "GOOGLE", + GOOGLE: 2, + OTHER: 1 + }, settings: new ImaSdkSettings(), UiElements: { AD_ATTRIBUTION: "adAttribution",