• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

内容脚本 -百度浏览器应用开发文档

相关文章 搞java代码 2年前 (2023-03-11) 23次浏览 已收录 0个评论

内容脚本是在网页的上下文中运行的 JavaScript文件,它们可以通过标准的文档对象模型(DOM)来获取浏览器访问的网页详情,或者作出更改。

如下是内容脚本可以实现的一些功能的例子:

  • 在网页中找出未链接的URL,并将它们转换为超链接
  • 增加字体大小,使文本更具有可读性
  • 发现并处理 DOM 中的微格式数据

<!—ecms @However, content scripts have some limitations.They cannot:–>然而,内容脚本也有一些限制,它们不能

  • 调用 chrome.* API,除了以下 API:
  • 使用所属应用页面中定义的变量或函数
  • 使用网页或其他内容脚本中定义的变量或函数

<!—ecms @These limitations aren't as bad as they sound.Content scripts can indirectly use the chrome.* APIs,get access to extension data,and request extension actionsby exchanging messageswith their parent extension.Content scripts can alsomake cross-site XMLHttpRequeststo the same sites as their parent extensions,and they cancommunicate with web pagesusing the shared DOM.For more insight into what content scripts can and can’t do,learn about theexecution environment.–>这些限制并不如看上去那么糟糕,内容脚本可以间接地通过与所属应用交换消息的方式,来使用 chrome.*API、访问应用数据并请求应用完成操作。内容脚本也可以像所属应用一样向拥有主机权限的站点发出跨域 XMLHttpRequest,另外也可以使用共享的 DOM 与网页通信。有关内容脚本能做什么与不能做什么的更多内部细节,请参见执行环境。

清单文件

<!—ecms @If your content script's code should always be injected,register it in theextension manifestusing the content_scripts field,as in the following example.-->如果您的内容脚本代码每一次都需要插入到网页中,请在应用的清单文件中使用content_scripts 字段注册它,如以下例子所示:

{  "name": "我的应用",  ...  "content_scripts": [    {      "matches": ["http://www.google.com/*"],      "css": ["mystyles.css"],      "js": ["jquery.js", "myscript.js"]    }  ],  ...}

<!---ecms @If you want to inject the code only sometimes,use thepermissions field instead,as described in Programmatic injection.-->如果您只是有时需要插入代码,应该使用permissions字段,如以编程方式插入部分所述。

{  "name": "我的应用",  ...  "permissions": [    "tabs", "http://www.google.com/*"  ],  ...}

<!---ecms @Using the content_scripts field,an extension can insert multiple content scripts into a page;each of these content scripts can have multiple JavaScript and CSS files.Each item in the content_scripts arraycan have the following properties:-->使用 content_scripts字段,应用可以向一个页面中插入多个内容脚本,每个内容脚本可以有多个JavaScript 和 CSS 文件,content_scripts数组中的每一个项目可以包含如下属性:

