2

For a test case, I want to try to output the URL for the current tab. My manifest.json

{
"manifest_version": 2,
"name": "Chrome Extension",
"description": "MyExtension",
"icons": {
    "16": "img/favicon.png",
    "48": "img/48.png"
},
"version": "0.1",
"background": {
    "scripts": ["js/content.js"],
    "persistent": false
},
"permissions": [
    "tabs", "https://*/*", "http://*/*"
],
"browser_action": {
    "default_icon": "img/default_icon.png",
    "default_title": "Get URL"
},
"content_scripts": [{
    "matches": ["<all_urls>"],
    "all_frames": true,
    "css": ["css/style.css"]
}],
    "short_name": "GetURL"
}

And the code in my content.js

document.addEventListener('DOMContentLoaded', () => { 
  chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
    alert(tabs[0].url)
  });
});

The problem is that the URL is displayed only for the first current tab, but not for another tab that became active. I tried to changed currentWindow to lastFocusedWindow and to windowId but it did not solve the problem. Tell me what I'm doing wrong?

JustTip
  • 21
  • 6
  • When I move from one tab to another – JustTip Mar 11 '17 at 20:16
  • 2
    The background page is a separate page with its own DOM (not related to the webpage in any way) inside the extension, see [architecture overview](https://developer.chrome.com/extensions/overview#arch), so 1) no need for DOMContentLoaded, it does nothing and 2) use [chrome.tabs.onActivated](https://developer.chrome.com/extensions/tabs#event-onActivated), also 3) don't use a misleading name `content.js` for a background/event script. – wOxxOm Mar 11 '17 at 20:18
  • It turns out, for this task, I do not really need background script. Right ? – JustTip Mar 11 '17 at 20:25
  • 1
    Well, the code so far can be effectively replaced with `alert(location.href)` in a *content script*, but overall it depends on what you want to do next with the url. – wOxxOm Mar 11 '17 at 20:28
  • I need to find all links on the all tabs and highlight them (this is the next task I wanted to do). – JustTip Mar 11 '17 at 20:30
  • Yep, then a content script and no background page. – wOxxOm Mar 11 '17 at 20:32
  • 1
    Actually, you can highlight the link without a script. Just use the CSS you inject. Also, you can have many content script declarations (`content_scripts` is an array as you can see) for different URL patterns. – wOxxOm Mar 11 '17 at 20:34
  • The only thing I do not like the event chrome.tabs.onActivated is that the URL is displayed after a while and not immediately. It is possible to fix this ? – JustTip Mar 11 '17 at 20:35
  • Why do you use it? Also, `alert` blocks the browser UI which might be the cause. – wOxxOm Mar 11 '17 at 20:38
  • You advised me to use chrome.tabs.onActivated to show current tab url – JustTip Mar 11 '17 at 20:40
  • It was before you told me what you really want to do. Why do you use it now that you know you don't need it? :-) – wOxxOm Mar 11 '17 at 20:41
  • I came up with this task. And now I want to do the first (show URL) and then second (Highlight all url in all tabs) – JustTip Mar 11 '17 at 20:44
  • I've added an answer that sums up the discussion in comments. – wOxxOm Mar 11 '17 at 20:54

1 Answers1

2

Make sure to read the extension architecture overview. You don't need a background/event page which is an entirely separate page inside the extension with its own DOM (document and window) not related to the webpage in any way.

You need a content script that runs alongside the webpage and can access its DOM directly.

manifest.json:

"content_scripts": [{
    "matches": ["<all_urls>"],
    "all_frames": true,
    "js": ["js/content.js"],
    "css": ["css/style.css"]
}],

content.js:

console.log(location.href);

Here you can write normal JavaScript DOM code and access the webpage.

There's no need for DOMContentLoaded wrapper because the content script is injected by default at document_idle which occurs after document_end event. If you need to run the code at document_end exactly, not later, you can specify it explicitly in manifest.json:

"content_scripts": [{
    "matches": ["<all_urls>"],
    "all_frames": true,
    "run_at": "document_end",
    "js": ["js/content.js"],
    "css": ["css/style.css"]
}],

P.S. alert is a counter-productive way of displaying information because it blocks the browser UI.

wOxxOm
  • 65,848
  • 11
  • 132
  • 136
  • I adjusted manifest.json, remove background, but console.log(location.href) did not work – JustTip Mar 11 '17 at 21:12
  • Assuming you've checked the devtools console panel, it can only mean the content script was not injected. You need to reload the page. This is a known problem and there is a solution that [forcefully injects the content script into all pages](https://stackoverflow.com/a/11598753) which might be useful in case you want the extension to produce effect right after it was installed/updated. – wOxxOm Mar 11 '17 at 21:15
  • How can I inject a script for all tabs if chrome.tabs.query doesn't work ? – JustTip Mar 11 '17 at 21:36
  • I try to inject my content.js to all tabs. But when I try to get all tabs using: chrome.tabs.query I get error 'Cannot read property 'query' of undefined' – JustTip Mar 11 '17 at 21:43
  • I need to get all tabs. How can this be done if content_script can't you ChromeAPI? – JustTip Mar 11 '17 at 21:51
  • yeah sorry, you're right. I did not carefully read the documentation. – JustTip Mar 11 '17 at 21:58