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


我可以允许我的扩展程序的域匹配是用户可配置的吗? 我想让我的用户在扩展程序运行时选择。


5310
2017-09-14 23:36


起源



答案:


要为内容脚本实现可自定义的“匹配模式”,内容脚本需要使用后台页面执行 chrome.tabs.executeScript 方法(使用后检测页面加载后) chrome.tabs.onUpdated 事件监听器)。

由于匹配模式检查未在任何API中公开,因此您必须自己创建该方法。它是在实施的 url_pattern.cc,规格可在 匹配模式

这是一个解析器的例子:

/**
  * @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;
}

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

在下面的示例中,阵列是硬编码的。实际上,您可以使用匹配模式将匹配模式存储在数组中 localStorage 要么 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
            });
        }
    }
});

要使其工作,您需要请求以下内容 清单文件中的权限

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

固定的权限列表

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


12
2017-09-15 11:07



哇,谢谢你提供了一个非常完整的答案! - Martin
@Rob W;有一个 match parse_match_pattern函数中的数组,但它看起来未定义。我试图得到这意味着什么,但我找不到。究竟什么是'匹配'数组? - Yasin Okumuş
@YasinOkumus感谢你提出来。这是一个错误,我应该称之为 result。 - Rob W
谢谢你,现在就明白了 - Yasin Okumuş
+1很棒的答案。我想知道是否有办法在内容脚本中为用户定义的列表应用Chrome匹配? stackoverflow.com/questions/28930209/... - user2381114


答案:


要为内容脚本实现可自定义的“匹配模式”,内容脚本需要使用后台页面执行 chrome.tabs.executeScript 方法(使用后检测页面加载后) chrome.tabs.onUpdated 事件监听器)。

由于匹配模式检查未在任何API中公开,因此您必须自己创建该方法。它是在实施的 url_pattern.cc,规格可在 匹配模式

这是一个解析器的例子:

/**
  * @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;
}

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

在下面的示例中,阵列是硬编码的。实际上,您可以使用匹配模式将匹配模式存储在数组中 localStorage 要么 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
            });
        }
    }
});

要使其工作,您需要请求以下内容 清单文件中的权限

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

固定的权限列表

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


12
2017-09-15 11:07



哇,谢谢你提供了一个非常完整的答案! - Martin
@Rob W;有一个 match parse_match_pattern函数中的数组,但它看起来未定义。我试图得到这意味着什么,但我找不到。究竟什么是'匹配'数组? - Yasin Okumuş
@YasinOkumus感谢你提出来。这是一个错误,我应该称之为 result。 - Rob W
谢谢你,现在就明白了 - Yasin Okumuş
+1很棒的答案。我想知道是否有办法在内容脚本中为用户定义的列表应用Chrome匹配? stackoverflow.com/questions/28930209/... - user2381114