名称 类型 描述
matches array of strings 必选。指定内容脚本要插入到哪些页面中去。有关这些字符串语法的更多细节请参见匹配表达式,有关如何排除 URL 的信息请参见匹配表达式和范围。
exclude_matches array of strings 可选。排除不需要插入内容脚本的页面。有关这些字符串语法的更多细节请参见匹配表达式,有关如何排除 URL 的信息请参见匹配表达式和范围。
match_about_blank boolean 可选。<!---ecms @ Whether to insert the content script on about:blank and about:srcdoc. Content scripts will only be injected on pages when their inherit URL is matched by one of the declared patterns in the matches field. The inherit URL is the URL of the document that created the frame or window.
Content scripts cannot be inserted in sandboxed frames.-->是否在 about:blank 和 about:srcdoc 中插入内容脚本,只有当继承 URL 匹配 matches 字段中声明的匹配表达式时才会插入内容脚本。继承 URL 为创建框架或窗口的文档 URL。
内容脚本不能在经过沙盒屏蔽的框架中插入。
默认为 false
css array of strings 可选。要插入匹配页面的 CSS 文件列表,它们将在页面的所有 DOM 构造或显示之前,按照数组中指定的顺序插入。
js array of strings 可选。要插入匹配页面的 JavaScript 文件列表,它们将按照数组中指定的顺序插入。
run_at string 可选。<!---ecms @ Controls when the files in js are injected. Can be "document_start", "document_end", or "document_idle". Defaults to "document_idle". -->控制 js 中的 JavaScript 文件何时插入,可以为 "document_start"、"document_end" 或 "document_idle",默认为 "document_idle"。
<!---ecms @In the case of "document_start", the files are injected after any files from css, but before any other DOM is constructed or any other script is run.--> 如果是 "document_start",这些文件将在 css 中指定的文件之后,但是在所有其他 DOM 构造或脚本运行之前插入。
如果是 "document_end",文件将在 DOM 完成之后立即插入,但是在加载子资源(如图像与框架)之前插入。
<!---ecms @In the case of "document_idle", the browser chooses a time to inject scripts between "document_end" and immediately after the window.onload event fires. The exact moment of injection depends on how complex the document is and how long it is taking to load, and is optimized for page load speed.--> 如果是 "document_idle",浏览器将在 "document_end" 和刚发生 window.onload 事件这两个时刻之间选择合适的时候插入,具体的插入时间取决于文档的复杂程度以及加载文档所花的时间,并且浏览器会尽可能地为加快页面加载速度而优化。
<!---ecms @Note: With "document_idle", content scripts may not necessarily receive the window.onload event, because they may run after it has already fired. In most cases, listening for the onload event is unnecessary for content scripts running at "document_idle" because they are guaranteed to run after the DOM is complete. If your script definitely needs to run after window.onload, you can check if onload has already fired by using the document.readyState property.--> 注意:如果使用 "document_idle",内容脚本不一定会收到 window.onload 事件,因为它们可能在这一事件已经发生后再执行。在大多数情况下,在 "document_idle" 时运行的内容脚本没有必要监听 onload 事件,因为它们保证在 DOM 完成后运行。如果您的脚本确实需要在 window.onload 之后运行,您可以检查 document.readyState 属性确定 onload 事件是否已经发生。
all_frames boolean 可选。控制内容脚本运行在匹配页面的所有框架中还是仅在顶层框架中。
<!---ecms @Defaults to false, meaning that only the top frame is matched.--> 默认为 false,意味着仅在顶层框架中运行。
include_globs array of string 可选。<!---ecms @ Applied after matches to include only those URLs that also match this glob. Intended to emulate the @include Greasemonkey keyword. See Match patterns and globs below for more details. -->在应用 matches 之后仅包含同时匹配这一范围的 URL。该属性是为了模拟 Greasemonkey 中的 @include 关键字,有关更多详情请参见下面的匹配表达式和范围。
exclude_globs array of string 可选。<!---ecms @ Applied after matches to exclude URLs that match this glob. Intended to emulate the @exclude Greasemonkey keyword. See Match patterns and globs below for more details. -->在应用 matches 之后排除匹配这一范围的 URL。该属性是为了模拟 Greasemonkey 中的 @exclude 关键字,有关更多详情请参见下面的匹配表达式和范围。

匹配表达式和范围

<!---ecms @The content script will be injected into a page if its URL matches any matches pattern and any include_globs pattern, as long as the URL doesn't also match an exclude_matches or exclude_globs pattern.Because the matches property is required, exclude_matches, include_globs, and exclude_globs can only be used to limit which pages will be affected.-->如果页面的 URL 匹配任何 matches 指定的表达式以及任何include_globs 指定的表达式,并且不匹配exclude_matches 和 exclude_globs指定的表达式,则会在页面中插入内容脚本。因为 matches属性是必需的,exclude_matches、include_globs和 exclude_globs 只能用来限制受到影响的页面。

<!---ecms @For example, assume matches is ["http://*.nytimes.com/*"]:-->例如,假设 matches 为 ["http://*.nytimes.com/*"]:

  • <!---ecms If exclude_matches is ["*://*/*business*"], then the content script would be injected into "http://www.nytimes.com/health" but not into "http://www.nytimes.com/business".-->如果 exclude_matches 为 ["*://*/*business*"],那么内容脚本会插入“http://www.nytimes.com/health”,但不会插入“http://www.nytimes.com/business”。
  • <!---ecms @If include_globs is ["*nytimes.com/???s/*"], then the content script would be injected into "http:/www.nytimes.com/arts/index.html" and "http://www.nytimes.com/jobs/index.html" but not into "http://www.nytimes.com/sports/index.html".-->如果 include_globs 为 ["*nytimes.com/???s/*"],那么内容脚本会插入“http://www.nytimes.com/arts/index.html”和“http://www.nytimes.com/jobs/index.html”,但不会插入“http://www.nytimes.com/sports/index.html”。
  • <!---ecms @If exclude_globs is ["*science*"], then the content script would be injected into "http://www.nytimes.com" but not into "http://science.nytimes.com" or "http://www.nytimes.com/science".-->如果 exclude_globs 为 ["*science*"],那么内容脚本会插入“http://www.nytimes.com”,但不会插入“http://science.nytimes.com”或“http://www.nytimes.com/science”。

