简体   繁体   English

用于修改页面脚本的 Chrome 扩展包括和 JS

[英]Chrome extension to modify page's script includes and JS

I work on a javascript library that customers include on their site to embed a UI widget.我在 javascript 图书馆工作,客户在他们的网站上包含该图书馆以嵌入 UI 小部件。 I want a way to test dev versions of the library live on the customer's site without requiring them to make any changes to their code.我想要一种方法来测试客户站点上的库的开发版本,而不需要他们对其代码进行任何更改。 This would make it easy to debug issues and test new versions.这将使调试问题和测试新版本变得容易。

To do this I need to change the script include to point to my dev server, and then override the load() method that's called in the page to add an extra parameter to tell it what server to point to when making remote calls.为此,我需要更改脚本包含以指向我的开发服务器,然后覆盖在页面中调用的 load() 方法以添加一个额外的参数来告诉它在进行远程调用时要指向哪个服务器。

It looks like I can add JS to the page using a chrome extension, but I don't see any way to modify the page before it's loaded.看起来我可以使用 chrome 扩展程序将 JS 添加到页面,但我看不到在加载页面之前修改页面的任何方法。 Is there something I'm missing, or are chrome extensions not allowed to do this kind of thing?有没有我遗漏的东西,或者不允许 chrome 扩展做这种事情?

I've done a fair amount of Chrome extension development, and I don't think there's any way to edit a page source before it's rendered by the browser.我已经完成了大量的 Chrome 扩展开发,我认为没有任何方法可以在浏览器呈现页面源之前对其进行编辑。 The two closest options are:最接近的两个选项是:

  • Content scripts allow you to toss in extra JavaScript and CSS files. 内容脚本允许您放入额外的 JavaScript 和 CSS 文件。 You might be able to use these scripts to rewrite existing script tags in the page, but I'm not sure it would work out, since any script tags visible to your script through the DOM are already loaded or are being loaded.您也许可以使用这些脚本来重写页面中现有的脚本标签,但我不确定它是否可行,因为您的脚本通过 DOM 可见的任何脚本标签都已经加载或正在加载。

  • WebRequest allows you to hijack HTTP requests, so you could have an extension reroute a request for library.js to library_dev.js .WebRequest允许您劫持 HTTP 请求,因此您可以使用扩展将对library.js的请求重新路由到library_dev.js

Assuming your site is www.mysite.com and you keep your scripts in the /js directory:假设您的站点是 www.mysite.com 并且您将脚本保存在 /js 目录中:

chrome.webRequest.onBeforeRequest.addListener(
    function(details) {
        if( details.url == "http://www.mysite.com/js/library.js" )
            return {redirectUrl: "http://www.mysite.com/js/library_dev.js" };
    },
    {urls: ["*://www.mysite.com/*.js"]},
    ["blocking"]);

The HTML source will look the same, but the document pulled in by <script src="library.js"></script> will now be a different file. HTML 源看起来是一样的,但是<script src="library.js"></script>拉入的文档现在将是一个不同的文件。 This should achieve what you want.这应该实现你想要的。

Here's a way to modify content before it is loaded on the page using the WebRequest API. This requires the content to be loaded into a string variable before the onBeforeRequest listener returns.这是一种在使用WebRequest API 将内容加载到页面之前修改内容的方法。这需要在 onBeforeRequest 侦听器返回之前将内容加载到字符串变量中。 This example is for javascript, but it should work equally well for other types of content.此示例适用于 javascript,但它应该同样适用于其他类型的内容。

chrome.webRequest.onBeforeRequest.addListener(
    function (details) {
        var javascriptCode = loadSynchronously(details.url);
        // modify javascriptCode here
        return { redirectUrl: "data:text/javascript," 
                             + encodeURIComponent(javascriptCode) };
    },
    { urls: ["*://*.example.com/*.js"] },
    ["blocking"]);

loadSynchronously() can be implemented with a regular XMLHttpRequest. Synchronous loading will block the event loop and isdeprecated in XMLHttpRequest, but it is unfortunately hard to avoid with this solution. loadSynchronously() 可以通过常规 XMLHttpRequest 实现。同步加载会阻塞事件循环,在 XMLHttpRequest 中已弃用,但不幸的是,这种解决方案很难避免。

You might be interested in the hooks available in the Opera browser.您可能对 Opera 浏览器中可用的挂钩感兴趣。 Opera used to have* very powerful hooks , available both to User JavaScript files (single-file things, very easy to write and deploy) and Extensions. Opera 曾经有*非常强大的钩子,可用于用户 JavaScript 文件(单文件的东西,非常容易编写和部署)和扩展。 Some of these are:其中一些是:

BeforeExternalScript:在外部脚本之前:

This event is fired when a script element with a src attribute is encountered.当遇到具有 src 属性的脚本元素时会触发此事件。 You may examine the element, including its src attribute, change it, add more specific event listeners to it, or cancel its loading altogether.您可以检查该元素,包括它的 src 属性,更改它,向它添加更多特定的事件侦听器,或者完全取消它的加载。

One nice trick is to cancel its loading, load the external script in an AJAX call, perform text replacement on it, and then re-inject it into the webpage as a script tag, or using eval.一个不错的技巧是取消它的加载,在 AJAX 调用中加载外部脚本,对其执行文本替换,然后将其作为脚本标签或使用 eval 重新注入网页。

