内容脚本看到错误的文档元素
Content script sees wrong Document element
我目前正在开发一个 Chrome 扩展程序,它试图从当前选项卡中显示的页面中获取突出显示的文本。
它适用于一些简单的页面,例如维基百科,但不适用于一些复杂的页面,尤其是主要的媒体页面,例如 http://www.nytimes.com/。
当我在下面调试我的内容脚本时,文档或 window 元素似乎与我的 Chrome 选项卡中显示的页面不对应。
这是我的 manifest.json :
{
"name": "Capitalize!t2",
"version": "3.1.2",
"manifest_version": 2,
"minimum_chrome_version": "29",
"browser_action": {
"default_icon": "icon-small.png",
"default_popup": "popup.html"
},
"content_scripts": [ {
"js": [ "selectionjfm.js","jquery-1.11.1.min.js","jquery-ui.min.js" ],
"css":["jquery-ui.css"],
"matches": [ "http://*/*", "https://*/*"],
"all_frames":true
}],
"icons" : { "16": "icon-small.png",
"48": "icon.png",
"128": "icon-small.png" },
"key": "MXXXXXX",
"permissions": [
"https://secure.flickr.com/","identity", "https://accounts.google.com/*", "https://www.googleapis.com/*","https://spreadsheets.google.com/*","tabs","storage","<all_urls>"
],
"oauth2": {
"client_id": "XXXXXX",
"scopes": ["https://www.googleapis.com/auth/plus.login","https://spreadsheets.google.com/feeds"]
}
}
这是我 popup.js
中有趣的部分
function extractselection(id)
{
chrome.tabs.query({active:true, windowId: chrome.windows.WINDOW_ID_CURRENT},
function(tab) {
chrome.tabs.sendMessage(tab[0].id, {method: "getSelection"},
function(response){
var text = document.getElementById(id);
if(response!=null){
text.innerHTML = response.data;
}
});
});
}
这是我的内容脚本(selectionjfm.cs),有点乱,对不起。
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
//console.log("grrroooooooove"+request.method);
var toto="";
if (request.method == "getSelection"){
var frame= document.getElementsByTagName('iframe');
if(frame!=null && frame.length>0){
for(var i=0;i<frame.length;i++){
win= frame[i].contentWindow;
idoc=win.document;
if(idoc.getSelection){
toto+=idoc.getSelection().toString();
}
}
//else console.log("no selection");
}
//console.log('totototo:'+window.getSelection().toString());
toto+=window.getSelection().toString();
toto+=document.getSelection().toString();
var html = document.getElementsByTagName('html')[0].innerHTML;
sendResponse({data: toto });
}
else{
//console.log('nullll');
sendResponse({}); // snub them.
}
});
如果我转到 a NY Times page、运行 我的应用程序并查看调试控制台,我可以看到我的文档元素 URI 实际上是:
`googleads.g.doubleclick.net/pagead/ads?...`
我在document.referer
中看到了好的URL。
我想知道是否有人可以解释这种重定向,是否有办法避免它...
我认为您没有被重定向。您发布的 URI 来自嵌套在纽约时报文章中的广告。您可能会发现 chrome.windows.WINDOW_ID_CURRENT
指的是该广告的框架而不是父 window。
考虑在 chrome.extension.onMessage
回调中的第一行使用 debugger
语句(或 setting a breakpoint),然后单步执行代码以查看问题所在。
您正在匹配文档中的每个 URL 和 显式 每一帧。
在您打开的文档中,有一个带有 URL 的广告框。
当您使用 chrome.tabs.sendMessage
广播消息时,无法告诉 API 它应该转到哪个帧:all 帧选项卡得到它,无论他们是否在听。
但是,由于 Chrome 中消息传递的性质,您只会 第一次 sendResponse()
调用成功 。基本上,你有一个竞争条件。
见末尾注释:Simple one-time requests
Note: If multiple pages are listening for onMessage
events, only the first to call sendResponse()
for a particular event will succeed in sending the response. All other responses to that event will be ignored.
最简单的解决方案是从清单中删除 "all_frames": true
。如果您确实需要它,您可以在内容脚本本身中 determine whether you are a top level frame(例如使用 window.parent == window
)并根据此决定使用 sendResponse
来回答。
感谢 Xan,我以这种方式找到了解决方案:
在我的程序中,我知道 page/frame 的 URL 是什么,我想从中获取选择。
所以我正在做的是从 popup.js 发送消息以及我想捕获的 page/frame 的 URI。
function extractselection(id,**urllink**)
{
chrome.tabs.query({active:true, windowId: chrome.windows.WINDOW_ID_CURRENT},
function(tab) {
chrome.tabs.sendMessage(tab[0].id, {method: "getSelection",**urllink:urllink**},
function(response){
var text = document.getElementById(id);
if(response!=null){
text.innerHTML = response.data;
}
});
});
}
在我的内容脚本中,我检查了框架 URL,如果它与我正在寻找的相匹配,我将发送响应,否则不会
内容脚本:
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
//console.log("grrroooooooove"+request.method);
var toto="";
if (request.method == "getSelection" && document.URL==request.urllink){
var frame= document.getElementsByTagName('iframe');
if(frame!=null && frame.length>0){
for(var i=0;i<frame.length;i++){
win= frame[i].contentWindow;
idoc=win.document;
if(idoc.getSelection){
toto+=idoc.getSelection().toString();
}
}
//else console.log("no selection");
}
//console.log('totototo:'+window.getSelection().toString());
toto+=window.getSelection().toString();
toto+=document.getSelection().toString();
var html = document.getElementsByTagName('html')[0].innerHTML;
sendResponse({data: toto });
}
// else{
//console.log('nullll');
// sendResponse({}); // snub them.
//}
});
清单保持不变。
我目前正在开发一个 Chrome 扩展程序,它试图从当前选项卡中显示的页面中获取突出显示的文本。
它适用于一些简单的页面,例如维基百科,但不适用于一些复杂的页面,尤其是主要的媒体页面,例如 http://www.nytimes.com/。
当我在下面调试我的内容脚本时,文档或 window 元素似乎与我的 Chrome 选项卡中显示的页面不对应。
这是我的 manifest.json :
{
"name": "Capitalize!t2",
"version": "3.1.2",
"manifest_version": 2,
"minimum_chrome_version": "29",
"browser_action": {
"default_icon": "icon-small.png",
"default_popup": "popup.html"
},
"content_scripts": [ {
"js": [ "selectionjfm.js","jquery-1.11.1.min.js","jquery-ui.min.js" ],
"css":["jquery-ui.css"],
"matches": [ "http://*/*", "https://*/*"],
"all_frames":true
}],
"icons" : { "16": "icon-small.png",
"48": "icon.png",
"128": "icon-small.png" },
"key": "MXXXXXX",
"permissions": [
"https://secure.flickr.com/","identity", "https://accounts.google.com/*", "https://www.googleapis.com/*","https://spreadsheets.google.com/*","tabs","storage","<all_urls>"
],
"oauth2": {
"client_id": "XXXXXX",
"scopes": ["https://www.googleapis.com/auth/plus.login","https://spreadsheets.google.com/feeds"]
}
}
这是我 popup.js
中有趣的部分function extractselection(id)
{
chrome.tabs.query({active:true, windowId: chrome.windows.WINDOW_ID_CURRENT},
function(tab) {
chrome.tabs.sendMessage(tab[0].id, {method: "getSelection"},
function(response){
var text = document.getElementById(id);
if(response!=null){
text.innerHTML = response.data;
}
});
});
}
这是我的内容脚本(selectionjfm.cs),有点乱,对不起。
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
//console.log("grrroooooooove"+request.method);
var toto="";
if (request.method == "getSelection"){
var frame= document.getElementsByTagName('iframe');
if(frame!=null && frame.length>0){
for(var i=0;i<frame.length;i++){
win= frame[i].contentWindow;
idoc=win.document;
if(idoc.getSelection){
toto+=idoc.getSelection().toString();
}
}
//else console.log("no selection");
}
//console.log('totototo:'+window.getSelection().toString());
toto+=window.getSelection().toString();
toto+=document.getSelection().toString();
var html = document.getElementsByTagName('html')[0].innerHTML;
sendResponse({data: toto });
}
else{
//console.log('nullll');
sendResponse({}); // snub them.
}
});
如果我转到 a NY Times page、运行 我的应用程序并查看调试控制台,我可以看到我的文档元素 URI 实际上是:
`googleads.g.doubleclick.net/pagead/ads?...`
我在document.referer
中看到了好的URL。
我想知道是否有人可以解释这种重定向,是否有办法避免它...
我认为您没有被重定向。您发布的 URI 来自嵌套在纽约时报文章中的广告。您可能会发现 chrome.windows.WINDOW_ID_CURRENT
指的是该广告的框架而不是父 window。
考虑在 chrome.extension.onMessage
回调中的第一行使用 debugger
语句(或 setting a breakpoint),然后单步执行代码以查看问题所在。
您正在匹配文档中的每个 URL 和 显式 每一帧。
在您打开的文档中,有一个带有 URL 的广告框。
当您使用 chrome.tabs.sendMessage
广播消息时,无法告诉 API 它应该转到哪个帧:all 帧选项卡得到它,无论他们是否在听。
但是,由于 Chrome 中消息传递的性质,您只会 第一次 sendResponse()
调用成功 。基本上,你有一个竞争条件。
见末尾注释:Simple one-time requests
Note: If multiple pages are listening for
onMessage
events, only the first to callsendResponse()
for a particular event will succeed in sending the response. All other responses to that event will be ignored.
最简单的解决方案是从清单中删除 "all_frames": true
。如果您确实需要它,您可以在内容脚本本身中 determine whether you are a top level frame(例如使用 window.parent == window
)并根据此决定使用 sendResponse
来回答。
感谢 Xan,我以这种方式找到了解决方案:
在我的程序中,我知道 page/frame 的 URL 是什么,我想从中获取选择。
所以我正在做的是从 popup.js 发送消息以及我想捕获的 page/frame 的 URI。
function extractselection(id,**urllink**)
{
chrome.tabs.query({active:true, windowId: chrome.windows.WINDOW_ID_CURRENT},
function(tab) {
chrome.tabs.sendMessage(tab[0].id, {method: "getSelection",**urllink:urllink**},
function(response){
var text = document.getElementById(id);
if(response!=null){
text.innerHTML = response.data;
}
});
});
}
在我的内容脚本中,我检查了框架 URL,如果它与我正在寻找的相匹配,我将发送响应,否则不会
内容脚本:
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
//console.log("grrroooooooove"+request.method);
var toto="";
if (request.method == "getSelection" && document.URL==request.urllink){
var frame= document.getElementsByTagName('iframe');
if(frame!=null && frame.length>0){
for(var i=0;i<frame.length;i++){
win= frame[i].contentWindow;
idoc=win.document;
if(idoc.getSelection){
toto+=idoc.getSelection().toString();
}
}
//else console.log("no selection");
}
//console.log('totototo:'+window.getSelection().toString());
toto+=window.getSelection().toString();
toto+=document.getSelection().toString();
var html = document.getElementsByTagName('html')[0].innerHTML;
sendResponse({data: toto });
}
// else{
//console.log('nullll');
// sendResponse({}); // snub them.
//}
});
清单保持不变。