Trying to contact default_script in content_script in chrome extension (JavaScript) does not work

Okay, so I am changing the color scheme of the site using the extension, this is my first time using content_scripts, so yes, I'm a complete beginner, do not hesitate to treat me as one.

The problem is that tabs.connect is not working, do I need a tab id or something else? Here is what I still have:

manifest.json:

{ "manifest_version": 2, "name": "ROBLOX Color Scheme", "description": "Edit the color scheme of the roblox bar! Note: Not created by roblox.", "version": "1.0", "permissions": [ "<all_urls>", "tabs" ], "browser_action": { "default_icon": "Icon.png", "default_popup": "Popup.html" }, "content_scripts": [ { "matches": ["http://www.roblox.com/*"], "js": ["ContentScript.js"] } ] } 

Popup.html:

 <!DOCTYPE html> <html> <head> <p>Choose a color:</p> <input type="color" id="Color" value=""> <button type="button" id="Button">Change Color!</button> </head> <body> <script src="Script.js"></script> </body> </html> 

Script.js

 function ChangeColor() { var TabId; chrome.tabs.query({currentWindow: true, active: true}, function(tabArray) { TabId = tabArray[0]; }); var port = chrome.tabs.connect(TabId, {name: "ColorShare"}); port.postMessage({Color: document.getElementById("Color").value}); } document.getElementById('Color').addEventListener("click", ChangeColor); 

ContentScript.js:

 var Color; chrome.runtime.onConnect.addListener(function(port) { if (port.name == "ColorShare") then { port.onMessage.addListener(function(msg) { Color = msg.Color; }); } }); document.getElementsByClassName("header-2014 clearfix")[0].style.backgroundColor = Color; 

All help is appreciated, thanks for taking the time to answer my question!

EDIT: now some files have changed thanks to me and the help of the one who answers, now they don't make mistakes, but nothing changes, any help you could give would be great! Here are the current codes:

Script.js

 chrome.tabs.query({currentWindow: true, active: true}, function(tabArray) { var TabId = tabArray[0].id; var port = chrome.tabs.connect(TabId, {name: "ColorShare"}); function ChangeColor() { port.postMessage({Color: document.getElementById("Color").value}); } document.getElementById('Color').addEventListener("click", ChangeColor); }); 

ContentScript.js:

 chrome.runtime.onConnect.addListener(function(port) { if (port.name == "ColorShare") { port.onMessage.addListener(function(msg) { document.querySelector("header-2014 clearfix").style.backgroundColor = msg.Color; }); } }); 

Edit: This problem has been resolved. I had to use chrome.storage.sync.set and chrome.storage.sync.get, which fully supports content scripts! I will publish the scripts soon!

+7
javascript google-chrome google-chrome-extension communication content-script
source share
5 answers

I think you misunderstand the idea of โ€‹โ€‹a port. The port is used for multiple messages in a session. But the port is destroyed when the session ends (for example, when the tab is closed). Regardless, you should not recreate the port every time you click.

In one of your comments, a page refresh was mentioned, which makes me think that you want this color to remain when the pages reload. This makes sense in terms of the user interface, but you really should have mentioned it at the beginning.

As I said, ports are destroyed when the tab is closed (or reloaded). If you want the value to be saved, you will need a storage mechanism, for example chrome.storage (you can also use local storage, but the previous link gives several reasons why not).

manifest.json just requires "permissions": [ "activeTab", "storage" ], You probably also want page actions, not a browser action (or none of them will get this).

ContentScript.js:

 var myBgColor = false; chrome.storage.sync.get("myBgColor",function(items) { if ( items.myBgColor ) { myBgColor = items.myBgColor; document.querySelector(".navbar").style.backgroundColor = myBgColor; } }); chrome.runtime.onMessage.addListener(function(request,sender,sendResponse) { if ( request.setColor ) { document.querySelector(".navbar").style.backgroundColor = request.setColor; chrome.storage.sync.set({"myBgColor":request.setColor}); } else if ( request.getColor ) { sendResponse({"myBgColor":myBgColor}); } }); 

I changed the argument to querySelector since I could not find the items you were looking for on the index page.

Popup.html:

 <!DOCTYPE html> <html> <body> <p>Choose a color:</p> <input type="color" id="color" value=""> <button type="button" id="button">Change Color!</button> <script src="Script.js"></script> </body> </html> 

I'm not sure why you had your inputs at the top of the page.

Script.js (but please rename the file to something more descriptive than Script.js):

 document.getElementById('button').addEventListener("click",function() { chrome.tabs.query({currentWindow: true, active: true},function(tabArray) { chrome.tabs.sendMessage(tabArray[0].id,{"setColor":document.getElementById("color").value}); }); }); chrome.tabs.query({currentWindow: true, active: true}, function(tabArray) { chrome.tabs.sendMessage(tabArray[0].id,{"getColor":1},setCurColor); }); function setCurColor(response) { if ( response.myBgColor ) { document.getElementById("color").value = response.myBgColor; } } 

Wed like to have ContentScript.js message when loading Script.js if the background color is previously set. Unfortunately, Script.js only exists when weve clicked on the action icon. So we have Script.js ask ContentScript.js for the current color (if it was set).