范围(glob)属性与匹配表达式相比遵循不同并且更灵活的语法。所有含有“通配符”星号和问号的URL都是可接受的范围字符串,星号(*)匹配任意长度的字符串(包括空字符串),问号(?)匹配任意单个字符。

例如,范围 "http://???.example.com/foo/*" 匹配以下任一 URL:

  • "http://www.example.com/foo/bar"
  • "http://the.example.com/foo/"

<!---ecms @However, it does not match the following:-->但是不匹配如下 URL:

  • "http://my.example.com/foo/bar"
  • "http://example.com/foo/"
  • "http://www.example.com/foo"

以编程方式插入

如果您的 JavaScript 或 CSS代码不需要插入匹配的每一个页面时,例如,如果您希望当用户单击浏览器按钮的图标时才运行脚本,以编程方式插入代码就十分有用。

<!---ecms @To insert code into a page,your extension must havecross-origin permissionsfor the page.It also must be able to use the chrome.tabs module.You can get both kinds of permissionusing the manifest file'spermissions field.-->要向页面中插入代码,您的应用必须拥有该页面的主机权限,并且还需要用到chrome.tabs 模块。您可以使用清单文件中的permissions 字段获得这些权限。

一旦您拥有了相应的权限,您可以通过调用 tabs.executeScript 向页面插入JavaScript 代码。要插入 CSS 代码,请使用 tabs.insertCSS。

下列代码当用户单击浏览器按钮时向当前标签页插入并执行 JavaScript 代码。

chrome.browserAction.onClicked.addListener(function(tab) {  chrome.tabs.executeScript({    code: 'document.body.style.backgroundColor="red"'  });});
"permissions": [  "activeTab"],

<!---ecms @When the browser is displaying an HTTP pageand the user clicks this extension's browser action,the extension sets the page's bgcolor property to 'red'.The result,unless the page has CSS that sets the background color,is that the page turns red.-->当浏览器正在显示一个 HTTP页面,并且用户单击该应用的浏览器按钮时,应用将页面的bgcolor 属性设为'red'。结果,除非页面通过 CSS设置了背景颜色,页面将变成红色。

通常,您不会直接插入代码(如前面的例子所示),而是将代码放在一个文件中。您可以像这样插入文件的内容:

chrome.tabs.executeScript(null, {file: "content_script.js"});

执行环境

<!---ecms @Content scripts execute in a special environment called an isolated world. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page. It looks to each content script as if there is no other JavaScript executing on the page it is running on. The same is true in reverse: JavaScript running on the page cannot call any functions or access any variables defined by content scripts.-->内容脚本在一个称为隔离环境的特殊环境中执行。它们可以访问所在页面的DOM,但是不能访问当前页面创建的任何 JavaScript变量或函数。对于每个内容脚本来说,就像没有其他 JavaScript在当前页面上执行。反过来也是如此:在当前页面运行的 JavaScript不能调用或访问任何内容脚本定义的函数或变量。

例如,考虑如下简单页面:

<html>  <button id="mybutton">单击我</button>  <script>    var greeting = "您好,";    var button = document.getElementById("mybutton");    button.person_name = "Bob";    button.addEventListener("click", function() {      alert(greeting + button.person_name + "。");    }, false);  </script></html>

假设如下内容脚本插入到了 hello.html 中:

var greeting = "您好啊,";var button = document.getElementById("mybutton");button.person_name = "Roberto";button.addEventListener("click", function() {  alert(greeting + button.person_name + "。");}, false);

现在,如果按钮按下,您将会看到两条问候。

隔离环境允许每一个内容脚本更改自己的 JavaScript环境,而不用担心是否会与页面或其他内容脚本发生冲突。例如,一个内容脚本可以包含JQuery v1 而页面可以包含 JQuery v2,并且它们互不影响。

