3

As a learning exercise I'm attempting to build an example Chrome extension that ensures sites on a 'greylist' are always opened in an incognito window.

Here's how far I have got - using the webNavigation.onBeforeNavigate event fired when a grey listed page is about to be navigated to I open a new tab in an incognito window, but now need to prevent the original tab from opening the page.

manifest.js:

"permissions": [
  "webNavigation",
  "tabs"
],

"background": {
  "scripts": [
    "background.js"
  ],
  "persistent": false
},

background.js:

chrome.webNavigation.onBeforeNavigate.addListener(function(details) {
  chrome.tabs.get(details.tabId, function(tab) {
    if(!tab.incognito) {

      // Open the page in an incognito window
      chrome.windows.create({ url: details.url, incognito: true});

      // TODO stop non-incognito tab opening page!
    }
  });
}, {
  url: [
    { hostEquals: 'badsite.com' }
  ],
});
Argenti Apparatus
  • 3,857
  • 2
  • 25
  • 35

3 Answers3

2

To stop the navigation use window.stop() by injecting a content script in the tab:

chrome.tabs.executeScript(details.tabId, {code: 'window.stop()'});

Add a permission in manifest.json, otherwise you'll see an error in the background page console:

"permissions": [
  "webNavigation",
  "tabs",
  "<all_urls>"
],
Community
  • 1
  • 1
wOxxOm
  • 65,848
  • 11
  • 132
  • 136
  • This is not working. Additionally I found that chrome.tabs.executeScript does not always execute the script. If I create a new tab and navigate to a great listed page it does not fire, if I then refresh the page it does. I'm not getting any permissions errors, and yes, I am checking that the onBeforeNavigate event is firing and my callback is called. – Argenti Apparatus Jul 27 '16 at 19:43
  • I've tested this code by clicking a link on the page and it worked. Just saying `not working` isn't helpful to diagnose the problem, it's better to tell the exact STR (steps to reproduce). – wOxxOm Jul 27 '16 at 19:45
  • Well, just saying, but 'it worked for me' is equivalent. However: I inserted your line of code into my code at the "// TODO ..." comment, added permissions, reloaded extension. Navigated to a grey listed page in non-incognito tab, page is loaded in an incognito tab AND is still loaded in original tab. No error messages in tab console or background page console. – Argenti Apparatus Jul 27 '16 at 20:09
  • Having read https://developer.chrome.com/extensions/tabs#method-executeScript and https://developer.chrome.com/extensions/content_scripts#pi I'm fairly sure the approach is not suitable for my needs as the page has to be loaded for the script to be executed, which is too late - history is created and cookies may be set. I'm really looking for a way to command the tab to abandon navigation immediately so an HTTP request is never sent. If this is not possible, that's fine, this is a learning exercise for me. – Argenti Apparatus Jul 27 '16 at 20:09
  • It's always best to include detailed STR in your question. At least the way I did ("[...] clicking a link on the page and it worked"). As for executeScript, try `runAt: 'document_start'` parameter so that it'll be executed immediately. – wOxxOm Jul 27 '16 at 20:15
  • Even with `runAt: 'document_start'` the page has started loading, `window.stop()` prevents the page content being *displayed* but not from being loaded. Thx for the attempt. At least I learned more about content scripts in Chrome extensions :). – Argenti Apparatus Jul 27 '16 at 20:20
  • If you want to prevent the request from being sent then you'll *need* webRequest API. – wOxxOm Jul 27 '16 at 20:24
  • Clarification: when I say 'navigated to a grey listed page', I meant 'typed the url in the omni box, hit return. In this case the script invoked by chrome.tabs.executeScript is *not* executed. Further experimentation reveals that when clicking a link to a grey listed page it *is* executed. – Argenti Apparatus Jul 27 '16 at 20:32
  • webRequest API blocks requests absolutely, so no good for my purpose. It can't tell if a page is to be displayed in incognito tab or not. – Argenti Apparatus Jul 27 '16 at 20:35
  • Huh, declare a content script in manifest.json that runs on blacklisted sites and `"run_at": "document_start"`, the script itself is simply `window.stop()`. It won't be executed in incognito mode unless someone specifically enables that checkbox on chrome://extensions page for the extension. – wOxxOm Jul 27 '16 at 20:37
2

Partial answer arrived at from wOxxOm's input and further experiments and reading - to at least document what I found out.

manifest.js:

"permissions": [
  "webNavigation",
  "tabs",
  "<all_urls>"        // Note: Permission
],

...

background.js:

// Note: onCommitted
chrome.webNavigation.onCommitted.addListener(function(details) {
  chrome.tabs.get(details.tabId, function(tab) {
    if(!tab.incognito) {

      // Stop non-incognito tab opening page
      // Note runAt: "document_start"
      chrome.tabs.executeScript(details.tabId, { runAt: "document_start", code: 'window.stop(); '})

      // Open the page in an incognito window
      chrome.windows.create({ url: details.url, incognito: true});
    }
  });
}, {
  url: [
    { hostEquals: 'badsite.com' }
  ],
});

Listening for chrome.webNavigation.onCommitted events instead of onBeforeNavigate allows the script injected by chrome.tabs.executeScript to run when a grey listed page is navigated to from a new tab and a url is pasted into the omni box.

This prevents the grey listed page from being displayed, but the page is at least partially loaded. A history entry is not created but cookies or local storage items are created, so it does not meet the ultimate need of my original question.

Argenti Apparatus
  • 3,857
  • 2
  • 25
  • 35
  • Use `chrome.webRequest.onBeforeRequest` to intercept the request and have it redirected to http://google.com/gen_204. This will cause the request to do essentially nothing (won't even refresh the page). Then just have your code open up the requested url in incognito. – Mason Jun 18 '19 at 09:29
1

two ways:

  1. base on @wOxxOm
chrome.webNavigation.onBeforeNavigate.addListener((details) => {    
        chrome.tabs.executeScript(tabid,{code: 'window.stop()'});   
});
  1. not refresh
window.history.pushState(“object or string”, “Title”, “/new-url”);
defend orca
  • 617
  • 7
  • 17