Reputation: 112
I am currently working on a Chrome extension that tries to get the highlighted text from the page displayed in the current tab.
It works for some simple pages, like Wikipedia for instance, but does not work for some complex pages, especially main media pages like http://www.nytimes.com/.
When I debug my content script below, it seems that the document or window element is not corresponding to the page displayed in my Chrome tab.
Here is my 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"]
}
}
Here is the intresting part of my 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;
}
});
});
}
Here is then my content script (selectionjfm.cs), a bit messy I am sorry.
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.
}
});
If I go to a NY Times page, run my application and look at the debug console, I can see my document element URI is in fact:
`googleads.g.doubleclick.net/pagead/ads?...`
I can see the good URL in document.referer
.
I was wondering if any one could explain that redirection and if there was a way to avoid it...
Upvotes: 2
Views: 183
Reputation: 112
Thanks to Xan I found a solution this way :
In my program I know what is the URL of the page/frame I want to get the selection from.
So what I am doing is that I send the message from the popup.js along with the URI of the page/frame I want to catch.
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;
}
});
});
}
In my content script I check for the frame URL, if it matches the one that I am looking for, I am sending a response, otherwise not
Content Script :
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.
//}
});
manifest remains unchanged.
Upvotes: 0
Reputation: 77523
You're matching every URL and explicitly every frame in the document.
Inside the document you open, there is an ad frame with that URL.
When you broadcast a message with chrome.tabs.sendMessage
, there is no way of telling the API which frame it should go to: all frames in that tab get it, whether they are listening or not.
However, due to the nature of messaging in Chrome, you only get the first sendResponse()
call to succeed. Basically, you've got a race condition.
See note at the end: 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.
Simplest solution is to drop "all_frames": true
from the manifest. If you do really need it, you can determine whether you are a top level frame (e.g. with window.parent == window
) in the content script itself and decide to answer with sendResponse
based on that.
Upvotes: 1
Reputation: 2552
I don't think you're being redirected. The URI you have posted is from an advert nested in the NYTimes article. You may find that chrome.windows.WINDOW_ID_CURRENT
is referring to that advert's frame instead of the parent window.
Consider using a debugger
statement (or setting a breakpoint) on the first line inside your chrome.extension.onMessage
callback, and step through your code to see what's going wrong.
Upvotes: 0