window.opera.defineMagicVariable: window.opera.defineMagicVariable:

This method can be used by User JavaScripts to override global variables defined by regular scripts.用户 JavaScript 可以使用此方法来覆盖由常规脚本定义的全局变量。 Any reference to the global name being overridden will call the provided getter and setter functions.对被覆盖的全局名称的任何引用都将调用提供的 getter 和 setter 函数。

window.opera.defineMagicFunction: window.opera.defineMagicFunction:

This method can be used by User JavaScripts to override global functions defined by regular scripts.用户 JavaScript 可以使用此方法来覆盖常规脚本定义的全局函数。 Any invocation of the global name being overridden will call the provided implementation.对被覆盖的全局名称的任何调用都将调用提供的实现。


*: Opera recently switched over to the Webkit engine, and it seems they have removed some of these hooks. *: Opera 最近切换到 Webkit 引擎,他们似乎已经删除了其中的一些钩子。 You can still find Opera 12 for download on their website, though.不过,您仍然可以在他们的网站上找到可供下载的 Opera 12。

When It comes to changing the page content (Be it HTML content or Scripts), Chrome extensions have technical constraints.在更改页面内容时(无论是 HTML 内容还是脚本),Chrome 扩展程序都有技术限制。 The easiest way to solve this problem would be to intercept the HTML and allow the developer to override the HTML/JS response content pragmatically.解决这个问题最简单的方法是拦截 HTML 并允许开发人员实用地覆盖 HTML/JS 响应内容。

This is possible through Requestly Desktop App这可以通过Requestly 桌面应用程序实现

Using Requestly Desktop App使用 Requestly 桌面应用程序

  1. Install Requestly Desktop App安装 Requestly 桌面应用程序
  2. Open Connected Apps and Launch any browser - Chrome, Firefox, etc打开连接的应用程序并启动任何浏览器 - Chrome、Firefox 等
  3. Go to HTTP Rules and Create a New Modify Response Rule Go 到 HTTP 规则并新建修改响应规则

Choose to override the content Programatically for your HTML Page .选择以编程方式覆盖您的 HTML 页面的内容 Write a simple JS script to do your modifications on top of the existing HTML/JS response.编写一个简单的 JS 脚本以在现有 HTML/JS 响应之上进行修改。

Here is a sample screenshot of how you can do it.这是您如何操作的示例屏幕截图。 请求修改响应规则

Using Requestly Chrome Extension使用 Requestly Chrome 扩展程序

If Redirecting a script URL and Inserting a new Script suffices your use case then you can also use Requestly Chrome Extension and create two rules如果重定向脚本 URL 和插入新脚本满足您的用例,那么您还可以使用 Requestly Chrome Extension 并创建两个规则

  1. Redirect Rule - Redirect Production Script with Dev scripts重定向规则- 使用开发脚本重定向生产脚本
  2. Insert Script Rule - Inject Scripts on Page插入脚本规则- 在页面上插入脚本

Disclaimer - I built Requestly.免责声明 - 我是按要求建造的。

I had an idea, but I didn't try it, but it worked in theory.我有一个想法,但我没有尝试,但它在理论上是可行的。

Run content_script that was executed before the document was loaded, and register a ServiceWorker to replace page's requested file content in real time.运行文档加载前执行的content_script,注册一个ServiceWorker,实时替换页面请求的文件内容。 (ServiceWorker can intercept all requests in the page, including those initiated directly through the dom) (ServiceWorker可以拦截页面中的所有请求,包括直接通过dom发起的请求)

Chrome extension (manifest v3) allow us to add rules for declarativeNetRequest : Chrome 扩展(清单 v3)允许我们为declarativeNetRequest添加规则:

chrome.declarativeNetRequest.updateDynamicRules({
    addRules: [
        {
            "id": 1002,
            "priority": 1,
            "action": { 
                "type": "redirect", 
                "redirect": { 
                    "url": "https://example.com/script.js" 
                } 
            },
            "condition": {
                "urlFilter": 'https://www.replaceme.com/js/some_script_to_replace.js',
                "resourceTypes": [
                    'csp_report',
                    'font',
                    'image',
                    'main_frame',
                    'media',
                    'object',
                    'other',
                    'ping',
                    'script',
                    'stylesheet',
                    'sub_frame',
                    'webbundle',
                    'websocket',
                    'webtransport',
                    'xmlhttprequest'
                ]

            }
        },
    ],
    removeRuleIds: [1002]

});

and debug it by adding listener:并通过添加侦听器对其进行调试:

chrome.declarativeNetRequest.onRuleMatchedDebug.addListener(
    c => console.log('onRuleMatchedDebug', c)
)

It's not a Chrome extension, but Fiddler can change the script to point to your development server (see this answer for setup instructions from the author of Fiddler).它不是 Chrome 扩展,但 Fiddler 可以更改脚本以指向您的开发服务器(有关 Fiddler 作者的设置说明,请参阅此答案)。 Also, with Fiddler you can setup a search and replace to add that extra parameter that you need.此外,使用 Fiddler,您可以设置搜索和替换以添加您需要的额外参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM