I am developing a Mozilla Firefox extension using the Add-on SDK. On every tab change event, I want to read cookies of specified host which is open in another tab. I reached up to tab change, but am trying to figure out the way to get the cookies of specified host in recent activated tab.
var tabs = require("sdk/tabs");
tabs.on('activate', function(tab) {
// want to get cookies here.
});
Well, from within a tabs.on('activate') event handler, you have the tab. The tab object has a property url from which you can obtain the host. Once you have the host, you can get the cookies for that host. You have not stated what you want to do with them. So, here is just a way to enumerate them.
In order to use some methods of Services.cookies (nsICookieManager2) you will also need to require Chrome Authority.
var domainToUse = 'google.com';
var { Services } = require("resource://gre/modules/Services.jsm");
var { Cc, Cu, Ci} = require("chrome");
let cookieEnumerator = Services.cookies.getCookiesFromHost(domainToUse);
while (cookieEnumerator.hasMoreElements()) {
let cookie = cookieEnumerator.getNext().QueryInterface(Ci.nsICookie2);
console.log(cookie.host + ";" + cookie.name + "=" + cookie.value + "\n");
}
Update for newer versions of Firefox:
Note: At least by Firefox 50.0a2 (currently Firefox Developer Edition), it is necessary to use a slightly different call to getCookiesFromHost() to obtain the cookieEnumerator. Without the change, the call to getCookiesFromHost() will display a warning message in the Browser Console directing you to visit the nsICookieManager2 MDN documentation page which has no updated information on the warning, or any documentation on the change. I had to look in the source code to determine what was required. What appears to be desired is to pass in the current content document. However, from a background script that did not appear reasonable. The other way it is used is to just pass in an empty Object, {}. Thus, that line is changed to:
let cookieEnumerator = Services.cookies.getCookiesFromHost(domainToUse,{});
It is supposed to be for passing in "the originAttributes of cookies that would be be retrieved."
The above code is slightly modified from my answer to "How to set custom cookies using Firefox Add-on SDK (using Services from Firefox Add-on SDK)".
Related
I'm trying to get window.location.href through the extension, but only the html file of the extension itself is given, although the manifest has permission for all sites.
I tried different options like
var local_url = window.location.href.split("/").splice(4, 2).join("/")
localStorage.Bid = JSON.stringify({local_url});
let Bid = JSON.parse(localStorage.Bid);
console.log(Bid)
but it gives only the href of the extension in which the code is run.
chrome.storage and localstorage of the browser have different storages, and when you try to pull out a specified variable, an error occurs with undefined.
The app I am working on, currently uses XML dataisland files to retrieve the dropdown data. Below is the code that defines the file.
<xml id="DefaultDataIslands" src="../XMLData/DataIslands-<%=((User.Identity).Database)%>.xml">
</xml>
Below is an example code that uses these XML dataislands.
var oDataIsland = document.getElementById("DefaultDataIslands");
var oXmlNodes = oDataIsland.XMLDocument.selectNodes("XMLDataIslands/DataIsland[#ID='DIMRGroup']/Option");
This oDataIsland line is used about 4k times total in the application. The application itself is intranet, so, I can even ask the users to download the xml files directly. Whole point is to keep the changes required to minimum, while removing all traces of XML tags. I want to make sure that application works on Chrome once this thing is completed.
I checked the link from mozilla regarding the dataislands here. https://developer.mozilla.org/en/docs/Using_XML_Data_Islands_in_Mozilla
Below is the code based on that mozilla link.
var doc = document.getElementById(strDataSource).contentDocument;
var mainNode = doc.getElementsByTagName("DataIsland");
var oXmlNodes;
var strOptions = "";
//finds the selected node based on the id, and gets the options for that id
for (i = 0; i < mainNode.length; i++) {
if (mainNode[i].getAttributeNode("ID").nodeValue == strDataMember) {
oXmlNodes = mainNode[i].getElementsByTagName("Option");
}
}
This code reads the data properly, works perfectly in IE (10 with standards mode, no quirks), was easy enough change to do in the full solution.
Only problem is, document.getElementById(strDataSource).contentDocument; line fails in Chrome. This is the same line as what was mentioned in Mozilla's documentation. But somehow contentDocument property is undefined on chrome.
So, I need some other suggestion on how to get this fixed. I tried other methods, using HTTPRequest (too many request per page), using JSON (requires changing existing methods completely), using backend to process XML instead of doing it client side (requires architectural changes). Till now, all these ideas failed.
Is there any other method that I can use? Or should I fix the contentDocument issue?
To allow contentDocument in Chrome, you will have to use --allow-file-access-from-files. Following are the steps for doing so:
Get the url of your Chrome Installation path to your chrome
installation e.g
C:\Users-your-user-name\AppData\Local\Google\Chrome\Application>
Launch the Google Chrome browser from the command line window with
the additional argument ‘–allow-file-access-from-files’. E.g ‘path
to your chrome installation\chrome.exe
--allow-file-access-from-files’
Temporary method you can use each time you are testing
Copy the existing chrome launcher
Do as above and save it with a new name e.g chrome - testing
Alternatively, you can simply create a new launcher with the above and use it to start chrome.
Source
We are using CrossRider to develop an extension for Internet Explorer. We have an object which is downloaded from http://jsons.[part_of_link_suppressed].com.s3.amazonaws.com/selectors.json. I found out that when this object is sent to a callback, arrays are converted to objects with integer keys. Why are arrays converted to objects and is there a way to prevent it? I know we can JSON.stringify the object and JSON.parse by the calling function, but is there a way to send arrays without converting them to strings? I checked and even ['a','b','c'] is converted to an object ({"0":"a","1":"b","2":"c"}) when calling a function with it.
I'm using Internet Explorer 11 but this extension should work on all versions of Internet Explorer.
Edit (1): I tested debug mode in Internet Explorer 11 and Google Chrome. I created a new extension - ID 67708. In Chrome it works fine, in Explorer it doesn't. Here is the code:
background.js:
/************************************************************************************
This is your background code.
For more information please visit our wiki site:
http://docs.crossrider.com/#!/guide/scopes_background
*************************************************************************************/
function callme1() {
var r1 = ['a','b','c'];
alert('r1 = ' + JSON.stringify(r1));
return r1;
}
appAPI.ready(function($) {
// Place your code here (ideal for handling browser button, global timers, etc.)
alert('callme1() = ' + JSON.stringify(callme1()));
});
extension.js:
/************************************************************************************
This is your Page Code. The appAPI.ready() code block will be executed on every page load.
For more information please visit our docs site: http://docs.crossrider.com
*************************************************************************************/
function callme2() {
var r2 = ['a','b','c'];
alert('r2 = ' + JSON.stringify(r2));
return r2;
}
appAPI.ready(function($) {
// Place your code here (you can also define new functions above this scope)
// The $ object is the extension's jQuery object
// alert("My new Crossrider extension works! The current page is: " + document.location.href);
alert('callme2() = ' + JSON.stringify(callme2()));
});
In Chrome all the alerts are ["a","b","c"], in Explorer they are {"0":"a","1":"b","2":"c"}, before and after returning the object. But in our extension (ID 43889), if we JSON.stringify the object and then JSON.parse it, then it's still an array (I didn't find how to reproduce it with a simple extension).
By the way, if I type in the console JSON.stringify(['a','b','c']) in Explorer or Chrome, I get the same result - "["a","b","c"]".
I also found another irritating bug - CrossRider converts my staging extensions to production, and I have to switch again to staging manually. It happened at least 5 times with both extensions.
Edit (2): I tried to use appAPI.JSON.stringify instead of JSON.stringify and now I receive the correct results in Explorer in extension.js (["a","b","c"]), but background.js is not loaded at all in debug mode and keeps displaying the old contents. I don't know if that's because I have 2 extensions in debug mode but this is a new bug - background.js is not updated when I click "reload background code".
I had the same problem, with the messaging api. not sure what is your case (when saving to DB?)
Though i don't remember my whole debugging findings i think its like that:
Crossrider api internally serialising the values to JSON in order to send them via postMessage/their own implementation for background communication with the background IE process(for all browser/not natively support pass objects via postMessage eg IE8).
They aren't using native JSON object but rather (broken) JSON implementation (I think only on their IE background process because its not really browser page and there's no built in JSON)
That means that even if you use their appAPI.JSON when no native JSON available you still get the broken arrays.
My solution was to use external json library, think i used JSON3
http://bestiejs.github.io/json3/
http://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js
It would be less performant but if its not really big object it won't be noticeable.
You can also try to monkey patch their JSON appAPI.JSON with the external library, it might fix their api
Introduction
I work with RapidWeaver — Mac OS X CMS application — and it uses no server environment. It has an editor and a preview mode. The preview mode is a Webkit based renderer, and I can use 'Inspect Element', like you normally could do in Safari.
I want to store some settings for a toolbar, either using localStorage or SQLite. I have read some information about indexedDB, though I have found no concrete implementations on how to use it.
Problems with localStorage
localStorage works fine when I stay in the preview mode, when I switch between editor and preview mode the url — location.href — is slightly altered:
file:///private/var/folders/s7/x8y2s0sd27z6kdt2jjdw7c_c0000gn/T/TemporaryItems/RapidWeaver/98970/document-143873968-28/RWDocumentPagePreview/code/styled/index.html
file:///private/var/folders/s7/x8y2s0sd27z6kdt2jjdw7c_c0000gn/T/TemporaryItems/RapidWeaver/98970/document-143873968-29/RWDocumentPagePreview/code/styled/index.html
document-143873968-28 changes into
document-143873968-29
What I have read about localStorage, that it's basically globalStorage[location.hostname] for FireFox. As far as I know globalStorage is not supported in Safari, so I can't try that.
Problems with SQLite
When I try to open a database:
var shortName = 'mydatabase';
var version = '1.0';
var displayName = 'My Important Database';
var maxSize = 65536; // in bytes
var db = openDatabase(shortName, version, displayName, maxSize);
I get this in my console:
SECURITY_ERR: DOM Exception 18: An attempt was made to break through the security policy of the user agent.
That basically wraps up my question, I will appreciate any answers or comments sincerely.
Using the following solution: Implementing a WebView database quota delegate with a few modifications I was able to get it to work.
The following delegate method worked for me (place in your webViewDelegate):
- (void)webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(id) origin database:(NSString *)databaseIdentifier
{
static const unsigned long long defaultQuota = 5 * 1024 * 1024;
if ([origin respondsToSelector: #selector(setQuota:)]) {
[origin performSelector:#selector(setQuota:) withObject:[NSNumber numberWithLongLong: defaultQuota]];
} else {
NSLog(#"could not increase quota for %#", defaultQuota);
}
}
By default the database is given 0 bytes, which results in the vague error message you get above. The above method is called after an attempt is made to create a database when there is not enough space. Note that this method is defined in WebUIDelegatePrivate.h ( http://opensource.apple.com/source/WebKit/WebKit-7533.16/mac/WebView/WebUIDelegatePrivate.h ) and using may preclude you from submitting your app to the mac app store.
localStorage is a html5 mechanism to give scripts a bit more space than cookies. Safari supports it: https://developer.apple.com/library/archive/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/Name-ValueStorage/Name-ValueStorage.html
I don't know offhand what, if any, path restrictions it should have for file:/// based apps.
Edit: looking into the path restrictions further, I see that what you got should work with Safari, FF recently fixed a bug that would keep it from working there: https://bugzilla.mozilla.org/show%5Fbug.cgi?id=507361
I used to be able to do this to create an exported HTML page containing some data. But the code is not working with the latest version of Google Chrome (It works all right with Chrome 5.0.307.11 beta and all other major browsers).
function createExport(text) {
var target = window.open();
target.title = 'Memonaut - Exported View';
target.document.open();
target.document.write(text);
target.document.close();
}
Chrome now complains that the domains don't match and disallows the JavaScript calls as unsafe. How can I access and modify the document of a newly opened browser-tab in such a scenario?
I also got this problem when using a local page using the file:// protocol (in Chromium 5.0.342.9 (Developer Build 43360) under Linux). The exact error message is:
Unsafe JavaScript attempt to access
frame with URL about:blank from frame
with URL
file:///home/foo/bar/index.htm.
Domains, protocols and ports must
match.
Apparently the protocols don't match, but the good news is: when this page on a web server, Chromium also opens a new window as "about:blank", but it doesn't complain any longer. It also works when using a local web server accessed via http://localhost.
EDIT: there is bug filed upstream about this. According to this comment, it is fixed and it will be rolled into trunk shortly.
UPDATE: this bug is now fixed, the following test case works properly:
var target = window.open();
target.title = 'Memonaut - Exported View';
target.document.open();
target.document.write("test");
target.document.close();
Here is the explanation I think
http://groups.google.com/group/chromium-dev/browse_thread/thread/9844b1823037d297?pli=1
Are you accessing any data from other domain? Not sure, but that might be causing this problem.
One alternative would be a data: protocol URL.
https://developer.mozilla.org/en/data_URIs
http://msdn.microsoft.com/en-us/library/cc848897%28VS.85%29.aspx
var durl = "data:text/html," + encodeURIComponent(text);
var target = window.open(durl);
Supported in all modern browsers except IE7 and below.
you can also try closing self tab/window by using this code,
originally I've made this small greasemonkey script sometime ago in order to close
bad popups and ad windows, it worked fair (not too brilliant though)...
//window.addEventListener("load", function () {
window.addEventListener("onbeforeunload", function () {
try {
// clear inner html content to prevent malicious JS overrides.
document.getElementsByTagName("html")[0].innerHTML = "";
window.open("javascript:window.close();", "_self", "");
window.open("javascript:window.close();", "_self", "");
}
catch (e) {}
}(), false);