My extension popup page gets data from a message from a sand-boxed page & scripts. I need to store this inside the chrome.storage, preferably using the storage.sync method. I'm getting this error:
Uncaught TypeError: Cannot read property 'sync' of undefined
I already added the permissions for storage inside my manifest.json.
... "permissions": ["storage"], ...
chrome.storage.sync undefined?
Google alsostates that no backgroud script is needed:
https://developer.chrome.com/extensions/storage
Quoting: Your extension's content scripts can directly access user data without the need for a background page.
What am I overlooking? Thanks in advance!
function receiveMessage(event) {
var data = event.data;
saveToStorage(data);
};
window.addEventListener("message", receiveMessage, false);
function saveToStorage(data)
{
if (!data) {
console.log('Error: No value specified. Nothing saved to storage.');
return;
}
chrome.storage.sync.set({'data': data}, function() {
console.log('Data saved to storage.');
});
};
Be sure to always reload your extension before testing something new. I never reloaded it before because it wasn't necessary, well until now :)
Also chrome.runtime.lastError comes in very handy!
Related
I'd like to write an extension for Thunderbird that modifies the message display (e.g. insert/replace text/markup/image).
Unfortunately, the documentation is lacking (due to recent changes?).
https://developer.mozilla.org/en-US/docs/Mozilla/Thunderbird/Thunderbird_extensions
is outdated
https://developer.thunderbird.net/
does not have useful examples (yet)
https://thunderbird-webextensions.readthedocs.io/
no examples either
Some examples can be found at
https://github.com/thundernest/sample-extensions
Building on https://github.com/thundernest/sample-extensions/tree/master/messageDisplay
I've modified background.js
browser.messageDisplay.onMessageDisplayed.addListener((tabId, message) => {
console.log(`Message displayed in tab ${tabId}: ${message.subject}`);
console.log(message.id);
browser.messages.getFull(message.id).then((messagepart) => {
console.log(messagepart);
body = messagepart['parts'][0]['parts'][0]['body'];
console.log(body);
body += "modified!";
console.log(body);
});
browser.windows.getCurrent().then((window)=>{
console.log(window.type);
});
browser.tabs.getCurrent().then((tab)=>{
console.log("tab",tab);
});
});
which gives me the message body (using magic indexes) but expectedly, the change is not reflected in the message display.
The window type returned is normal, not messageDisplay.
The tab is undefined despite adding permissions
"permissions": [
"messagesRead",
"activeTab",
"tabs",
"tabHide"
],
but I assume that's because the script is running as background.
So I'd need a script running on the content / access to the tab and then some hints on how to modify the displayed message content (I do not want to modify the message).
Where would I find the equivalent documentation to
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_scripts
specific to Thunderbird?
Specifying content_scripts in manifest.json causes "Error: Error reloading addon messageDisplay#sample.extensions.thunderbird.net: undefined".
executeScript() from background does not seem to work either, even with tabId specified.
This was not possible to do when you wrote your question, the API for modifying displayed messages was missing.
As of this writing (September 2020), the browser.messageDisplayScripts API landed a few days ago, see bug 1504475 and related patch for examples. It works as follows: You can register your content script (to modify the displayed messages) like this
let myPromise = browser.messageDisplayScripts.register({
css: [{
file: "/style.css",
}],
js: [{
file: "/content_script.js",
}],
});
And you can later unregister with
myPromise.then((script) => { script.unregister(); });
You need to register the script just once for all messages (you do not need a listener that would load it each time a message is displayed).
Note that your manifest.json needs to include the messagesModify permission for this to work.
The new API will be in Thunderbird version 82, so if I understand the release process correctly it should be in stable version 88 (unless it is backported before that). You can try it already (v82 is the current EarlyBird).
Documentation https://thunderbird-webextensions.readthedocs.io/en/68/tabs.html#getcurrent
says:
May be undefined if called from a non-tab context (for example: a background page or popup view).
Since the background.js is not called from a tab context the tab is undefined.
I'm working on a Chrome extension that will require the user to log into an account in order to see their content. What I want to do is prevent the user from having to log in every time by saving some kind of cookie or localStorage with relevant login/ session data once they do login.
So far after doing a bit of research it seems that using Google Chromes local storage API would be the best way of doing this (would be great if someone could confirm this).
My issue is with setting and getting local storage. I've setup a dummy local storage scenario here just to try and get Chrome to store ANY kind of local storage for the extension:
Popup.js:
function setCookie(){
chrome.extension.sendMessage({name: 'setLoginCookie'}, function(otherResponse) {
console.log(otherResponse)
})
}
function getCookie(){
chrome.extension.sendMessage({name: 'getloginCookie'}, function(response) {
alert(response)
})
}
event.js:
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
if (request.name == 'setLoginCookie') {
var obj = {test:"test"}
chrome.storage.sync.set(obj, function() {
alert('Data saved');
});
}
if (request.name == 'getLoginCookie') {
chrome.storage.sync.get('test', function(data) {
sendResponse({ screenshotUrl: data.test });
})
}
return true;
});
When the setCookie function is executed I get the alert of 'data saved!' which would indicate to me it has worked but when I check the local storage on my extensions Chrome dev tools there is nothing there and if I call the getCookie function then it doesn't pick up anything.
Here are the permissions in my manifest.json:
"permissions": [
"storage",
"cookies",
"tabs",
"<all_urls>",
"pageCapture",
"downloads"
],
Have I used the wrong approach here? Is using chrome.storage.sync perhaps where i've gone wrong?
Thanks
chrome.storage.sync is not the same thing as local storage, you won't see the data saved using this method in the dev tools Local Storage.
You have a message mismatch. You're using {name: 'getloginCookie'} to send the message and the if statement is checking for getLoginCookie. The difference is the lower case l in the parameter you pass to the sendMessage function.
when I check the local storage on my extensions Chrome dev tools there is nothing there
Dev Tools do not expose chrome.storage inside them.
The "Local Storage" item exposes localStorage instead.
To inspect an extension's chrome.storage, you can use Storage Area Explorer extension or simply call chrome.storage.sync.get(null, (data) => { console.log(data) }) from the console.
Note: you don't have to delegate working with chrome.storage to your Event page. chrome.storage is directly accessible from all extension contexts - background, popup, options, content scripts. Don't layer on Messaging just for this.
I'm trying to develop a restartless firefox extension without the sdk, and I would like to be able to manipulate the DOM of the page, but either the document, content.document or unsafeWindow.document are returning undefined.
My bootstrap.js code:
Components.utils.import("resource://gre/modules/Services.jsm");
function startup(data,reason) {
Components.utils.import("chrome://myextension/content/plugin-min.js");
}
function shutdown(data,reason) {
Components.utils.unload("chrome://myextension/content/plugin-min.js");
}
function install(data,reason) { }
function uninstall(data,reason) { }
and my plugin-min.js code:
document.addEventListener('keydown',activate); // document undefined
content.document.addEventListener('keydown',activate); // content undefined
unsafeWindow.document.addEventListener('keydown',activate); // unsafeWindow undefined
And Mozilla published solution only for SDK users, and google searches I've done brought only these SDKs solutions. :/
But in my case, Does anyone know what I'm missing?
Thank you very much.
Main extension script has no direct access to document. You should inject to document own content-script, and exchange with it via async messaging (port object).
Also, you can provide an array of context script -in that case all of them will be imported:
var panel = panels.Panel({
contentURL: self.data.url("page.html"),
contentScriptFile: [self.data.url("script.js"), self.data.url('libs/jss.js')],
contentStyleFile: self.data.url("style.css"),
onHide: handleHide
});
Not sure about loading order, but after documentready evrything accessible.
More reading in official documentation.
I try to write a Google Chrome extension that simply opens a new tab when I click left-right in a short interval. The JavaScript is no problem but I implemented this as a "content_scripts" script.
In some other threads I read that I can't access the chrome.* APIs from content_scripts (except the chrome.extension API).
Even if it's not necessary to access the chrome.tabs API to open a new window (window.open should do the job) it seems I need it though for opening a new tab with the new tab page which obviously isn't possible via window.open.
So I can't really figure out what is the best way to do that. I could use a background page which I could call from the content_script but I think there should be a much more simple way to do that, I just don't get it.
Anyone have an idea?
I think your content script will have to send a message to your background page to invoke chrome.tabs.create - content scripts cannot use the chrome api, nor can they directly communicate with the background page.
Here's a reference about message passing inside Chrome extensions for further detail, but here's the example code ( modified from the example in said reference )
// in background
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse) {
switch ( request.action) {
case 'newTab' : {
//note: passing an empty object opens a new blank tab,
//but an object must be passed
chrome.tabs.create({/*options*/});
// run callback / send response
} break;
}
return true; //required if you want your callback to run, IIRC
});
// in content script:
chrome.extension.sendMessage({action: "newTab"}, function(response) {
//optional callback code here.
});
simple and easy
document.body.onclick = function openNewWindow( ) {
window.location.href = 'javascript:void window.open( "chrome://newtab" )';
}
manifest:
,"permissions":[
"http://*/*"
,"https://*/*"
]
,"manifest_version": 2
,"content_scripts":[{
"matches":[
"http://*/*"
,"https://*/*"
]
,"js":[
"js/openWindow.js"
]
}]
alright i miss understanding the question... modified
I'm developing an extension for Google Chrome, and have run into some trouble.I created an options.html page and added it to the manifest.json file.The page shows properly.
I saved the options, and then went back to the page on which the extension is supposed to run.
Unfortunately, the Local storage for the options was returning a 'null' instead of the option. If I set the local storage option directly from the extension's JS script, it works fine but not if it was set from the options page.
Any idea how i can access the options.html local storage values from my Javascript file in the extension?
You can set them using either
localStorage["var"]=data;
or
localStorage.var=data;
Load them using
var myvar = localStorage.var;
You can read about the API here.
The correct method is:
if (typeof(localStorage) == ‘undefined’ ) {
alert(‘Your browser does not support HTML5 localStorage. Try upgrading.’);
}
else {
try {
localStorage.setItem(“name”, “Hello World!”); //saves to the database, “key”, “value”
}
catch (e) {
if (e == QUOTA_EXCEEDED_ERR) {
alert(‘Quota exceeded!’); //data wasn’t successfully saved due to quota exceed so throw an error
}
}
document.write(localStorage.getItem(“name”)); //Hello World!
localStorage.removeItem(“name”); //deletes the matching item from the database
}
REFERENCE: http://html5tutorial.net/tutorials/working-with-html5-localstorage.html