Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invisible tabs in chrome extension

I basically want to automate a website by using a Chrome extension. But this website has extremely much client-side code, so it's really hard to find out which request I need to make in order to get the needed information.

The easiest way I can think of would be to use a content script to enter text in input elements and click buttons, like this (with jQuery in this case):

$.ready(function(){
  $("#input").val("foo");
  $("#submit").click();
});

Quite similar to this question: Injecting input into a tab opened by a Chrome Extension, but the interaction with that website should not be visible.

So: Can I open pages in chrome from an extension, that are not visible to the user and use them to interact with websites?

like image 701
Pete Avatar asked May 31 '16 17:05

Pete


2 Answers

If you want the page to be completely invisible, I believe that the only option is to load it into an iframe on the background page. You can then access the page within the iframe using content scripts, just as you would access any normal visible page.

Since many sites limit embedding using the X-Frame-Options header, you will likely have to use the webRequest API to remove that header before loading the page into an iframe. Some pages also use other techniques to prevent embedding that might further complicate this.

Example code:

manifest.json

{
  "manifest_version": 2,
  "name": "Hidden page in background",
  "description": "Interact with a hidden page in background",
  "version": "1.0",

  "background": {
    "page": "background.html",
    "persistent": true
  },
  "content_scripts": [
    {
      "matches": ["*://*.google.fr/*"],
      "js": ["contentscript.js"],
      "all_frames": true
    }
  ],
  "permissions": ["*://*.google.fr/*", "webRequest", "webRequestBlocking"]
}

background.html

<!DOCTYPE html>
<html>
  <head>
    <script src="background.js"></script>
  </head>
  <body>
    <iframe id="iframe1" width="1000 px" height="600 px" src="http://www.google.fr"></iframe>
  </body>
</html>

background.js

// This is to remove X-Frame-Options header, if present
chrome.webRequest.onHeadersReceived.addListener(
    function(info) {
      var headers = info.responseHeaders;
      var index = headers.findIndex(x=>x.name.toLowerCase() == "x-frame-options");
      if (index !=-1) {
        headers.splice(index, 1);
      }
      return {responseHeaders: headers};
    },
    {
        urls: ['*://*.google.fr/*'], //
        types: ['sub_frame']
    },
    ['blocking', 'responseHeaders']
);

contentscript.js

var elementToInsert = document.createElement("h1");
elementToInsert.textContent = "This text comes from my content script.";
document.body.insertBefore(elementToInsert, document.body.firstChild);

Couple of notes:

  • The removal of X-Frame-Options header is not limited to the background page here. It would allow embedding of the relevant page in iframes on any other page as well. Unfortunately, Chrome does not seem to support the ALLOW-FROM uri value that could be used to limit embedding to your extension only.
  • Content script is being injected to all pages here. You could inject it programmatically only to the iframe on the background page, but that gets a bit more complicated.
  • I used www.google.fr as an example, because it uses X-Frame-Options, but does not use any other techniques to prevent embedding. I used the French domain because google.com tends to redirect to local country-level domains automatically.
like image 150
Petr Srníček Avatar answered Nov 26 '22 14:11

Petr Srníček


See tabs.create, you could call the following code creating an invisible tab (not active).

chrome.tabs.create({ url: 'https://www.google.com', active: false, });
like image 35
Haibara Ai Avatar answered Nov 26 '22 15:11

Haibara Ai