且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

我可以允许分机用户选择匹配的网域吗?

更新时间:2023-10-28 11:22:04

要实现可自定义的匹配模式对于内容脚本,内容脚本需要在后台页面中使用 chrome.tabs.executeScript 方法(使用 chrome.tabs.onUpdated 事件监听器)。



因为匹配模式检查没有公开在任何API中,您都必须自己创建方法。它在 url_pattern.cc ,该规范可在匹配模式中找到。



下面是一个解析器的例子:

  * @param字符串输入匹配模式
*如果输入无效,则返回null
* @returns要传递给RegExp构造函数的字符串* /
函数parse_match_pattern(输入){
if(typeof input!=='string')return null;
var match_pattern ='(?:^'
,regEscape = function(s){return s.replace(/ [[^ $。|?* +(){} \\] / g,'\\ $&');}
,result = / ^(\ * | https?| file | ftp | chrome-extension):\ / \ //。exec输入);

//解析方案
if(!result)返回null;
input = input.substr(result [0] .length);
match_pattern + = result [1] ==='*'?'https?://':result [1] +'://';

//如果scheme不是`file `
if(result [1]!=='file'){
if(!(result = /^(?:\*|(\*\.)?([^ \ / *] +))(?= \ /)/ .exec(input)))return null;
input = input.substr(result [0] .length);
if结果[0] ==='*'){//主机是'*'
match_pattern + ='[^ /] +';
} else {
if(result [1 ]){//子域通配符存在
match_pattern + ='(?:[^ /] + \\。)?';
}
//追加主机(转义特殊的正则表达式字符)
match_pattern + = regEscape(result [2]);

$ b $ //添加余数(路径)
match_pattern + = input.split('*')。map(regEscape).join('。*');
match_pattern + ='$)';
返回match_pattern;
}



示例:在匹配模式的页面上运行内容脚本



在下面的例子中,数组是硬编码的。实际上,您可以使用 localStorage chrome.storage

//示例:解析匹配模式列表:
var patterns = ['*: // * / *','* exampleofinvalid *','file:// *'];

//解析列表和过滤器(排除)无效匹配模式
var parsed = patterns.map(parse_match_pattern)
.filter(function(pattern){return pattern!==空值});
//创建用于验证的模式:
var pattern = new RegExp(parsed.join('|'));

//过滤示例:
chrome.tabs.onUpdated.addListener(function(tabId,changeInfo,tab){
if(changeInfo.status ==='complete' ){
var url = tab.url.split('#')[0]; //排除URL片段
if(pattern.test(url)){
chrome.tabs。 executeScript(tabId,{
file:'contentscript.js'
//或:code:'< JavaScript code here>'
//其他有效选项:allFrames,runAt
});
}
}
});

为了实现这个目标,您需要请求以下清单文件中的许可


  • tabs - 启用必要的标签 API。 < all_urls> - 能够使用 chrome.tabs.executeScript 在特定页面执行内容脚本。



固定权限列表



如果一组匹配模式是固定的(即用户不能定义新模式,只有切换模式),< all_urls>可以用这个替换一组权限。您甚至可以使用可选的权限来减少所请求权限的初始数量(在 chrome.permissions 的文档)。


Can I allow the domain matching for my extension to be user configurable? I'd like to let my users choose when the extension runs.

To implement customizable "match patterns" for content scripts, the Content script need to be executed in by the background page using the chrome.tabs.executeScript method (after detecting a page load using the chrome.tabs.onUpdated event listener).

Because the match pattern check is not exposed in any API, you have to create the method yourself. It is implemented in url_pattern.cc, and the specification is available at match patterns.

Here's an example of a parser:

/**
  * @param String input  A match pattern
  * @returns  null if input is invalid
  * @returns  String to be passed to the RegExp constructor */
function parse_match_pattern(input) {
    if (typeof input !== 'string') return null;
    var match_pattern = '(?:^'
      , regEscape = function(s) {return s.replace(/[[^$.|?*+(){}\\]/g, '\\$&');}
      , result = /^(\*|https?|file|ftp|chrome-extension):\/\//.exec(input);

    // Parse scheme
    if (!result) return null;
    input = input.substr(result[0].length);
    match_pattern += result[1] === '*' ? 'https?://' : result[1] + '://';

    // Parse host if scheme is not `file`
    if (result[1] !== 'file') {
        if (!(result = /^(?:\*|(\*\.)?([^\/*]+))(?=\/)/.exec(input))) return null;
        input = input.substr(result[0].length);
        if (result[0] === '*') {    // host is '*'
            match_pattern += '[^/]+';
        } else {
            if (result[1]) {         // Subdomain wildcard exists
                match_pattern += '(?:[^/]+\\.)?';
            }
            // Append host (escape special regex characters)
            match_pattern += regEscape(result[2]);
        }
    }
    // Add remainder (path)
    match_pattern += input.split('*').map(regEscape).join('.*');
    match_pattern += '$)';
    return match_pattern;
}

Example: Run content script on pages which match the pattern

In the example below, the array is hard-coded. In practice, you would store the match patterns in an array using localStorage or chrome.storage.

// Example: Parse a list of match patterns:
var patterns = ['*://*/*', '*exampleofinvalid*', 'file://*'];

// Parse list and filter(exclude) invalid match patterns
var parsed = patterns.map(parse_match_pattern)
                     .filter(function(pattern){return pattern !== null});
// Create pattern for validation:
var pattern = new RegExp(parsed.join('|'));

// Example of filtering:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo.status === 'complete') {
        var url = tab.url.split('#')[0]; // Exclude URL fragments
        if (pattern.test(url)) {
            chrome.tabs.executeScript(tabId, {
                file: 'contentscript.js'
                // or: code: '<JavaScript code here>'
                // Other valid options: allFrames, runAt
            });
        }
    }
});

To get this to work, you need to request the following permissions in the manifest file:

  • "tabs" - To enable the necessary tabs API.
  • "<all_urls>" - To be able to use chrome.tabs.executeScript to execute a content script in a specific page.

A fixed list of permissions

If the set of match patterns is fixed (ie. the user cannot define new ones, only toggle patterns), "<all_urls>" can be replaced with this set of permissions. You may even use optional permissions to reduce the initial number of requested permissions (clearly explained in the documentation of chrome.permissions).