chrome扩展在其他js之前在顶部注入javascript [英] chrome extension inject javascript at top of head before any other js

查看:159
本文介绍了chrome扩展在其他js之前在顶部注入javascript的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要做什么



使用Chrome扩展我需要在页面上下文中注入一个脚本,使注入的脚本在任何页面上的其他javascript。



为什么我需要这个?



我需要为特定页面劫持所有 console 命令,以便我的扩展程序可以侦听这些消息。



我当前的问题



目前我正在捕获页面记录的一些消息,但并不是所有消息,特别是来自 web-directory-132a3f16cf1ea31e167fdf5294387073.js的所有消息没有被捕获。经过一番挖掘,我发现 web-directory-132a3f16cf1ea31e167fdf5294387073.js 也是劫持控制台但是在之前我的脚本有机会。



作为一个可视化,如果我在加载页面后查看网络标签,我看到这个:



我的注入脚本是 consoleInterceptor.js 。它正确地捕获了在这里加载的js文件的输出接受 web-directory-132a3f16cf1ea31e167fdf5294387073.js



里面 web-directory-132a3f16cf1ea31e167fdf5294387073.js 有些代码是这样的:

  .... 
_originalLogger:t.default.Logger,
...
//做日志记录....
this._originalLogger [e]。 apply(this._originalLogger,s),



我认为问题是



在我看来, web-directory-132a3f16cf1ea31e167fdf5294387073.js 抓住了标准控制台函数并在内部将它们存储在之前我的脚本有机会用我自己的版本替换它们。因此,即使我的脚本工作, web-directory-132a3f16cf1ea31e167fdf5294387073.js 仍然使用它保存的原始标准控制台功能。



请注意, web-directory-132a3f16cf1ea31e167fdf5294387073.js 是一个应用程序应用程序,我没有看到任何简单的方法来钩入代码以覆盖这些功能,但我打开作为解决方案。



我目前的代码:



manifest.js

  ... 
web_accessible_resources:[
js / ajaxInterceptor.js,
js / consoleInterceptor.js
],
version:5.2,
manifest_version:2,
permissions:[
< all_urls>,
tabs,
activeTab,
storage,
webNavigation,
unlimitedStorage,
通知,
clipboardWrite,
下载,
tabCapture,
cookies,
浏览数据,
webRequest,
*:// * / *,
gcm,
contextMenus,
management
],
externally_connectable:{
matches:[*://apps.mypurecloud.com/*,*://*.cloudfront.net/*]
},
...

background.js

  var options = {url:[{hostContains:'apps.mypurecloud.com'}]}; 
chrome.webNavigation.onCommitted.addListener(function(details){
//首先注入chrome扩展的id
chrome.tabs.executeScript(details.tabId,{
code: var chromeExtensionId =+ JSON.stringify(chrome.runtime.id)
});
//然后注入将使用动态添加的扩展ID
//的脚本进行交谈扩展
chrome.tabs.executeScript(details.tabId,{
file:'js / injectConsoleInterceptor.js'
});
},
options
);
chrome.runtime.onMessageExternal.addListener(
函数(msg,sender,sendResponse){
if(msg.action ==='console_intercepted'){
_this.processConsoleMessage发件人,msg.details.method,msg.details.arguments);

}
});

injectConsoleInterceptor.js

  var interceptorScript = document.createElement('script'); 
interceptorScript.src = chrome.extension.getURL('js / consoleInterceptor.js');
interceptorScript.onload = function(){this.remove();};
(document.head || document.documentElement).prepend(interceptorScript);

