localStorage in a Firefox extension - javascript

I am trying to access the localStorage of a page from a Firefox extension. My understanding is that content gives a reference to the window of the current page. When I try and access the localStorage for the page with content.localStorage, I think I am getting a reference to it. However, when I try content.localStorage.length, I get nothing.
Attached is the code in question.
var myExtension = {
init: function() {
var appcontent = document.getElementById("appcontent"); // browser
if(appcontent)
appcontent.addEventListener("DOMContentLoaded", myExtension.onPageLoad, true);
},
onPageLoad: function(aEvent) {
var doc = aEvent.originalTarget;
alert(content.localStorage) // alerts "[object XPCNativeWrapper [object Storage]]"
alert(content.localStorage.length) // alerts nothing
}
window.addEventListener("load", function() { myExtension.init(); }, false);
EDIT#1: More information.
try{
alert(content.localStorage.getItem('todoData'))
alert(content.localStorage.length)
} catch (e){
alert(e)
}
The length is throwing the exception "[Exception... "Component is not available" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)"
localStorage.length works when I have it on a standard web page in Firefox, but content.localStorage.length dose not work from the Firefox extension. Now I'm confused...

From a Firefox extension, you can access the localStorage object with window.content.localStorage, for example:
var ls = window.content.localStorage;
ls.setItem("myvariable", "myvalue");
var item = ls.getItem("myvariable");
Anything else will give you a "Component not available" error.
As an aside, globalStorage doesn't work this way. You can't use it at all with an extension because the object is only available if it's run from a server.

Using NsIDOMStorageManager xpcom interface you can get your local storage information.
https://developer.mozilla.org/en/XPCOM_Interface_Reference/NsIDOMStorageManager

use content.localStorage.wrappedJSObject.myVariable

Related

Listen(capture) an iframe console logs

I'm trying to catch console logs of an iframe which I don't have access to its source and its implementation.
<iframe src="an http address" name="my-iframe" allowFullScreen/>
When the iframe logs data I see them in my console. But the problem is,
this piece of code
// define a new console
var console = (function(oldCons){
return {
log: function(text){
oldCons.log(text);
if(text === "hi"){
alert("text")
}
},
info: function (text) {
oldCons.info(text);
if(text === "hi"){
alert("text")
}
},
warn: function (text) {
oldCons.warn(text);
if(text === "hi"){
alert("text")
}
},
error: function (text) {
oldCons.error(text);
if(text === "hi"){
alert("text")
}
}
};
}(window.console));
//Then redefine the old console
window.console = console;
Which I got from this post is not working for the iframe logs. It only works on my app console logs.
If the src is a different domain, and you can't run code directly on the other domain (for example, by being able to modify or insert a .js into it), then there's nothing you can do. This is for security reasons: browsers don't want to leak any information between domains unless the sender of the information deliberately allows it.
If you can alter code on the other domain, you could monkeypatch the console and have it pass the log information to the parent window with postMessage so that the parent can do something with it.
If you happen to be trying to examine messages for your personal use only (rather than for use by random people on the internet), you can modify your browser to run your custom JavaScript on the other domain with a userscript, by using a userscript manager like Tampermonkey.

Firefox extension: Open window and write dynamic content

I have developed a Chrome Extension and it's mostly compatible to firefox web-extensions API. Just one problem:
In Chrome Extension i have popup.js and background.js. User click's a button, popup.js does chrome.sendMessage to background.js where data is received and afterwards (popup.html may be closed meanwhile) i just call in background.js:
newWin = window.open("about:blank", "Document Query", "width=800,height=500");
newWin.document.open();
newWin.document.write('<html><body><pre>' + documentJson + '</pre></body></html>');
// newWin.document.close();
so that works fine in Chrome extension but not in firefox. I read here (https://javascript.info/popup-windows) that for safety reasons firefox will only open with a "button click event". And if i move above code to popup.js, inside button-click-evenListener, it will open this way (but i dont have the data prepared yet, thats really not what i want)
So i tried everything i found but i dont get the chrome.tabs.executeScript running. Here is my code with comments:
popup.js
// working in firefox and chrome (popup.js)
const newWin = window.open("about:blank", "hello", "width=200,height=200");
newWin.document.write("Hello, world!");
// not working firefox: id's match, he enters function (newWindow) but document.write doing nothing (but no error in log)
// not working chrome: doesnt even enter "function (newWindow)""
chrome.windows.create({
type: 'popup',
url: "output.html"
}, function (newWindow) {
console.log(newWindow);
console.log(newWindow.id);
chrome.tabs.executeScript(newWindow.tabs[0].id, {
code: 'document.write("hello world");'
});
});
background.js
(created local output.html and gave several permissions in Manifest.json - tabs, activeTab, output.html, , about:blank)
// opening but executeScript not working in firefox: Unchecked lastError value: Error: The operation is insecure.
// opening but executeScript not working in chrome: Unchecked runtime.lastError: Cannot access contents of url "chrome-extension://plhphckppghaijagdmghdnjpilpdidkh/output.html". Extension manifest must request permission to access this host
chrome.tabs.create({
// type: 'popup',
url: "output.html"
}, function (newWindow) {
console.log(newWindow);
console.log(newWindow.id);
chrome.tabs.executeScript(newWindow.id, {
code: 'document.write("hello world");'
});
});
How can I get the data into the new window/popup from background.js - i can open an empty page from there, so it's only about getting executeScript() running
Thanks to #wOxxOm for pointing me to a data URI to transport the json document into the browser from background.js.
While searching for a javascript method to build a data URI i found this thread, with the suggestion to create a Blob :
https://stackoverflow.com/a/57243399/13292573
So my solution is this:
background.js
var documentJson = JSON.stringify(documents, null, 2)
let a = URL.createObjectURL(new Blob([documentJson]))
chrome.windows.create({
type: 'popup',
url: a
});

Javascript Console.log Not working in Chrome, or Firefox

I am doing a very simple:
console.log("Testing");
along with :
alert("testing");
The Alert works (so I know the javascript is working) but I'm unable to see the log. When I use Firefox I get the following error:
The Web Console logging API (console.log, console.info,
console.warn, console.error) has been disabled by a script on this
page.
What is going on? I have looked at the following topics, but none have helped:
Chrome: console.log, console.debug are not working
console.log quit working in Chrome
Console.log not working in Chrome [closed]
why does console.log not output in chrome?
Console.log not working at all
I have also made sure that the funnel is working and that logging is turned on.
What else could the problem be?
I just came across this problem after a Firefox update and managed to fix it. Here's the code that caused the problem:
/* IE fix that allows me to still log elsewhere */
if (typeof(console)=="undefined") {
var console = {
output: null,
log: function (str) {
// we can't emulate the console in IE, but we can cache what's output
// so that IE users can get it via console.output
if (!this.output) this.output = new Array();
this.output.push(new String(str));
}
};
window.console = console;
}
In the previous version of FireFox, "var console;" wouldn't get executed. Now it seems to have added some sort of branching/prediction mechanism. Seeing that I may define a variable called console with global scope, it disables window.console.
I fixed this issue by renaming var console; to var cons;
/* IE fix that allows me to still log elsewhere */
if (typeof(console)=="undefined") {
var cons = {
output: null,
log: function (str) {
// we can't emulate the console in IE, but we can cache what's output
// so that IE users can get it via console.output
if (!this.output) this.output = new Array();
this.output.push(new String(str));
}
};
window.console = cons;
}
I still need to test this to make sure it does what I expect in IE, though. I just need to find a copy of IE without a console (I think 9 or below).
I just wish that Firefox would tell you what line of what script disabled the console - that would be nice.
I had the same issue with a Magento e-commerce site (version 1.6.2.0).
I fixed it commenting the following lines in /js/varien/js.js:637
if (!("console" in window) || !("firebug" in console))
{
var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
"group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
window.console = {};
for (var i = 0; i < names.length; ++i)
window.console[names[i]] = function() {}
}
This fix is only (obviously) for Magento sites.
Turns out the theme developer had added firebug lite to the theme without me knowing. Turning it off fixed the problem.
I think the page you are viewing when trying to log via console.log() has a script in it which overwrites the property window.console.log. Usually this property is preset with a function by the browser but you a script may override it.
First suggestion: Do you use any other dev tools that use console? On Firefox I had the same problem with Firebug running on background without me noticing it, after closing firebug the error went away. Here's a possiple duplicate thread: Firefox Web Console Disabled?
Second, if it is overridden by some script, then one by one disable scripts and see which draws the error.

Getting Javascript Errors From Another Window

I created some test code to open a new window and attempt to catch javascript errors in the new window, from the parent window. The problem is that it only works in Firefox:
...
<body>
<script>
//open new window and keep a reference to it
var w = window.open('test.html', '_blank'); //test.html has an error
//add the error listener
w.onerror = function(msg, file, line) { alert('error'); };
</script>
</body>
...
All of test.html code:
<script>
alert('test');s //error on the s
</script>
Forefox will catch this, but Chrome and IE do not. All 3 browsers will open the new window, but the error alert only displays in Firefox. Each of the browsers' consoles also show the error.
Why don't Chrome and IE catch it?
Is there some other way to make those 2 browsers catch the errors?
Edit:
I also tried add w.location.href after the onerror code, because I thought that maybe the onerror code was executed too late. This did not affect my results. Firefox was still the only one to catch the error.
<script>
var w = window.open('test2.html', '_blank'); // test 2 is a page with no errors
w.onerror = function(msg, file, line) { alert('error'); };
w.location.href = 'test.html'; // the page with the error
</script>
I did a little searching, it seems the return value of window.open() of Chrome and IE are not act as normal/original window.
It seems the reason is about security, the following post is about chrome extension, but it may help:
window.open returns undefined in chrome extension
Your best bet is going to be to wrap any code in the new window in a try/catch block. Catch the errors then send them back as such:
catch ... {
window.opener.console.log(message);
}
Try with adding some timeout
setTimeout(function(){w.onerror = function(msg, file, line) { alert('error'); };}, 3000)

Accessing XUL Elements using Firefox Add-on SDK

I'm trying to manipulate the XUL elements in the Firefox add-on page using the Add-on SDK. I wouldn't mind using lower-level modules. I used DOM inspector to see the structure for the add-on page. It looks like this for the add-on page:
#document
--page (id='addons-page', windowtype='Addons:Manager', etc.)
----...
----hbox
----hbox
----etc.
So I tried this bit of code in exports.main:
let delegate = {
onTrack: function(window) {
console.log('window is being tracked: ' + window); // outputs [object ChromeWindow
let doc = window.document;
var addOnPage = doc.getElementById('addons-page');
console.log(window.document.page); // outputs undefined
console.log(addOnPage); // outputs null
var xulElements = window.document.getElementsByClassName('addon-control');
console.log('our elements: ' + xulElements); // outputs [object HTMLCollection]
console.log('our elements length: ' + xulElements.length); // outputs length of 0
}
};
var tracker = new winUtils.WindowTracker(delegate);
The first problem is that the window tracker only open when Firefox is first started. How can I get it to listen and wait for the add-on page to be opened?
The second problem (probably related to the first) is that getting the elements doesn't seem to be working (xulElements.length is 0).
Any ideas?
Two issues here:
Add-on Manager doesn't usually open as a separate window so using WindowTracker is pointless. It is a page loaded into the browser.
You access the window before it has a chance to load to it isn't surprising that you don't see any elements.
Given that page-mod module doesn't seem to work for this page, listening to the chrome-document-global-created notification is probably the best solution. This code works for me:
var observers = require("observer-service");
observers.add("chrome-document-global-created", function(wnd)
{
if (wnd.location.href == "about:addons")
{
// Wait for the window to load before accessing it
wnd.addEventListener("load", function()
{
console.log(wnd.document.getElementsByClassName('addon-control').length);
}, false);
}
});

Categories

Resources