18

I am developing a Chrome extension to tweak Facebook. However, catching browsing actions within HTML5-enabled sites such as Facebook requires an override of window.history.pushState as explained in this SO question.

Unfortunately, it seems that Chrome's isolated worlds prevent this sort of override. Is there any other method of catching history changes (other than polling document.location.href)?

Community
  • 1
  • 1
shmichael
  • 2,985
  • 3
  • 25
  • 32

3 Answers3

10

Not sure whether you trying to do this in background.js or content.js, but if it is the former, you can do so using webNavigation events:

You need to set permissions for webNavigation in manifest.json:

  "permissions": [
     "webNavigation"
  ],

Then in background.js:

  chrome.webNavigation.onHistoryStateUpdated.addListener(function(details) {
        console.log('Page uses History API and we heard a pushSate/replaceState.');
        // do your thing
  });

Source: Chrome Extension docs for webNavigation

philoye
  • 2,490
  • 28
  • 23
7

Yes,

One way is to create a script tag and put your code there:

html = "window.history.pushState = function(a,b,c) { alert('Change !'); };";

var headID = document.getElementsByTagName("head")[0];         
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.innerHTML = html;
headID.appendChild(newScript);
Boris
  • 3,163
  • 5
  • 37
  • 46
  • what if you want to intercept the pushstate command, do something, and then let the pushstate command complete as normal, the example given above seems to intercept the pushstate fine, but it doesnt actually carry out the pushstate command afterwards, how would you implement that? – user280109 Jan 23 '11 at 07:44
  • found a solution here, not sure if it works with chrome yet though : http://stackoverflow.com/questions/4570093/how-to-get-notified-about-changes-of-the-history-via-history-pushstate/4585031#4585031 – user280109 Jan 23 '11 at 08:32
  • Has this stopped working since the answer was posted, or is there some permission etc that is left out...? – Mattias Jiderhamn Jun 06 '15 at 07:15
  • 1
    This doesn't work. Chrome Extensions (content scripts) do not have access to the variables scope of the page, although they have access to the DOM. – fiatjaf Mar 13 '16 at 02:32
4

Building on @Boris's answer: to continue with the default action, save a reference to the original pushState function, and then call it:

var headID = document.getElementsByTagName("head")[0];         
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = chrome.extension.getURL('script.js');
headID.appendChild(newScript);

script.js:

window.history.pushState = (function(nativePushState) {
    return function(a,b,c) {
        // Do something
        nativePushState.apply(this, arguments); //Continue by calling native history.pushState
    };
})(window.history.pushState)
Owen
  • 630
  • 6
  • 21