consoleInterceptor.js

  if(!window.hasConsoleInterceptor){
window.hasConsoleInterceptor = true;
console.log('覆盖控制台函数');
var originals = {};
var console = window.console;
if(console){
function interceptConsoleMethod(method){
originals [method] = console [method];
console [method] = function(){
//将数据发送给扩展
// chromeExtensionId应单独注入页面并在此脚本之前注入
var data = {
action:'console_intercepted',
details:{
method:method,
arguments:arguments
}
};
chrome.runtime.sendMessage(chromeExtensionId,data);
originals [方法] .apply(控制台,参数)
}
}
//我们要观察的方法数组
var methods = ['assert ','count','debug','dir','dirxml','error','group','groupCollapsed','groupEnd','info','log','profile','profileEnd', '时间', 'timeEnd', '时间戳', '跟踪', '警告', '表'];
for(var i = 0; i< methods.length; i ++){
interceptConsoleMethod(methods [i])
}
console.log('成功覆盖控制台函数:'+ methods.join(','));


$ / code $ / pre
$ b $ h我的问题

web-directory-132a3f16cf1ea31e167fdf5294387073.js 之前运行 consoleInterceptor.js 加载使得 web-directory-132a3f16cf1ea31e167fdf5294387073.js 使用我修改后的控制台功能而不是默认的浏览器控制台功能?


在manifest.json文件中:

 

content_scripts:[
{
matches:[http:// * / *,https:// * / *],
js:[script / inject.js],
run_at:document_start
}
]

在inject.js中:

  VA r ss = document.createElement(script); ss.innerHTML =xxx; document.documentElement.appendChild(ss);  


What I want to do.

Using a Chrome extension I need to inject a script into the page context in such a way that the injected script runs before any other javascript on the page.

Why do I need this?

I need to hijack all console commands for a specific page so my extension can listen to the messages.

My current issue

Currently I am catching some of the messages logged by the page but not all of them, specifically, all messages from web-directory-132a3f16cf1ea31e167fdf5294387073.js are not being caught. After some digging I discovered that the web-directory-132a3f16cf1ea31e167fdf5294387073.js is also hijacking console but doing so before my script has a chance to.

As a visual, if I look at the network tab after loading the page, I see this:

My injected script is consoleInterceptor.js. It correctly captures the output of the js files that are loaded here accept web-directory-132a3f16cf1ea31e167fdf5294387073.js

Inside of web-directory-132a3f16cf1ea31e167fdf5294387073.js is some code something like this:

   ....
    _originalLogger: t.default.Logger,
   ...
    // do stuff with logging ....
    this._originalLogger[e].apply(this._originalLogger, s),

What I think the problem is

It seems to me that, web-directory-132a3f16cf1ea31e167fdf5294387073.js is grabbing the standard console functions and storing them internally before my script has had a chance to replace them with my own versions. So even though my script works, the web-directory-132a3f16cf1ea31e167fdf5294387073.js still uses the original standard console functions it saved.

Note that web-directory-132a3f16cf1ea31e167fdf5294387073.js is an ember application and I dont see any simple way to hook into that code to overwrite those functions too but Im open to that as a solution.

My current code:

manifest.js

  ...
  "web_accessible_resources": [
    "js/ajaxInterceptor.js",
    "js/consoleInterceptor.js"
  ],
  "version" : "5.2",
  "manifest_version": 2,
  "permissions": [
    "<all_urls>",
    "tabs",
    "activeTab",
    "storage",
    "webNavigation",
    "unlimitedStorage",
    "notifications",
    "clipboardWrite",
    "downloads",
    "tabCapture",
    "cookies",
    "browsingData",
    "webRequest",
    "*://*/*",
    "gcm",
    "contextMenus",
    "management"
  ],
  "externally_connectable": {
    "matches": ["*://apps.mypurecloud.com/*","*://*.cloudfront.net/*"]
  },
  ...

background.js

var options = {url: [{hostContains: 'apps.mypurecloud.com'}]};
chrome.webNavigation.onCommitted.addListener(function(details) {
        // first inject the chrome extension's id
        chrome.tabs.executeScript(details.tabId, {
            code: "var chromeExtensionId = " + JSON.stringify(chrome.runtime.id)
        });
        // then inject the script which will use the dynamically added extension id
        // to talk to the extension
        chrome.tabs.executeScript(details.tabId, {
            file: 'js/injectConsoleInterceptor.js'
        });
    },
    options
);
chrome.runtime.onMessageExternal.addListener(
    function(msg, sender, sendResponse) {
        if(msg.action === 'console_intercepted'){
            _this.processConsoleMessage(sender, msg.details.method, msg.details.arguments);

        }
    });

injectConsoleInterceptor.js

var interceptorScript = document.createElement('script');
interceptorScript.src = chrome.extension.getURL('js/consoleInterceptor.js');
interceptorScript.onload = function(){this.remove();};
(document.head || document.documentElement).prepend(interceptorScript);

consoleInterceptor.js

if(!window.hasConsoleInterceptor){
    window.hasConsoleInterceptor = true;
    console.log('overriding console functions');
    var originals ={};
    var console = window.console;
    if (console){
        function interceptConsoleMethod(method){
            originals[method] = console[method];
            console[method] = function(){
                // send the data to the extension
                // chromeExtensionId should be injected into the page separately and before this script
                var data = {
                    action: 'console_intercepted',
                    details: {
                        method: method,
                        arguments: arguments
                    }
                };
                chrome.runtime.sendMessage(chromeExtensionId, data);
                originals[method].apply(console, arguments)
            }
        }
        // an array of the methods we want to observe 
        var methods = ['assert', 'count', 'debug', 'dir', 'dirxml', 'error', 'group','groupCollapsed','groupEnd','info','log', 'profile', 'profileEnd','time','timeEnd','timeStamp','trace','warn','table'];
        for (var i = 0; i < methods.length; i++){
            interceptConsoleMethod(methods[i])
        }
        console.log('Successfully overridden console functions: '+methods.join(','));
    }
}

My question

What can I do to make consoleInterceptor.js run before web-directory-132a3f16cf1ea31e167fdf5294387073.js loads so that web-directory-132a3f16cf1ea31e167fdf5294387073.js uses my modified console functions rather than the default browser console funcitons?

解决方案

You can try this.

In manifest.json file:


    "content_scripts": [
            {
              "matches": ["http://*/*", "https://*/*"],
              "js": ["script/inject.js"],
              "run_at":"document_start"
            }
        ]

In inject.js:

var ss = document.createElement("script");
ss.innerHTML= "xxx";
document.documentElement.appendChild(ss);

这篇关于chrome扩展在其他js之前在顶部注入javascript的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