| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /** |
| * @fileoverview Defines the ScriptInstaller functions which install scripts |
| * into the web page (not a content script) |
| * |
| */ |
| |
| goog.provide('ScriptInstaller'); |
| |
| |
| /** |
| * URL pattern where we do not allow script installation. |
| * @type {RegExp} |
| */ |
| ScriptInstaller.denylistPattern = /chrome:\/\/|chrome-extension:\/\//; |
| |
| /** |
| * Installs a script in the web page. |
| * @param {Array<string>} srcs An array of URLs of scripts. |
| * @param {string} uid A unique id. This function won't install the same set of |
| * scripts twice. |
| * @param {function()=} opt_onload A function called when the last script |
| * has loaded. |
| * @param {string=} opt_chromevoxScriptBase An optional chromevoxScriptBase |
| * attribute to add. |
| * @return {boolean} False if the script already existed and this function |
| * didn't do anything. |
| */ |
| ScriptInstaller.installScript = function( |
| srcs, uid, opt_onload, opt_chromevoxScriptBase) { |
| if (ScriptInstaller.denylistPattern.test(document.URL)) { |
| return false; |
| } |
| if (document.querySelector('script[' + uid + ']')) { |
| ScriptInstaller.uninstallScript(uid); |
| } |
| if (!srcs || srcs.length === 0) { |
| return false; |
| } |
| |
| ScriptInstaller.installScriptHelper_( |
| srcs, uid, opt_onload, opt_chromevoxScriptBase); |
| return true; |
| }; |
| |
| /** |
| * Uninstalls a script. |
| * @param {string} uid Id of the script node. |
| */ |
| ScriptInstaller.uninstallScript = function(uid) { |
| let scriptNode; |
| if (scriptNode = document.querySelector('script[' + uid + ']')) { |
| scriptNode.remove(); |
| } |
| }; |
| |
| /** |
| * Helper that installs one script and calls itself recursively when each |
| * script loads. |
| * @param {Array<string>} srcs An array of URLs of scripts. |
| * @param {string} uid A unique id. This function won't install the same set of |
| * scripts twice. |
| * @param {function()=} opt_onload A function called when the |
| * last script has loaded. |
| * @param {string=} opt_chromevoxScriptBase An optional chromevoxScriptBase |
| * attribute to add. |
| * @private |
| */ |
| ScriptInstaller.installScriptHelper_ = function( |
| srcs, uid, opt_onload, opt_chromevoxScriptBase) { |
| function next() { |
| if (srcs.length > 0) { |
| ScriptInstaller.installScriptHelper_( |
| srcs, uid, opt_onload, opt_chromevoxScriptBase); |
| } else if (opt_onload) { |
| opt_onload(); |
| } |
| } |
| |
| const scriptSrc = srcs.shift(); |
| if (!scriptSrc) { |
| next(); |
| return; |
| } |
| |
| const xhr = new XMLHttpRequest(); |
| const url = scriptSrc + '?' + new Date().getTime(); |
| xhr.onreadystatechange = function() { |
| if (xhr.readyState === 4) { |
| const scriptText = xhr.responseText; |
| const apiScript = document.createElement('script'); |
| apiScript.type = 'text/javascript'; |
| apiScript.setAttribute(uid, '1'); |
| apiScript.textContent = scriptText; |
| if (opt_chromevoxScriptBase) { |
| apiScript.setAttribute('chromevoxScriptBase', opt_chromevoxScriptBase); |
| } |
| const scriptOwner = document.head || document.body; |
| scriptOwner.appendChild(apiScript); |
| next(); |
| } |
| }; |
| |
| try { |
| xhr.open('GET', url, true); |
| xhr.send(null); |
| } catch (exception) { |
| console.log( |
| 'Warning: ChromeVox external script loading for ' + document.location + |
| ' stopped after failing to install ' + scriptSrc); |
| next(); |
| } |
| }; |