Chrome extension : access local storage more than once in content script - google-chrome

I know how to access localstorage in content script, but only one time. I access it via sendRequest, but when I try to use this method in an event function, the jvascript file doesn't even load.
Is it possible to access to the options many times, like whenever the onclick event is fired ?
I looked on the google code website and found something to create a connection between content script and background using chrome.extension.connect(). Do i need to use that ?
Thanks !

Actually you can use sendRequest as many times as you can, but if you want to do it in another way you can open a long-lived channel (or what I call, "message tunnel") between content script and background page to communicate.
In your content script, you can use
var port = chrome.extension.connect({name: "myChannel"});
to open up a channel.
Then you can use
port.postMessage({message: "This is a message."});
to send a new message to the background page.
port.onMessage.addListener(function(msg) { }) listens to a new message.
In your background page,
chrome.extension.onConnect.addListener(function(port) {
port.onMessage.addListener(function(msg) {
if(port=="myChannel"){
console.log(msg+" from port "+port) //Gives you the message
}
})
})
listens to a new message in a specific port.

Related

chrome.runtime.connect from Content Script and DevTools Page JS failing to connect

I have reviewed this question/answer as well:
Communicating between Chrome DevTools and content script in extension
It looks like they are doing something slightly different than I am trying to do, so I don't know how much it applies. Maybe I absolutely need a background.js file?
I have also reviewed this question:
extension using background, content and devtools together
Here it looks like they are not using long-lived connections as documented here (which is what I need):
https://developer.chrome.com/extensions/messaging#connect
Anyway, previous question aside here is my problem:
I have tried this a few ways over the span of a few hours so I am pretty convinced I am just missing something here to make this work.
The crux of my issue is that:
chrome.runtime.onConnect.addListener(function(){...})
the listener here will never fire.
Here's my setup:
My extension uses a Content Script and a DevTools page. From both locations, the Content Script and DevTools page, I have tried to enabling messaging though chrome.runtime. My boilerplate initialization looks like this for starting the connection:
console.log('initializing connection');
var port = chrome.runtime.connect({name: 'My Extension'});
console.log('port', port.name);
and this for waiting for onConnect:
chrome.runtime.onConnect.addListener(function(port){
console.log('got connection!!!!!!');
});
My onConnect handler will never be invoked. I have tried placing the connection code (chrome.runtime.connect({...})) in the Content Script and in the DevTools page JS while placing the handler initialization the opposite location to no avail.
In other words, if I place the connection code in the Content Script, I will place the handler initialization into the DevTools page JS. If I place the connection code into the DevTools page JS I will place the handler initialization into the Content Script.
In both cases, I receive no runtime errors, however, I also never see the console.log('got connection!!!!!!'); get called. Yes, I am looking at the DevTools page console when I have the handler initialization located in the DevTools page JS.
I simply must just be misunderstanding something or missing something in the docs. Can anyone point me in the right direction re: having DevTools Page JS communicate with a Content Script?
As per Xan comment, communication between devtools extension and content scripts should be done through the use of a background script. The process is basically:
(devtools script) - create the connection ( and sends or listens to messages through the connection port opened)
(background script) - listen for the connection to be created, receiving the port and using it to listen or broadcast messages
This is useful if you want to keep a long lived connection, so basically you will need a couple of messages to be passed back and forward for a single process. If you want simple messages to be passed from time to time, but don't need multiple messages being passed back and forth then you might implement a more simple communication:
(devtools script) - sends a message using the chrome.runtime.sendMessage
(background script) - listens for messages send by any extension associated with it using the chrome.runtime.onMessage.addListener()

Modify local storage via popup, and use stored values in contentscript

I'm trying my hand at creating a chrome extension, but am running into a wall.
I want to be able to use the browser-action popup to write/modify values into local storage (extension storage).
Then, I want to use the stored values in a content script.
From what I've read, it looks like I need a background file? but I'm not sure.
Some coded examples would be extremely appreciated!
Thanks for your help!
You can avoid using a background page as a proxy if you use chrome.storage API. It's a storage solution that is available from Content Scripts directly.
Here is a comparison between it and localStorage in the context of Chrome extensions.
An important thing to note is that it's asynchronous, making code slightly more complicated than using localStorage:
/* ... */
chrome.storage.local.get('key', function(value){
// You can use value here
});
// But not here, as it will execute before the callback
/* ... */
But to be fair, if you go with the background being the proxy for data, message passing is still asynchronous.
One can argue that once the data is passed, localStorage works as a synchronous cache.
But that localStorage object is shared with the web page, which is insecure, and nobody stops you from having your own synchronous storage cache, initialized once with chrome.storage.local.get(null, /*...*/) and kept up to date with a chrome.storage.onChanged listener.
Background pages can access the localStorage variables saved by your extension. Your content script only has access to the localStorage of the website open in a specific tab. You will therefore need to send the variables from the background page to the content script. The content script can then access these variables.
The following code saves a localStorage variable in the background script and then sends it to the content script for use.
Since you requested a coded example, I've written you one. This project would have a background page and a content script. Using localStorage in your popup will allow the background page to access these variables for use in the content script.
Something like this:
background.js
// When a tab is updated
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo) {
// When the tab has loaded
if(changeInfo.status == 'complete') {
// Query open tabs
chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function (tabs) {
// Get URL of current tab
var tabURL = tabs[0].url;
// If localStorage is not empty
if(localStorage.length != 0) {
// Set a local storage variable
localStorage.helloworld = "Hello World";
// Send message to content script
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
// Send request to show the notification
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
});
});
}
});
}
});
contentscript.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
// Use the local storage variable in some way
if(request.greeting == "hello") {
var hello = localStorage.helloworld;
// do something with the variable here
}
});
Once you have this working, consider switching to chrome.storage

