Content script sees wrong Document element

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

Answers (3)

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

Xan
Xan

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 call sendResponse() 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

Jim O&#39;Brien
Jim O&#39;Brien

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

Related Questions