隔离环境的另一个重要好处是将页面上的 JavaScript 和应用中的 JavaScript完全区分开来,这样我们就可以为内容脚本提供额外功能,而这些额外功能不应该从网页中访问,我们也不用担心访问它们的网页。

<!---ecms @It's worth noting what happens with JavaScript objects that are shared by the page and the extension - for example, the window.onload event. Each isolated world sees its own version of the object. Assigning to the object affects your independent copy of the object. For example, both the page and extension can assign to window.onload, but neither one can read the other's event handler. The event handlers are called in the order in which they were assigned.-->网页与应用之间共享的 JavaScript 对象值得注意,例如window.onload事件。每一个隔离环境拥有该对象自己的副本,对该对象赋值只影响这一独立的副本。例如,网页和应用都可以给window.onload赋值,但是都不能读取另外一方的事件处理器。事件处理器将按照它们赋值的顺序调用。

与嵌入的页面通信

尽管内容脚本的执行环境和所在页面是互相隔离的,但是它们都可以访问页面的DOM。如果页面想要和内容脚本通信(或者通过内容脚本与应用通信),必须通过共享的DOM 进行。

可以使用 window.postMessage(或者 window.webkitPostMessage 用于可传输(Transferable)的对象):

var port = chrome.runtime.connect();window.addEventListener("message", function(event) {  // 我们只接受来自我们自己的消息  if (event.source != window)    return;  if (event.data.type && (event.data.type == "FROM_PAGE")) {    console.log("内容脚本接收到:" + event.data.text);    port.postMessage(event.data.text);  }}, false);
document.getElementById("theButton").addEventListener("click",    function() {  window.postMessage({ type: "FROM_PAGE", text: "来自网页的问候!" }, "*");}, false);

在上面的例子中,example.html(不是应用的一部分)向自己发送消息,由内容脚本截获并检查,然后发送至应用进程。通过这种方式,页面建立了与应用之间的通信,通过类似的方式反过来也是可能的。

安全性考虑

当您编写内容脚本时,您应该注意两个安全问题。首先,注意不要向您插入内容脚本的网站引入安全隐患。例如,如果您的内容脚本从另一个网站接收内容(例如通过发出XMLHttpRequest),一定要注意把内容插入当前页面前过滤可能的跨站脚本攻击。例如,首选 innerText 而不是 innerHTML 插入内容。当您在HTTPS 页面上获取来自 HTTP 的内容时要特别小心,因为如果用户在不安全的网络环境中,HTTP 内容可能会因为网络中的中间人攻击而遭到破坏。

第二,尽管在隔离环境中运行您的内容脚本提供了某些保护,但是如果您不加区分地使用来自网页的内容,恶意网页仍然可能攻击您的内容脚本。例如,以下形式是危险的:

var data = document.getElementById("json-data")// 警告!可能会执行恶意脚本!var parsed = eval("(" + data + ")")
var elmt_id = ...// 警告!elmt_id可能为"); …恶意脚本… //"!window.setTimeout("animate(" + elmt_id + ")", 200);

因此,改用更安全的不运行脚本的 API:

var data = document.getElementById("json-data")// JSON.parse 不会运行攻击者的脚本。var parsed = JSON.parse(data);
var elmt_id = ...// 闭包形式的 setTimeout 不会运行脚本。window.setTimeout(function() {  animate(elmt_id);}, 200);

引用应用的文件

<!---ecms @Get the URL of an extension's file usingchrome.extension.getURL().You can use the resultjust like you would any other URL,as the following code shows.-->使用 extension.getURL 获得应用的文件 URL,您可以像任何其他 URL一样使用获得的结果,如以下代码所示。

<em>//用来显示 <应用目录>/images/myimage.png 的代码:</em>var imgURL = <b>chrome.extension.getURL("images/myimage.png")</b>;document.getElementById("someImage").src = imgURL;

<!---ecms

--> <!---ecms 例子

--><!---ecms 您可以找到很多使用内容脚本的例子。一个简单的通过消息通信的例子在Message Timer中,有关以编程方式插入的例子请参见Page Redder和Email this page (by Google)。

-->

来源: https://chajian.baidu.com/developer/extensions/content_scripts.html


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:内容脚本 -百度浏览器应用开发文档

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址