Accessing data from local storage by content scripts

I'm trying to access local storage from content scripts but even though the message passing is working, the output isn't as expected.
CONTENT SCRIPT
var varproxy = localStorage.getItem('proxy'); //gets data from options page saved to local storage
var proxy = "proxystring";
chrome.runtime.sendMessage({message:"hey"},
function(response) {
proxy = response.proxy;
console.log(response.proxy);
}
);
console.log(proxy);
BACKGROUND PAGE (For message passing)
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse)
{
if (request.message == "hey")
{
sendResponse({proxy: varproxy});
console.log('response sent');
}
else
{sendResponse({});}
});
The console logs the proxy as the value of varproxy and also "response sent" but the
console.log(proxy);
logs the proxy as "proxystring"
Why isn't the value of proxy getting changed? How do I change it as required?
Message sending -- among lots of chrome API function -- is an asynchronous function. The interpreter won't wait for the response, but jumps to the next line. So it can easily happen that log(proxy) will be evaluated first, since communicating with the background page takes some time. As soon as the response is received, the value of proxy changes.
Might I recommend you try out another implementation? What about Chrome Storage?
Then you don't need any message passing at all, because you can access chrome storage within content scripts.
Example, this is something I do in my extensions' content script to grab several values from chrome storage:
chrome.storage.sync.get({HFF_toolbar: 'yes',HFF_logging: 'yes',HFF_timer: '1 Minute'},
function (obj) {
toolbar_option = obj.HFF_toolbar;
logging_option = obj.HFF_logging;
timer_option = obj.HFF_timer;
/* the rest of my content script, using those options */
I personally found this approach much easier, for my purposes anyway, than message passing implementations.

How to get appWindow from Chrome.app.window.create

I am trying to write a chrome.app that is able to open and close chrome.app windows on both displays of a system that is configured with two monitors. When launched, the chrome application establishes a socket connection with a native application running on the same computer, I also open a hidden window via chrome.app.window.create to keep the chrome application up and running. The native application then reads a configuration file and then sends a series of ‘openBrowser’ commands to the chrome application via the socket.
When the chrome application receives an ‘openBrowser’ command, the chrome application makes a call to the chrome API method chrome.app.window.create, passing the create parameters AND a callback function. A code snippet is below:
NPMBrowserManager.prototype.openBrowser = function (browserId,htmlFile,browserBounds,hidden,grabFocus)
{
var browserManager = this;
var createParameters = {};
createParameters.bounds = browserBounds;
createParameters.hidden = hidden;
chrome.app.window.create(htmlFile,createParameters,function(appWindow)
{
// Check to see if I got a non-undefined appWindow.
if(appWindow !== null)
{
browserManager.browsers.push({"browserId":browserId,"window":appWindow});
console.info("NPMBrowserManager.openBrowser: Added browser, id =" + browserId + ", count =" + browserManager.browsers.length);
}
});
}
Unfortunately, the ‘appWindow’, parameter passed in the create callback is always undefined. I suspect it has something to do with the fact that the method openBrowser is itself being called by another method that processes commands received from the native application. However, the window opens exactly here and when I want to to, I just can’t seem to cache away any information about the new window that can be used later to close or move the window.
I want to be able to cache away the appWindow so that I can close or modify the created window later on in the workflow.
As a side note, I’ve noticed that appWindow is NOT undefined if I call the openBrowser method from within the callback that is associated with the chrome.app.runtime.onLaunched event. I suspect it has something to do with the current script context. I was not able to find any chrome.app documentation that goes into any detail about the chrome app architecture.
I would GREATLY appreciate it if anyone out there can explain to me how I can get the appWindow of the window that is created in the chrome.app.window.create method. By the way, I have also tried calling chrome.app.window.current to no avail… Very frustrating!!!
I’d also be interested in any documentation that might exist. I am aware of developer.chrome.com, but could not find much documentation other than reference documentation.
Thanks for the help!
Jim

Chrome extension - Message Passing FROM Background To contents script

I found numerous ways to send data from contents TO background.js actively.
However, it there any active way to notify or send message FROM background.js TO contents script?
Seems like the usual mean to achieve message passing is addListener in background, and passing message from contents and get return value as call back.
Since the port keeps changing as I open new pages, opening port seems not an option.
I need way around : sending message from background and contents has listner.
In details of my use case is ..
I have Cookie change listener in background.js (chrome.cookies.onChanged.addListener)
and I'd like to notify to contents script every time cookies has changed/updated.
in background.js
function cookieUpdate(info) {
// need to notify to contents script
};
chrome.cookies.onChanged.addListener(cookieUpdate);
Have a try on chrome.tabs.sendRequest(tabId, {}, callback);