我正在努力学习如何构建Google Chrome扩展程序。我在网页上有一个联系表单,我用它进行测试。我试图创建一个扩展来读取该表单中的输入字段值。这时,我有:
的manifest.json
{
"manifest_version": 2,
"name": "Contact Form Friend",
"description": "This extension gets contact form info.",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"<all_urls>"
]
}
popup.html
<!doctype html>
<html>
<head>
<title>Getting Started Extension's Popup</title>
<style type="text/css">
body {
margin: 10px;
white-space: nowrap;
}
h1 {
font-size: 15px;
}
#container {
align-items: center;
display: flex;
justify-content: space-between;
}
</style>
<script src="popup.js"></script>
</head>
<body>
<h1>Info</h1>
<div id="info">
</div>
</body>
</html>
popup.js
function getHost() {
return document.documentElement;
}
document.addEventListener('DOMContentLoaded', () => {
const infoDisplay = document.getElementById('info');
const scriptToRun = `(${getHost})()`;
// Run the script in the context of the tab
chrome.tabs.executeScript({
code: scriptToRun
}, (result) => {
var values = [];
var inputFields = result.getElementsByTagName('input');
infoDisplay.innerHTML = 'inputs: ' + inputFields.length;
for (var i = 0; i < inputFields.length; i++) {
values.push(inputFields[i].value);
}
infoDisplay.innerHTML += '<br />fields: ' + values.length;
});
});
当我运行它时,它就像从用户所在的网页(不是扩展程序的网页)访问输入字段一样。我究竟做错了什么?我错过了许可吗?我不相信。但是,它不起作用,我不知道为什么。
感谢您的帮助。
答案 0 :(得分:4)
根据Gabriel Bleu的报告,您需要一个内容脚本来与Chrome标签页内的网页进行互动。
以下是Chrome扩展程序示例,其中内容脚本向popup.js公开两个“命令”。
请参阅代码注释以获取解释。
manifest.json (与您的相似)
{
"name": "My ext",
"version": "0.1",
"description": "my desc",
"permissions": [
"activeTab",
"<all_urls>"
],
"icons": {
"128": "icon-128.png"
},
"browser_action": {
"default_title": "My ext",
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"manifest_version": 2,
"content_security_policy": "script-src 'self' https://ajax.googleapis.com object-src 'self'"
}
popup.html (类似于你的,除了jQuery用于简单的DOM操作)
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="application/javascript" charset="utf-8" src="popup.js"></script>
</head>
<body class="body-popup">
<button id="btn_check" class="btn btn-warning">check current tab</button>
<hr>
<div id="pg_url"></div>
<hr>
<div id="log"></div>
</body>
</html>
<强> popup.js 强>
$(function() {
$('#btn_check').click(function() { checkCurrentTab(); });
});
function checkCurrentTab() {
chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function (tabs) {
var url = tabs[0].url;
console.log("checkCurrentTab: "+url);
$(".pg_url").text(url);
// request content_script to retrieve title element innerHTML from current tab
chrome.tabs.sendMessage(tabs[0].id, "getHeadTitle", null, function(obj) {
console.log("getHeadTitle.from content_script:", obj);
log("from content_script:"+obj);
});
});
}
document.addEventListener('DOMContentLoaded', function () {
chrome.windows.getCurrent(function (currentWindow) {
chrome.tabs.query({active: true, windowId: currentWindow.id}, function(activeTabs) {
// inject content_script to current tab
chrome.tabs.executeScript(activeTabs[0].id, {file: 'content_script.js', allFrames: false});
});
});
});
function log(txt) {
var h = $("#log").html();
$("#log").html(h+"<br>"+txt);
}
<强> content_script.js 强>
// you will see this log in console log of current tab in Chrome when the script is injected
console.log("content_script.js");
chrome.runtime.onMessage.addListener(function(cmd, sender, sendResponse) {
console.log("chrome.runtime.onMessage: "+cmd);
switch(cmd) {
case "getHtml":
// retrieve document HTML and send to popup.js
sendResponse({title: document.title, url: window.location.href, html: document.documentElement.innerHTML});
break;
case "getHeadTitle":
// retrieve title HTML and send to popup.js
sendResponse(document.getElementsByTagName("title")[0].innerHTML);
break;
default:
sendResponse(null);
}
});
P.S。:显然jQuery不是强制性的
答案 1 :(得分:2)
如果您的扩展程序需要与网页进行交互,那么它需要一个内容脚本。内容脚本是一些JavaScript,它在已加载到浏览器中的页面的上下文中执行。将内容脚本视为该加载页面的一部分,而不是作为其打包的扩展(其父扩展)的一部分。
https://developer.chrome.com/extensions/overview#contentScripts
答案 2 :(得分:1)
以下是您收到的错误:
Error in response to tabs.executeScript: TypeError: result.getElementsByTagName is not a function
at Object.chrome.tabs.executeScript [as callback] (chrome-extension://lmaefdnejmkjjmgalgfofdbobhapfmoh/popup.js:15:32)
at HTMLDocument.document.addEventListener (chrome-extension://lmaefdnejmkjjmgalgfofdbobhapfmoh/popup.js:10:17)
我建议使用内容脚本来执行任务,并将结果作为消息发送到弹出窗口,而不是尝试获取popup.js中当前选项卡的DOM。
<强>的manifest.json 强>
{
"manifest_version": 2,
"name": "Contact Form Friend",
"description": "This extension gets contact form info.",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"<all_urls>"
],
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["content.js"]
}
]
}
在 manifest.json 文件中,您必须添加内容脚本并设置要在其中注入脚本的网站的网址。
<强> popup.js 强>
document.addEventListener('DOMContentLoaded', () => {
const infoDisplay = document.getElementById('info');
window.addEventListener('DOMContentLoaded', function () {
chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, {}, function (result) {
infoDisplay.innerHTML = result
});
});
});
});
在 popup.js 中向内容脚本发送请求,以获取输入字段的数量并将响应插入div
。
<强> content.js 强>
chrome.runtime.onMessage.addListener(function (msg, sender, response) {
var values = [];
var inputFields = document.getElementsByTagName('input');
var result = 'inputs: ' + inputFields.length;
for (var i = 0; i < inputFields.length; i++) {
values.push(inputFields[i].value);
}
result += '<br />fields: ' + values.length;
response(result)
});
创建一个名为content.js
的新文件。此文件将被注入网页,并侦听来自popup.js的消息。当消息到达时,它会计算响应并将其发送回popup.js。
要了解有关内容脚本的详情,请查看documentation。
答案 3 :(得分:-1)
您的方法的主要问题是您尝试通过message / sendResponse从内容脚本向弹出/后台发送DOM树,以便在那里处理它。您无法通过message / sendResponse发送DOM树。
更好的方法是在内容脚本中处理DOM,并将所需信息(在您的情况下,input
值)发送回弹出/背景页面。
一种可行的方法是:
<强> popup.js 强>
document.addEventListener('DOMContentLoaded', () => {
const infoDisplay = document.getElementById('info');
const scriptToRun = `
var values = [];
var inputFields = document.getElementsByTagName('input');
for (var i = 0; i < inputFields.length; i++) {
values.push(inputFields[i].value);
}
values;`; //all this code will be run on the tab page
//and the array "values" will be returned.
chrome.tabs.executeScript({
code: scriptToRun
}, (result) => {
infoDisplay.innerHTML = `There are: ${result[0].length} inputs, with these values: <ol><li>${result[0].join("<li>")}`;
});
});