just-jeb/angular-chrome-extension

How to use an injected content script

Closed this issue · 10 comments

Thanks for your work on this, has been really helpful.

I was wondering if you knew how to add a content script? I've been racking my brains for a while and have tried every combo of ...

  chrome.tabs.executeScript(null, {
    file: "content.js"
  });

The standard way above works fine for vanilla js but in the context of angular it doesn't seem to work. I presume something webpack related maybe.

I've updated the webpack conf as so...

module.exports = {
  entry: {
    background: "src/background.ts",
    content: "src/content.ts"
  }
};

(dev)

entries: {
        background: "background",
        content: "content"
      }

and the content file transpiles to the dist dir fine. It evens reports to have injected properly with no last runtime error, however I am unable to see any logs or alerts in the websites own console.

Do you kow what might be the way to get this working in the angular context you presented?

thanks :)

Mind creating a fork for reproduction so that I could take a look?

Not sure what your exact use case is but you can try declarative content scripts.

Hey, thanks so much for your reply. I've figured it out as it happens. Let me see if I can find my answer when I'm back at my desk and post it here for posterity :)

That would be much appreciated, thank you.

What was the solution for this problem @garethharding . I'm having the same issue where content script is not running.

This was the gist of what I did if I remember correctly. Maybe errors etc as can't find original version. Not a solution using webpack which i'd have preferred but works well for my needs.

Background script - install your content script via appropriate hooks

// on first install ------------------
chrome.runtime.onInstalled.addListener(() => {
  // on every navigation event ------------------
  chrome.webNavigation.onCompleted.addListener(async () => {
    chrome.tabs.query({ active: true, currentWindow: true }, tabs => {
        if (tabs[0].url.includes("chrome://")) return;
        
        // this injects content script
        chrome.tabs.executeScript(null, { file: "js/content-script.js" }, () => {});
    });
  });
}); // end onInstalled listener

Content script - install angular

(async () => {
    installApp();  
})();

function installApp() {
  document.body.insertAdjacentHTML("beforeend", `<app-root></app-root>`);
  // point these to your own files. localhost here so can use live reload via ng serve
  addScript("http://localhost:4200/runtime.js");
  addScript("http://localhost:4200/polyfills.js");
  addScript("http://localhost:4200/styles.js");
  addScript("http://localhost:4200/vendor.js");
  addScript("http://localhost:4200/main.js");
}

function addScript(src) {
  var s = document.createElement("script");
  s.setAttribute("src", src);
  document.body.appendChild(s);
}

any updates on this one?
Can't you just reference all the compiled angular-related files and reference them under content_scripts in manifest.json

 // some codes omitted for brevity
  "content_scripts": [
    {
       "matches": ["http://*/*", "https://*/*"],
      "js": ["polyfills.js", "runtime.js", "main.js"],
    }
  ]

In theory, we're essentially just injecting everything in angular as part of a content script w/c is loaded on pages specified by matches property.

In this case, we can just create a separate component for any browser_action or page_action functionality.

@chan-dev didn't check that but I don't see why it wouldn't work. Out of curiosity, why do you need Angular in content script? Purely for DI? Or something else?

@just-jeb we're currently working on a chrome extension and sort of had a similar setup where instead of using a popup, we use angular components to show a sidebar w/c is an Angular component and you toggle the sidebar when you press the chrome extension icon and with the ability to pin the sidebar w/c I believe you can't do using a popup.

Yup, sounds about right.