- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是浏览器扩展开发的新手,我了解浏览器扩展更改页面并向其中注入(inject)代码的概念。
有没有办法可以扭转这个方向?我编写了一个扩展程序,提供了一组API,想要使用该扩展程序的网站可以检测到该扩展程序的存在,如果存在,该网站可以调用我的API方法,例如var extension = Extenion(foo, bar)
。在Chrome,Firefox和Safari中可能吗?
例子:
beautifer = Beautifier();
最佳答案
由于Chrome引入了 externally_connectable
,因此在Chrome中非常容易做到。首先,在manifest.json
文件中指定允许的域:
"externally_connectable": {
"matches": ["*://*.example.com/*"]
}
chrome.runtime.sendMessage
从页面发送消息:
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
function(response) {
// ...
});
chrome.runtime.onMessageExternal
监听您的背景页面:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
// verify `sender.url`, read `request` object, reply with `sednResponse(...)`...
});
externally_connectable
支持,则原始答案如下:
<div>
元素添加到页面,则可以正常工作。内容脚本和页面都将看到新的<div>
。 foo()
(如在设置新API时可能会尝试的)。页面无法查看或执行foo
,因为foo
仅存在于内容脚本的执行环境中,而不存在于页面环境中。 dispatchEvent
触发自定义DOM事件,内容脚本使用addEventListener
监听它们,并在收到事件时采取措施。这是一个简单的基于事件的存储API,网页可以使用该API进行扩展以为其存储数据:// an object used to store things passed in from the API
internalStorage = {};
// listen for myStoreEvent fired from the page with key/value pair data
document.addEventListener('myStoreEvent', function(event) {
var dataFromPage = event.detail;
internalStorage[dataFromPage.key] = dataFromPage.value
});
function sendDataToExtension(key, value) {
var dataObj = {"key":key, "value":value};
var storeEvent = new CustomEvent('myStoreEvent', {"detail":dataObj});
document.dispatchEvent(storeEvent);
}
sendDataToExtension("hello", "world");
CustomEvent
constructor中。这里的示例非常简单-一旦内容脚本具有页面中的数据(很可能是pass it到background page进行进一步处理),您显然可以在内容脚本中执行更多操作。 sendDataToExtension
。创建和触发自定义事件非常冗长(我的代码占用3行,并且相对简短)。您不想强制网站仅使用API编写奥术事件触发代码。该解决方案有点讨厌:将<script>
标记附加到共享DOM,这会将事件触发代码添加到主页的执行环境中。// inject a script from the extension's files
// into the execution environment of the main page
var s = document.createElement('script');
s.src = chrome.extension.getURL("myapi.js");
document.documentElement.appendChild(s);
myapi.js
中定义的任何函数都将可访问主页。 (如果使用的是"manifest_version":2
,则需要在 list 的 myapi.js
列表中包括web_accessible_resources
)。function sendDataToExtension(key, value) {
var dataObj = {"key":key, "value":value};
var storeEvent = new CustomEvent('myStoreEvent', {"detail":dataObj});
document.dispatchEvent(storeEvent);
}
sendDataToExtension("hello", "world");
myapi.js
脚本在加载时将无法完全使用。相反,它将在页面加载时间之后的一段时间加载。因此,纯网页需要知道何时可以安全地调用您的API。您可以通过让myapi.js
触发“API就绪”事件来解决此问题,您的页面会监听该事件。function sendDataToExtension(key, value) {
// as above
}
// since this script is running, myapi.js has loaded, so let the page know
var customAPILoaded = new CustomEvent('customAPILoaded');
document.dispatchEvent(customAPILoaded);
document.addEventListener('customAPILoaded', function() {
sendDataToExtension("hello", "world");
// all API interaction goes in here, now that the API is loaded...
});
run_at
属性设置为"document_start"
,如下所示: "content_scripts": [
{
"matches": ["https://example.com/*"],
"js": [
"myapi.js"
],
"run_at": "document_start"
}
],
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.
function getDataFromExtension(key, callback) {
var reqId = Math.random().toString(); // unique ID for this request
var dataObj = {"key":key, "reqId":reqId};
var fetchEvent = new CustomEvent('myFetchEvent', {"detail":dataObj});
document.dispatchEvent(fetchEvent);
// get ready for a reply from the content script
document.addEventListener('fetchResponse', function respListener(event) {
var data = event.detail;
// check if this response is for this request
if(data.reqId == reqId) {
callback(data.value);
document.removeEventListener('fetchResponse', respListener);
}
}
}
// listen for myFetchEvent fired from the page with key
// then fire a fetchResponse event with the reply
document.addEventListener('myStoreEvent', function(event) {
var dataFromPage = event.detail;
var responseData = {"value":internalStorage[dataFromPage.key], "reqId":data.reqId};
var fetchResponse = new CustomEvent('fetchResponse', {"detail":responseData});
document.dispatchEvent(fetchResponse);
});
document.addEventListener('customAPILoaded', function() {
getDataFromExtension("hello", function(val) {
alert("extension says " + val);
});
});
reqId
是必需的,这样它们就不会读取错误的响应。 关于javascript - 网站可以调用浏览器扩展吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10526995/
为了让我的代码几乎完全用 Jquery 编写,我想用 Jquery 重写 AJAX 调用。 这是从网页到 Tomcat servlet 的调用。 我目前情况的类似代码: var http = new
我想使用 JNI 从 Java 调用 C 函数。在 C 函数中,我想创建一个 JVM 并调用一些 Java 对象。当我尝试创建 JVM 时,JNI_CreateJavaVM 返回 -1。 所以,我想知
环顾四周,我发现从 HTML 调用 Javascript 函数的最佳方法是将函数本身放在 HTML 中,而不是外部 Javascript 文件。所以我一直在网上四处寻找,找到了一些简短的教程,我可以根
我有这个组件: import {Component} from 'angular2/core'; import {UserServices} from '../services/UserService
我正在尝试用 C 实现一个简单的 OpenSSL 客户端/服务器模型,并且对 BIO_* 调用的使用感到好奇,与原始 SSL_* 调用相比,它允许一些不错的功能。 我对此比较陌生,所以我可能会完全错误
我正在处理有关异步调用的难题: 一个 JQuery 函数在用户点击时执行,然后调用一个 php 文件来检查用户输入是否与数据库中已有的信息重叠。如果是这样,则应提示用户确认是否要继续或取消,如果他单击
我有以下类(class)。 public Task { public static Task getInstance(String taskName) { return new
嘿,我正在构建一个小游戏,我正在通过制作一个数字 vector 来创建关卡,该数字 vector 通过枚举与 1-4 种颜色相关联。问题是循环(在 Simon::loadChallenge 中)我将颜
我有一个java spring boot api(数据接收器),客户端调用它来保存一些数据。一旦我完成了数据的持久化,我想进行另一个 api 调用(应该处理持久化的数据 - 数据聚合器),它应该自行异
首先,这涉及桌面应用程序而不是 ASP .Net 应用程序。 我已经为我的项目添加了一个 Web 引用,并构建了各种数据对象,例如 PayerInfo、Address 和 CreditCard。但问题
我如何告诉 FAKE 编译 .fs文件使用 fsc ? 解释如何传递参数的奖励积分,如 -a和 -target:dll . 编辑:我应该澄清一下,我正在尝试在没有 MSBuild/xbuild/.sl
我使用下划线模板配置了一个简单的主干模型和 View 。两个单独的 API 使用完全相同的配置。 API 1 按预期工作。 要重现该问题,请注释掉 API 1 的 URL,并取消注释 API 2 的
我不确定什么是更好的做法或更现实的做法。我希望从头开始创建目录系统,但不确定最佳方法是什么。 我想我在需要显示信息时使用对象,例如 info.php?id=100。有这样的代码用于显示 Game.cl
from datetime import timedelta class A: def __abs__(self): return -self class B1(A):
我在操作此生命游戏示例代码中的数组时遇到问题。 情况: “生命游戏”是约翰·康威发明的一种细胞自动化技术。它由一个细胞网格组成,这些细胞可以根据数学规则生存/死亡/繁殖。该网格中的活细胞和死细胞通过
如果我像这样调用 read() 来读取文件: unsigned char buf[512]; memset(buf, 0, sizeof(unsigned char) * 512); int fd;
我用 C 编写了一个简单的服务器,并希望调用它的功能与调用其他 C 守护程序的功能相同(例如使用 ./ftpd start 调用它并使用 ./ftpd stop 关闭该实例)。显然我遇到的问题是我不知
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
我希望能够从 cmd 在我的 Windows 10 计算机上调用 python3。 我已重新安装 Python3.7 以确保选择“添加到路径”选项,但仍无法调用 python3 并使 CMD 启动 P
我是一名优秀的程序员,十分优秀!