As Ruvenka Madhushan noted, your original script failed (in part) because you assumed that the asynchronous chrome.tabs.query would complete before moving on to the next line of code. Asynchronous javascript is very powerful, but it is not responsible for the fact that the code is not complete. You need to use nested function calls, either anonymously (for example, using Script.js s onclick) or naming a utility function (as with setCurColor ). (There are also javascript libraries that will help with asynchronous functions, but I don't know them.)

Everything works, but there is a small problem: Popup.html closes when it loses focus - in this case, when you click on the color picker tab. (Very bad) to open a pop-up window and right-click and select Inspect Element. This calls up the console for the popup and prevents the popup from closing when you select a color. Another option might be to enable color picker in the iframe inside the popup (I don't know if this is possible).

But since it was about expansion options, a better alternative would be to use a page. It will also give much more room for your html. For example, you might want to consider a button to remove localStorage.myBgColor so that you can return the default value. Or other site customization options, since Im hoping you wonโ€™t go for all these problems, just change the color. And it will hide the action icon, since presumably you are going to set your parameters, and then want to forget about the existing extension.

+4
source share

Well, what you are trying to do is to do this via messaging. I see how you might have thought that centenarians are the way to go, but it is not. You will need to use a storage system, especially chrome.storage, which is fully compatible with content scripts!

Instead of using a browser action, you can simply create a settings page that saves the color in chrome.storage, where content scripts can restore it. The options page is just plain HTML, but the code can be a little complicated for someone just getting started.

The options page you want will be something like this:

 <!DOCTYPE html> <html> <head><title>Choose A ROBLOX Color</title></head> <body> <h>Color:</h> <input type="color" id="Color" value=""> <div id="Status"></div> <button id="Save">Save</button> <script src="Options.js"></script> </body> </html> 

Options.js takes the parameters and saves it to chrome.storage using the parameters selected on the HTML page above. He does this using chrome.storage.sync.set

Options.js will look something like this:

 // Saves options to chrome.storage function save_options() { var color = document.getElementById('Color').value; chrome.storage.sync.set({ Color: color }, function() { // Update status to let user know options were saved. var status = document.getElementById('Status'); status.textContent = 'Options saved.'; setTimeout(function() { status.textContent = ''; }, 750); }); } // Restores select box and checkbox state using the preferences // stored in chrome.storage. function restore_options() { // Use default value color = 'red' chrome.storage.sync.get({ Color: 'red' }, function(items) { document.getElementById('Color').value = items.Color; }); } document.addEventListener('DOMContentLoaded', restore_options); document.getElementById('Save').addEventListener('click', save_options); 

Finally, the content of the script retrieves the data using chrome.storage.sync.get, and then sets the color of the site panel.

and the contents of the script will look like this:

 chrome.storage.sync.get({ Color: 'red' }, function(items) { document.getElementsByClassName("header-2014 clearfix")[0].style.backgroundColor = items.Color; } ); 

The manifest file must have permission "storage" and must include "options_page"

If you don't know what manifest.json will look like, it will be like this:

 { "manifest_version": 2, "name": "ROBLOX Color Scheme", "description": "Edit the color scheme of the roblox bar! Note: Not created by roblox.", "version": "1.0", "options_page": "Options.html", "permissions": [ "<all_urls>", "storage" ], "content_scripts": [ { "matches": ["http://www.roblox.com/*"], "js": ["ContentScript.js"] } ] } 
+2
source share

Not tested, but I think you should do this:

Script.js:

 chrome.tabs.query({currentWindow: true, active: true}, function(tabArray) { var TabId = tabArray[0]; var port = chrome.tabs.connect(TabId, {name: "ColorShare"}); function ChangeColor() { port.postMessage({Color: document.getElementById("Color").value}); }); document.getElementById('Color').addEventListener("click", ChangeColor); } 

ContentScript.js:

 chrome.runtime.onConnect.addListener(function(port) { if (port.name == "ColorShare") { port.onMessage.addListener(function(msg) { document.querySelector("header-2014 clearfix").style.backgroundColor = msg.Color; }); } }); 

And you should use chrome.tabs.sendMessage instead of chrome.tabs.connect

0
source share

Script.js

 function ChangeColor() { var tabId; chrome.tabs.query({currentWindow: true, active: true}, function(tabArray) { tabId = tabArray[0].id; chrome.tabs.sendMessage(tabId,{color: document.getElementById("Color").value}); }); } document.getElementById('Color').addEventListener("click", ChangeColor); 

ContentScript.js

 chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) { document.getElementsByClassName("header-2014 clearfix")[0].style.backgroundColor = msg.color; }); 

This applies to your asynchronous problems, as well as switching to individual messages, and not for a long time. If you do not send a lot of information back and forth, individual messages are probably better than opening a port. You can also add some description to the message as additional fields, for example:

 chrome.tabs.sendMessage(tabId,{type: 'setColor', color: stuff}); 

Then you can check the type in the listener and split it like this.

0
source share

I think your connection doesnโ€™t need a connection for a long time, just use a simple one-time request . By the way, since you are using a long-term connection, I am going to answer that.

First you have a button with the identifier Button , but you attach a click event handler to enter the color document.getElementById('Color').addEventListener("click", ChangeColor); you need to change this, here is my code for popup.html.

popup.html

 <!DOCTYPE html> <html> <head> <p>Choose a color:</p> <input type="color" id="ColorVal"> <button type="button" id="color">Change Color!</button> </head> <body> <script src="script.js"></script> </body> </html> 

Change the identifier accordingly in Script.js. Also, your edited Script.js and ContentScript.js are fine. Your first code fails due to a request for tabs, takes a long time. Since tabid does not exist, the port declaration is not executed. Hope this helps you.

0
source share

All Articles