76

General Questions

Hello! I'm delving into the world of Chrome Extensions and am having some problems getting the overall workflow down. It seems that Google has recently switched to heavily advocating Event Pages instead of keeping everything in background.js and background.html. I take part of this to mean that we should pass off most of your extension logic to a content script.

In Google's Event Page primer, they have the content script listed in the manifest.json file. But in their event page example extension, it is brought in via this code block in background.js: chrome.tabs.executeScript(tab.id, {file: "content.js"}, function() { });

What are the advantages of doing it one way over the other?

My Code

I'm going forward with the programatic way of injecting the content script, like Google's example.

manifest.json

{
    "manifest_version": 2,
    "name": "Test",
    "description": "Let's get this sucker working",
    "version": "0.0.0.1",
    "permissions": [
        "tabs",
        "*://*/*"
    ],
    "background": {
        "scripts": ["background.js"],
        "persistent": false
    },
    "browser_action": {
        "default_icon": "icon.png"
    }
}

background.js

chrome.browserAction.onClicked.addListener(function() {
    console.log("alert from background.js");
    chrome.tabs.executeScript({file: "jquery-2.0.2.min.js"}, function() {
        console.log("jquery Loaded");
    });
    chrome.tabs.executeScript({file: "content.js"}, function() {
        console.log("content loaded");
    });
});

content.js

console.log('you\'r in the world of content.js');
var ans = {};

ans.createSidebar = function() {

    return {
        init: function(){
            alert("why hello there");
        }
    }
}();

ans.createSidebar.init();

I am able to get the first 3 console.log statements to show up in the background page's debugger. I'm also able to get the alert from content.js to show up in any website. But I'm not able to see the console.log from content.js, nor am I able to view any of the JS from content.js. I've tried looking in the "content scripts" section of the background page debugger's Sources tab. A few other posts on SO have suggested adding debugger; statements to get it to show, but I'm not having any luck with anything. The closest solution I've seen is this post, but is done by listing the content script in the manifest.

Any help would be appreciated. Thanks!

Community
  • 1
  • 1
NoR
  • 975
  • 1
  • 7
  • 8
  • 1
    Your question solved my problem. By injecting content script through the manifest, I was not able to interact with the webpage's DOM in a true sense. Now, loading contentScript through browser_action solved my issue. Thanks. Appreciated. – jainashish Nov 17 '17 at 07:21

4 Answers4

107

Content scripts' console.log messages are shown in the web page's console instead of the background page's inspector.

Adding debugger; works if the Developer Tool (for the web page where your content script is injected) is opened.

Therefore, in this case, you should first activate the Developer Tool (of the web page) before clicking the browser action icon and everything should work just fine.

方 觉
  • 4,042
  • 1
  • 24
  • 28
  • 1
    Excellent, that works! Is the `debugger;` statement always needed to get the debugger to recognize content scripts in the extension environment? It seems like you get one pass to make breakpoints. Any subsequent times you try to run the extension, the content scripts are loaded into a new environment and you lose your original breakpoints. – NoR Jun 15 '13 at 13:57
  • 1
    Debugger will persist page loads and will always break if you have the Developer Tool (F12) open. They are hard coded into your script, so don't forget to remove them later. Debugger will work on any javascript, they are not exclusive to content-scripts. – QFDev Jun 15 '13 at 17:50
  • 2
    If the content script has errors such as mismatched brackets (eg. forgetting to close `)` after passing an inline function as an argument), no error is given and it fails silently even with `debugger`. This is really frustrating. How can you debug this? – jozxyqk Nov 23 '13 at 06:55
  • where do you put "debugger;" in background.js or contextscript.js? Where exactly? – jim Sep 23 '20 at 17:43
  • So adding a `debugger;` on is the only way to be able to view the `console.log` statements? – libby Jun 17 '21 at 20:07
  • Adding `debgger;`.. _where_? A full log statement example wouldn't hurt – abbood Jul 24 '23 at 06:28
  • The debugger should be added within the content script file – aaronmbmorse Aug 14 '23 at 20:08
3

I tried to use the debuggermethod, but it doesn't not work well because the project is using require.js to bundle javascript files.

If you are also using require.js for chrome extension development, you can try adding something like this to the code base, AND change eval(xhr.responseText) to eval(xhr.responseText + "\n//@ sourceURL=" + url);. (like this question)

Then you can see the source file in your dev tool (but not the background html window)

DevGrowth.Tech
  • 1,523
  • 17
  • 23
1

There are two ways you can do this:

  1. Accessing it via the service worker (background.js)
  2. Using console.log() (recommended)

The easiest as you may guess correctly is option 2 and is the recommended solution on Google Chrome docs

To get this to work you have to inspect the current page you are running the content.js script and not the popup or background element.

Here's an example:

// content.js
console.log('Hello World!');

In matches: key, specify the URL you want to run the script. You can use ["<all_urls>"] to inject the script on all permitted URLs.

// manifest.json
"content_scripts": [
    {
      "matches": ["https://www.google.com/"],
      "js": ["content.js"]
    }
  ],

Now when you visit google.com and inspect the console, you'll see the "Hello World" string.

Victor Eke
  • 109
  • 6
0

manifest v3

You can add console.log statements to your content scripts.

This is one of the best ways to debug an application.

Let's say you want to access a DOM node from the content script.

const node = document.querySelector("selector")

node will be Element instance if it exists else it will be null

If you can see the node in the Elements tab but not able to access it via content script then the node might have not been loaded at the time you accessed it.

Follow this answer to fix this issue.

Anjan Talatam
  • 2,212
  • 1
  • 12
  • 26