0

Following up on a previous post, I am now trying to create a version of a Chrome extension that does not specify content_scripts: or matches: in the manifest.json file; instead the content script is to be injected programmatically by a en event triggered from the options page which prompts the user to grant optional permissions for executing the content script. The rationale is to be able to have the extension working on pages from hosts with different top-level domain names (see previous post for details). I have read the documentation on this and tried to connect the dots, but I'm not quite getting there.

Below is a demo version of what I have created so far. I manage to get the optional permissions request processed and the user prompt for granting that request shown (the alert "granted!" is displayed). However, when I try to have the message listener in background.js execute the script content.js (by removing the /* commented-out code */ there), I get the error message

Unchecked runtime.lastError: Cannot access contents of url "chrome-extension://[blah]/options.html". Extension manifest must request permission to access this host.

Any guidance as to what I have missed here would be most welcome.

I also have a second question: since I am using jQuery in the content.js script, do I have to execute the jQuery.js file as well in response to the granted permission, and if so, should that be done by adding another separate chrome.tabs.executeScript() command?

manifest.json:

{
  "manifest_version": 2, 
  "name": "My Extension",
  "version": "1",
  "description": "Demo extension",
   "options_page":"options.html",
   "background": {
    "scripts": ["background.js"],
    "persistent": false
  },        
  "optional_permissions":["tabs","https://*/*"],
  "permissions": ["activeTab","storage"]

  }

options.html:

<html>
<head> 
<style>
button#permreq{font-size:2em;}
</style>
</head>
<body>
<button id="permreq">Click this button to enable My Extension</button>
<script src="jQuery.js"></script>
<script src="options.js"></script>
</body>
</html>

options.js:

jQuery(function($){
  $(document).ready(function(){
    $("button#permreq").click(function(){    
        chrome.permissions.request({
          permissions: ['tabs'],
          origins: ["https://*/*"]
        }, function(granted) {
          if (granted) {
            chrome.runtime.sendMessage("granted");
          } else {
            alert("denied");
          }

      });
    });
  });
});

background.js:

chrome.runtime.onMessage.addListener(
    function(message, callback) {
      if (message == "granted"){
        /*chrome.tabs.executeScript({
          file: "content.js"
        });*/
        alert("granted!");//no errors as long as above code is commented out
      } else{
        alert("denied");
      }
  });
danbae
  • 319
  • 1
  • 5
  • 18
  • 1
    executeScript without parameters runs the script in the active tab, which is your options page, but executeScript is only for web pages, it can't run scripts in the extension pages. You probably want to inject into all other tabs, [example](/a/11598753). You'll also probably want a listener for tab status change like I suggested in the previous topic e.g. chrome.tabs.onUpdated. – wOxxOm Nov 26 '19 at 04:10
  • Yes I did realise that after posting, that executeScript was not directed to the page I wanted to be modified. But is there a way to use the options page to direct script injection to a _specific_ tab, or do I use the popup or other element for that? I did manage to get a working code injection into a specific tab by triggering action from a popup item, but then that code was lost from the tab upon reload. Is that how it works, or can such programatically injected code be made persistent like in the case of declarative injection? – danbae Nov 26 '19 at 10:20
  • I'd like to post the code I now have, but I don't know whether to edit the present post (rather heavily) or create a new post. What's the SO-kosher way? – danbae Nov 26 '19 at 10:22
  • As I suggested you can/should use chrome.tabs.onUpdated or declarativeContent API. – wOxxOm Nov 26 '19 at 11:39
  • I did that – put the addition of a chrome.tabs.onUpdated.addEventListener() as part of the response to the granting of permission. Oddly, it works for a few rounds of updating, then somehow derails, so I have to ask for permission again via the popup to restart it. I put in an alert that goes up everytime the listener reacts, and that stops too, so it is not something in the content script that causes this. – danbae Nov 26 '19 at 14:09
  • chrome.tabs.onUpdated should be registered globally like this: chrome.permissions.contains({origins: ["https://*/*"]}, ok => { if (ok) { add the listener } }) – wOxxOm Nov 26 '19 at 15:36
  • Thank you. I now have managed to write some code that does what I want, except that the initial permission has to be requested _twice_ before the content script runs. I would like to show the code here but I don't know whether it should be entered as an attempted answer or an edit to the original post. Could you please advise? – danbae Nov 27 '19 at 16:07
  • I guess it would make sense to overwrite the question using the new code and info because no one answered it yet so modifying it won't make an answer irrelevant. – wOxxOm Nov 27 '19 at 16:15
  • On second thought, I created a new question instead since not even the subject line of the present post is relevant anymore to the new question. Link: https://stackoverflow.com/questions/59075511/programmatic-injection-of-chrome-extension-content-script-using-popup – danbae Nov 27 '19 at 17:28

0 Answers0