2

I'm making an extension to customize Google' homepage background.So I write some match rules in manifest like this:

"content_scripts": [
    {
      "matches": ["https://www.google.com/", "http://www.google.com/"],
      "js": ["static/js/jquery.js", "static/js/contentscript.js"]
    }
],

and some scripts in contentscript.js:

var imgURL = chrome.extension.getURL("static/images/bg.jpg");
$('body').css('background-image', 'url(' + imgURL + ')');

The script works fine for https://www.google.com, but when I try to search something ,the page jumps to https://www.google.com/#newwindow=1&sclient=psy-ab&q=Google&oq=Google&gs_l=hp.3..35i39l2j0i20l2j0l6.4788.5717.2.5939.5.3.2.0.0.0.142.397.0j3.3.0....0.0..1c.1.20.hp.xCFVga8gVZU&bav=on.2,or.r_cp.r_qf.&bvm=bv.49784469%2Cd.dGI%2Cpv.xjs.s.en_US.MpiVkF51mpA.O&fp=806ba48f5b2ed550&biw=1920&bih=963

But the script is still working after the jumping! And if I paste the long url in a new tab directly, it won't work!

I think it should be related with iframe or Ajax or something else. Could someone give some more details? And how can I prevent scripts from running after the url changed?

Sam Su
  • 4,585
  • 6
  • 31
  • 74
  • 2
    I'm not sure why it *isn't* loading when you directly visit the search page. I've never inspected it too closely, but it seems Google is a bit tricky: when you do a search from their main page, I don't think they ever actually load a new page. They just heavily edit the DOM of the existing page to include search results (and use the [history API](http://diveintohtml5.info/history.html) to allow you to use your back button, I think). Thus, the results page is not a new page, so your content script is still loaded. – apsillers Jul 29 '13 at 13:01
  • What I see is that the search result page had a obvious reloading action,quite different from Github that changes its URL without reloading. – Sam Su Jul 29 '13 at 15:06
  • 2
    PS. Come on, you don't need jQuery for something as trivial as changing the background image: `document.body.style.backgroundImage = 'url(' + chrome.extension.getURL("static/images/bg.jpg") + ')';` does the same thing and saves you many bytes. – Rob W Jul 29 '13 at 17:46

2 Answers2

2

If you want to apply a style to Google's home page, just use a selector which is very specific to Google's homepage. With the Inspector, I quickly discovered that the <body> tag at the homepage has a class "hp". This class does not show up in search results.

Drop your JavaScript code, and use

Part of manifest.json

"content_scripts": [
    {
      "matches": ["*://www.google.com/*"],
      "css": ["my-google-style.css"]
    }
],
"web_accessible_resources": [
    "static/images/bg.jpg"
],
  • The first wildcard, *, means "http" and "https".
  • The added wildcard at the end does not matter, because the "homepage" requirement is enforced in the next stylesheet.
  • The "web_accessible_resources" key is necessary if you want to display the image in an external (=non-extension) page.

my-google-style.css

body.hp {
    background-image: url("chrome-extension://__MSG_@@extension_id__/static/images/bg.jpg");
}

The first part of my answer is the recommendation for your case. In general, if you want to catch every (scripted and user-initiated) URL change, including but not limited to:

  • history.pushState / history.replaceState
  • location.hash = '...';
  • User goes back / forward (and changes hash / history state)

... then you need to use the chrome.webNavigation API in the background/event page, in particular the onHistoryStateUpdated and/or onReferenceFragmentUpdated events. In response to these events, you'll either send a message or execute a content script.

If you only expect rewrites of the reference fragment (aka location hash), then there's no need for the webNavigation API. The implementation will be simplier, as you only need to listen to the global hashchange event in the content script.

Community
  • 1
  • 1
Rob W
  • 315,396
  • 71
  • 752
  • 644
  • Tks for ur long answer. BTW, I think the prefix chrome-extension://__MSG_@@extension_id__/ is necessary in manifest v2, otherwise the injection will be "google.com/static/images/bg.jpg" :-) – Sam Su Jul 30 '13 at 01:49
  • @Sam URLs within stylesheet are resolved relative to the style sheet. Last time I checked, there was no need to add these images to the `web_accessible_resources` section of the manifest file to get it to work. – Rob W Jul 30 '13 at 07:28
  • I still failed. The relative path is recognized as Google's, not my extension, so the style injection result I see at the chrome developer tools is "google.com/static/images/bg.jpg". Check it here:`http://stackoverflow.com/questions/3559781/google-chrome-extensions-cant-load-local-images-with-css/8864212#8864212` – Sam Su Jul 30 '13 at 08:19
  • @Sam I've revised my answer, see the revision history to see what's different. – Rob W Jul 30 '13 at 08:27
-1

You need to include a wildcard * to your matches like so:

"content_scripts": [
    {
      "matches": ["https://www.google.com/*", "http://www.google.com/*"],
      "js": ["static/js/jquery.js", "static/js/contentscript.js"]
    }
],
Chris McFarland
  • 5,847
  • 4
  • 44
  • 61
  • 1
    If so,every link which started with `https://www.google.com/` will be injected.I just mean the Google Homepage. – Sam Su Jul 29 '13 at 14:54
  • Could you add a check with `window.onhashchange` so that, if `window.document.location.href != "https://www.google.com/" && window.document.location.href != "http://www.google.com/"`, revert your code's changes? Also see http://stackoverflow.com/a/2162174/206410 – Chris McFarland Jul 29 '13 at 15:02