Ed Carter
Ed Carter

Reputation: 17

chrome extension changing host/domain warning

I am trying to create a chrome extension that will notify me of host/domain changes when I'm testing a specific website. Often links will be present that point towards developer or live environments and I'd like to be warned if I follow one of these links as the websites are often identical.

Edit for clarity: I want it to alert me when a link takes me away from http(s)://example.staging.something.com and ends up on the live site http(s)://www.example.com or the dev site http(s)://example.dev.something.com

So far I have managed to create a script that identifies when I am on a staging url (our test environment) however I've been unable to reverse this logic to give me a warning when I navigate to a url that doesn't contain 'staging'.

My manifest.json

{
"manifest_version": 2,

"name": "A What URL",
"description": "This extension monitors and warns you of domain changes",
"version": "1.0",

"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},

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

"permissions": [
"activeTab",
"webNavigation"
]
}

my background.js

   chrome.webNavigation.onCommitted.addListener(function(e) {
        alert ("you are still on staging!");
  }, {url: [{hostContains: 'staging'}]});

I'm sure this is simple but it appears my brain is far simpler!

Upvotes: 0

Views: 508

Answers (3)

Ed Carter
Ed Carter

Reputation: 17

Adding my final solution as an answer as requested in case anyone else is interested in the future.

Many thanks to both Xan and Rob with the help! If I could tick both I would but in the end I ended up ticking the one that led to my implementation.

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {

    var queryInfo = {
    active: true,
    currentWindow: true
    };

   chrome.tabs.query(queryInfo, function(tabs) {
       var tab = tabs[0];
       var url = tab.url;

       if(!url.match(/[^\/]*\/\/[^\/]*staging/) &&   changeInfo.status=="complete"){
           alert ("WTF!!! " +url); 
       }
   });
});

Upvotes: 0

Rob W
Rob W

Reputation: 348962

There are multiple ways to solve your problem.

  • Use the chrome.webRequest.onBeforeSendHeaders (or .onSendHeaders) event to get notified when a request is sent to your production website, and check whether the Referer header is set to your staging site. This only works if the document referrer is set (this won't be the case if you're navigating from https to http, or if the "noreferrer" referrer policy is set).

  • In the absence of a referer, use the webNavigation, webRequest and/or tabs APIs to track the navigation state of a page, and do whatever you want when you detect that the transition production -> dev occurs. Implementing this correctly is very difficult.

Here is a sample for the first method:

// background.js
chrome.webRequest.onBeforeSendHeaders.addListener(function(details) {
    var referer;
    for (var i = 0; i < details.requestHeaders.length; ++i) {
        var header = details.requestHeaders[i];
        if (header.name.toLowerCase() === 'referer' && header.value) {
            referer = header.value;
            break;
        }
    }
    if (referer && /^https?:\/\/dev\.example\.com(\/|$)/.test(referer)) {
        alert('Navigated from dev to production!');
    }
}, {
    urls: ['*://production.example.com/*', '*://prod.example.com/*'],
    types: ['main_frame', 'sub_frame'] // Track navigations, not img/css/etc.
}, ['requestHeaders']);

Example of manifest.json to test the previous logic:

{
    "name": "Detect nav from dev to prod",
    "version": "1",
    "manifest_version": 2,
    "background": {
        "scripts": ["background.js"],
        "persistent": true
    },
    "permissions": [
        "webRequest",
        "*://*/*"
    ]
}

Upvotes: 2

Xan
Xan

Reputation: 77482

Unfortunately, you can't "invert" the filter, so you'll have to catch all events and filter in the code.

Here come the Chrome Events. Your code suggests you treat them like DOM events (with the e parameter). Instead, they pass arguments depending on the event in question, sometimes several.

If you look at the documentation, you'll see that the expected callback format is:

function(object details) {...};

Where details will contain, among other things, a url property.

So you'll have:

chrome.webNavigation.onCommitted.addListener(function(details) {
  // Regexp matches first "//", followed by any number of non-/, followed by "staging"
  if(!details.url.match(/[^\/]*\/\/[^\/]*staging/)) {
    alert ("This is no longer staging!");
  }
});

Note that this is going to be extremely annoying unless you can turn it off - it will match almost any page, after all.

Upvotes: 0

Related Questions