LeOSium_webview/LeOS/patches/Inject-scripts-for-AMP-trac...

193 lines
22 KiB
Diff
Raw Permalink Normal View History

2023-11-18 11:46:19 +01:00
From: csagan5 <32685696+csagan5@users.noreply.github.com>
Date: Sat, 28 Oct 2017 10:09:41 +0200
Subject: Inject scripts for AMP, tracking, ads and video
Remove AMP, tracking and ads from search/news results
Break Page Visibility API and Fullscreen API for youtube.com and vimeo.com to allow playing videos in background (original Javascript code by timdream)
Set proper injection script nonce
Send a random key press to circumvent idle status detection
License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
---
third_party/blink/renderer/core/dom/build.gni | 2 +
.../blink/renderer/core/dom/document.cc | 64 +++++++++++++++++++
.../blink/renderer/core/dom/document.h | 3 +
.../core/dom/extensions/anti_amp_cure.h | 6 ++
.../core/dom/extensions/video_bg_play.h | 6 ++
.../renderer/core/html/html_script_element.cc | 5 ++
.../renderer/core/html/html_script_element.h | 1 +
7 files changed, 87 insertions(+)
create mode 100644 third_party/blink/renderer/core/dom/extensions/anti_amp_cure.h
create mode 100644 third_party/blink/renderer/core/dom/extensions/video_bg_play.h
diff --git a/third_party/blink/renderer/core/dom/build.gni b/third_party/blink/renderer/core/dom/build.gni
--- a/third_party/blink/renderer/core/dom/build.gni
+++ b/third_party/blink/renderer/core/dom/build.gni
@@ -167,6 +167,8 @@ blink_core_sources_dom = [
"has_invalidation_flags.h",
"icon_url.cc",
"icon_url.h",
+ "extensions/anti_amp_cure.h",
+ "extensions/video_bg_play.h",
"id_target_observer.cc",
"id_target_observer.h",
"id_target_observer_registry.cc",
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -295,6 +295,7 @@
#include "third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h"
#include "third_party/blink/renderer/core/page/scrolling/scroll_state_callback.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
+#include "extensions/video_bg_play.h"
#include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.h"
#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
#include "third_party/blink/renderer/core/page/spatial_navigation_controller.h"
@@ -372,6 +373,8 @@
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h"
+#include "extensions/anti_amp_cure.h"
+
#ifndef NDEBUG
using WeakDocumentSet = blink::HeapHashSet<blink::WeakMember<blink::Document>>;
static WeakDocumentSet& LiveDocumentSet();
@@ -7440,6 +7443,64 @@ void Document::OnPrepareToStopParsing() {
MilestoneForDelayedAsyncScript::kFinishedParsing);
}
+void Document::injectScripts() {
+ // determine whether this is a search results page
+ const WTF::String& host = url_.Host();
+ if ((host == nullptr) || host.empty())
+ return;
+
+ auto* bodyElement = body();
+ if (!bodyElement)
+ return;
+ int selected = 0;
+ size_t pos1 = host.Find("www.google."), pos2 = host.Find("news.google."), pos3 = url_.GetPath().Find("/search"), pos4 = host.Find("images.google.");
+ if (((pos1 == 0) && (pos3 == 0)) || (pos2 == 0) || (pos4 == 0)) {
+ LOG(INFO) << "injecting AMP removal Javascript payload";
+ selected = 1;
+ // check for eligibility of the video bg fix
+ } else if (
+ ((WTF::kNotFound != host.Find("youtube.com")) && (WTF::kNotFound == host.Find("accounts.youtube.com"))) ||
+ (WTF::kNotFound != host.Find("vimeo.com"))
+ ) {
+ LOG(INFO) << "injecting video-bg-play Javascript payload";
+ selected = 2;
+ } else
+ return;
+
+ // find out which nonce to use
+ const AtomicString& nonce = findFirstScriptNonce();
+
+ HTMLScriptElement* e = MakeGarbageCollected<HTMLScriptElement>(*this, CreateElementFlags());
+ if (selected == 1)
+ e->setTextContent(ANTI_AMP_CURE_JS);
+ else if (selected == 2)
+ e->setTextContent(VIDEO_BG_PLAY_JS);
+ else
+ NOTREACHED();
+
+ if (nonce != g_null_atom) {
+ e->setNonce(nonce);
+ } else
+ LOG(WARNING) << "could not find script nonce to use";
+
+ bodyElement->AppendChild(e);
+}
+
+const AtomicString& Document::findFirstScriptNonce() {
+ HTMLCollection* s = scripts();
+ unsigned source_length = (unsigned)s->length();
+ // all scripts are likely to have the nonce, thus scan only first 10
+ if (source_length > 10)
+ source_length = 10;
+ for (unsigned i = 0; i < source_length; ++i) {
+ Element* element = s->item(i);
+ const AtomicString& nonce = element->nonce();
+ if ((nonce != g_null_atom) && !nonce.empty())
+ return nonce;
+ }
+ return g_null_atom;
+}
+
void Document::FinishedParsing() {
DCHECK(!GetScriptableDocumentParser() || !parser_->IsParsing());
DCHECK(!GetScriptableDocumentParser() || ready_state_ != kLoading);
@@ -7506,6 +7567,9 @@ void Document::FinishedParsing() {
}
frame->Loader().FinishedParsing();
+ if (!IsPrefetchOnly()) {
+ injectScripts();
+ }
}
// Schedule dropping of the ElementDataCache. We keep it alive for a while
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -2076,6 +2076,9 @@ class CORE_EXPORT Document : public ContainerNode,
void AXContextModeChanged();
void ClearAXObjectCache();
+ void injectScripts();
+ const AtomicString& findFirstScriptNonce();
+
bool IsDocumentFragment() const =
delete; // This will catch anyone doing an unnecessary check.
bool IsDocumentNode() const =
diff --git a/third_party/blink/renderer/core/dom/extensions/anti_amp_cure.h b/third_party/blink/renderer/core/dom/extensions/anti_amp_cure.h
new file mode 100644
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/extensions/anti_amp_cure.h
@@ -0,0 +1,6 @@
+#ifndef anti_amp_cure_h
+#define anti_amp_cure_h
+
+#define ANTI_AMP_CURE_JS "/* Array of bytes to base64 string decoding */\n/* */\nfunction b64ToUint6(nChr) {\n return nChr > 64 && nChr < 91 ?\n nChr - 65 :\n nChr > 96 && nChr < 123 ?\n nChr - 71 :\n nChr > 47 && nChr < 58 ?\n nChr + 4 :\n nChr === 43 ?\n 62 :\n nChr === 47 ?\n 63 :\n 0;\n}\n\n/* returns an Uint8Array with decoded bytes */\n/* from https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Appendix.3A_Decode_a_Base64_string_to_Uint8Array_or_ArrayBuffer */\nfunction base64DecToArr(sBase64, nBlockSize) {\n var\n // URL encoding variant\n sB64Enc = sBase64.replace('-', '+').replace('_', '/'),\n nInLen = sB64Enc.length,\n nOutLen = nBlockSize ? Math.ceil((nInLen * 3 + 1 >>> 2) / nBlockSize) * nBlockSize : nInLen * 3 + 1 >>> 2,\n aBytes = new Uint8Array(nOutLen);\n\n for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {\n nMod4 = nInIdx & 3;\n nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;\n if (nMod4 === 3 || nInLen - nInIdx === 1) {\n for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {\n aBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;\n }\n nUint24 = 0;\n }\n }\n\n return aBytes;\n}\n\nconst antiAMPPolicy = trustedTypes.createPolicy(\"antiAMP\", {\n createHTML: (s) => s\n});\n\n\nfunction replaceHyperlink(a, url) {\n // create new A element - old one has event listeners attached\n var newA = document.createElement('a');\n newA.referrerPolicy = 'no-referrer';\n // property set when hyperlink has been created by this script\n newA.sane = true;\n newA.href = url;\n // copy CSS classes - news have only one\n newA.className = a.className;\n // scan child nodes for SVGs\n // news nodes will only have a text node\n a.childNodes.forEach(function(n) {\n // remove icon from image result buttons\n if (n.nodeName == 'DIV') {\n var svgs = n.querySelectorAll('div svg');\n if (svgs.length == 2)\n svgs[1].parentNode.removeChild(svgs[1]);\n }\n });\n // use direct HTML as appending nodes skips some e.g. heading\n newA.innerHTML = antiAMPPolicy.createHTML(a.innerHTML);\n // replace hyperlink\n a.parentNode.replaceChild(newA, a);\n return newA;\n}\n\nfunction getURLFromJsData(jsdata) {\n if (!jsdata) return;\n\n var res = jsdata.split(';');\n if (res.length < 3) return;\n // decode the payload\n var data = base64DecToArr(res[1]);\n // 08 = field 1, type Variant\n if (data[0] != 0x08)\n return;\n // 13 = 19 (raw) or -10 (zigzag)\n if (data[1] != 0x13) {\n console.warn('could not decode:', res[1]);\n return;\n }\n // 22 = field 4, type String\n if (data[2] != 0x22)\n return;\n // usually 2 bytes varint e.g. 88-01 = length 136\n res = proto_read_uint32(data, 3);\n // extract slice with the URL\n var url = new TextDecoder().decode(data.slice(res.pos, res.pos + res.value));\n console.log('decoded proto URL:', url);\n return url;\n}\n\nfunction recreateNewsHyperlink(a) {\n var article = a.parentNode;\n if (!article) return false;\n // grab jsdata from parent\n var url = getURLFromJsData(article.getAttribute('jsdata'));\n // use the AMP (but external) URL as fallback\n var obfuscated = false;\n if (!url) {\n url = a.href;\n obfuscated = true;\n }\n\n // ready to replace the hyperlink\n var newA = replaceHyperlink(a, url);\n if (obfuscated)\n newA.setAttribute(\"_target\", \"blank\");\n\n // replace headline hyperlink\n var h4a = article.querySelector('h4 a');\n if (h4a) {\n var newH4a = replaceHyperlink(h4a, url);\n if (obfuscated)\n newH4a.setAttribute(\"_target\", \"blank\");\n }\n\n // remove icon b
+
+#endif // anti_amp_cure_h
diff --git a/third_party/blink/renderer/core/dom/extensions/video_bg_play.h b/third_party/blink/renderer/core/dom/extensions/video_bg_play.h
new file mode 100644
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/extensions/video_bg_play.h
@@ -0,0 +1,6 @@
+#ifndef video_bg_play_h
+#define video_bg_play_h
+
+#define VIDEO_BG_PLAY_JS "'use strict';\n\nconst IS_YOUTUBE = window.location.hostname.search(/(?:^|.+\\.)youtube.com/) > -1 ||\n window.location.hostname.search(/(?:^|.+\\.)youtube-nocookie.com/) > -1;\nconst IS_MOBILE_YOUTUBE = window.location.hostname == 'm.youtube.com';\nconst IS_VIMEO = window.location.hostname.search(/(?:^|.+\\.)vimeo.com/) > -1;\n\n/* video background play fix - based on https://github.com/mozilla/video-bg-play */\ndocument.wrappedJSObject = {};\n\n// Page Visibility API\nObject.defineProperties(document.wrappedJSObject,\n { 'hidden': {value: false}, 'visibilityState': {value: 'visible'} });\n\nwindow.addEventListener(\n 'visibilitychange', evt => evt.stopImmediatePropagation(), true);\n\n// Fullscreen API\nif (IS_VIMEO) {\n window.addEventListener(\n 'fullscreenchange', evt => evt.stopImmediatePropagation(), true);\n}\n\nfunction activityRefresh() {\n var baseDelay = 3000;\n if (!this.firstRun) {\n if (window.hasOwnProperty('ytcfg')) {\n var cfg = window.ytcfg.get(\"EXPERIMENT_FLAGS\");\n cfg.kevlar_sign_in_prompt_before_mandatory_consent = false;\n window.ytcfg.set(\"EXPERIMENT_FLAGS\", cfg);\n this.firstRun = false;\n } else {\n baseDelay = 200;\n }\n }\n if (window.hasOwnProperty('_lact')) {\n window._lact = Date.now();\n }\n window.setTimeout(activityRefresh, baseDelay + Math.round(Math.random()*baseDelay*3));\n}\n\n// User activity tracking\nif (IS_YOUTUBE) {\n window.setTimeout(activityRefresh, 200 + Math.round(Math.random()*400));\n}\n"
+
+#endif // video_bg_play_h
diff --git a/third_party/blink/renderer/core/html/html_script_element.cc b/third_party/blink/renderer/core/html/html_script_element.cc
--- a/third_party/blink/renderer/core/html/html_script_element.cc
+++ b/third_party/blink/renderer/core/html/html_script_element.cc
@@ -182,6 +182,11 @@ void HTMLScriptElement::setTextContent(const String& string) {
Node::setTextContent(string);
}
+void HTMLScriptElement::setTextDirect(
+ const char *s) {
+ Node::setTextContent(s);
+}
+
void HTMLScriptElement::setAsync(bool async) {
// https://html.spec.whatwg.org/multipage/scripting.html#dom-script-async
SetBooleanAttribute(html_names::kAsyncAttr, async);
diff --git a/third_party/blink/renderer/core/html/html_script_element.h b/third_party/blink/renderer/core/html/html_script_element.h
--- a/third_party/blink/renderer/core/html/html_script_element.h
+++ b/third_party/blink/renderer/core/html/html_script_element.h
@@ -60,6 +60,7 @@ class CORE_EXPORT HTMLScriptElement final : public HTMLElement,
void setTextContentForBinding(const V8UnionStringOrTrustedScript* value,
ExceptionState& exception_state) override;
void setTextContent(const String&) override;
+ void setTextDirect(const char*);
void setAsync(bool);
bool async() const;
--
2.25.1