0

I'm writing a simple Chrome extension that tries to spoof your current user agent. I just found out about this question and implemented it in my code.

The following is a content script that tries to replace the current user agent string, set to run at document_start:

let useragent, actualCode, timer = null;
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.useragent) {
    sendResponse({error: false});
    useragent = request.useragent;
  }
  else sendResponse({error: true});
});

var receivedUA = function() {
  if (useragent != null) {
    window.clearInterval(timer);
    actualCode = function(userAgent) {
      console.log('im being called');
      'use strict';
      let navigator = window.navigator;
      let modifiedNavigator;

      if ('userAgent' in Navigator.prototype) {
        modifiedNavigator = Navigator.prototype;
      } else {
        modifiedNavigator = Object.create(navigator);
        Object.defineProperty(window, 'navigator', {
          value: modifiedNavigator,
          configurable: false,
          enumerable: false,
          writable: false
        });
        Object.defineProperty(navigator, 'navigator', {
          value: modifiedNavigator,
          configurable: false,
          enumerable: false,
          writable: false
        });
      }

      Object.defineProperties(modifiedNavigator, {
        userAgent: {
          value: userAgent.useragent,
          configurable: false,
          enumerable: true,
          writable: false
        },
        appVersion: {
          value: userAgent.appversion,
          configurable: false,
          enumerable: true,
          writable: false
        },
        platform: {
          value: userAgent.platform,
          configurable: false,
          enumerable: true,
          writable: false
        }
      });

      console.dir(modifiedNavigator);

    };
    let evt = new Event('reset');
    document.documentElement.addEventListener('reset', actualCode(useragent));
    document.documentElement.dispatchEvent(evt);
    document.documentElement.removeEventListener('reset', actualCode(useragent));
  }
  else {
    window.clearTimeout(timer);
    timer = window.setTimeout(receivedUA, 100);
  }
}
receivedUA();

However, I'm testing on whatsmyua.com and the code is called when the document starts to load, but after it has loaded, it displays my true user agent, and typing window.navigator.userAgent on the console returns the same. What am I missing here?

Alexandre
  • 97
  • 11

2 Answers2

0

Maybe you should avoid such complexity with using chrome.webRequest API here. Here is a bit modified example which will output User-Agent header's object from the link above:

chrome.webRequest.onBeforeSendHeaders.addListener(
    function(details) {
        for (var i = 0; i < details.requestHeaders.length; ++i) {
            if (details.requestHeaders[i].name === 'User-Agent') {
              console.log(details.requestHeaders[i]);
              break;
            }
          }
          return {requestHeaders: details.requestHeaders};
    },
    {urls: ["<all_urls>"]},
    ["blocking", "requestHeaders"]
);

Also.. you should add this into your background script (see here)

aderushev
  • 818
  • 8
  • 11
  • 1
    I think part of answering the question is explaining why it didn't work, specially since your suggestion won't affect `window.navigator` – Ruan Mendes Jul 03 '16 at 14:11
  • I already use this part in my code. I think the vast majority of websites rely on `window.navigator` to retrieve the user agent instead of the HTTP headers. – Alexandre Jul 03 '16 at 16:09
  • So, is there anything I can do to prevent it from being overwritten? – Alexandre Jul 10 '16 at 16:11
0

If you check source code of the http://www.whatsmyua.com/ you can see that it gets user-agent at the page loading in inline scripts at the beginning of the body:

function getUa() { return decodeURIComponent(location.hash.replace('#', '')) || navigator.userAgent; }

So the answer here is timing: who will be faster - your content-script or page scripts. And the page is winning. It retrieves user-agent before content-script overrides it.

You can download the page as html, run it on localhost and put there additional logging with timestamps to measure timings.

Also make sure you're using "run_at": "document_start" for your context script.