variable not recognized inside contentscript - firefox

I am trying to create an addon which after a user logs in to my site I will try and read the session id of that domain and use it for further interactions with my addon. I use the online addon builder and I have this code which I want to read the cookies:
var data = require("self").data;
var {Cc, Ci} = require("chrome");
var cookieMgr = Cc["#mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
var cm = require("context-menu");
cm.Item({
label: "My Menu Item",
contentScript: 'self.on("click", function (node, data) {' +
'for (var e = cookieMgr.enumerator; e.hasMoreElements();) { ' +
'var cookie = e.getNext().QueryInterface(Ci.nsICookie); ' +
' console.log(cookie.host + ";" + cookie.name + "=" + cookie.value + "\\n");'+
'}});'
});
but it throws an error every time I click on the 'My Menu Item' button, saying cookieMgr, the variable is not defined.

The content script context is entirely disconnected from the addon script context. It's not so easy to grasp this when you're using contentScript, but if you put it in another file and use it through a contentScriptFile it becomes more obvious. Content scripts are run in the context of the document, while addon scripts aren't.

Related

Can you add html markup in Kendo UI Tabstrip tab text during binding

Trying to add a "x" in my tabs similar to the "x" in the Chrome browser tabs, to be able to click on to remove the tab. Just double checking, but it seems you can't add html markup to your tabs (not the content, but the tabs themselves), using the MVC wrappers in the BindTo method like so:
#(Html.Kendo().TabStrip()
.Name("OrderDetailsTabs")
.HtmlAttributes(new { #class="orderDtlTabs"})
.BindTo(Model, (tab, tabModel) =>
{
tab.Text = "<a class='k-link'><span>Part: " + tabModel.WOHdr.OrderDetailId +
"<button onclick='return deleteWorkOrder(" + tabModel.WOHdr.Id +")' class='delete k-button' title='Delete Work Order'></button>" +
"</span></a>"; // tab text
I know I can do some DOM manipulation after the tabs load, but just seeing if I'm missing something to do it at binding time.
Well, I ended up doing post binding DOMnastics to update the html in the tabs after they load:
function addDeleteIconToTabs() {
var $tabItems = $('ul.k-tabstrip-items > li.k-item');
$tabItems.each(function (index, tabLI) {
var strTabId = $(tabLI).attr('aria-controls');
var $tabContainerDiv = $('#' + strTabId);
var intWorkOrderId = $tabContainerDiv.find('input.wohid').val();
var strButtonHtml = "<button onclick='return deleteWorkOrder(this," + intWorkOrderId + ")' class='delete k-button' title='Delete Work Order'></button>";
$(tabLI).append(strButtonHtml);
});
}

Open a tab next to the active tab in Firefox Add-on SDK

I am trying to open a new tab right next to the active tab in a firefox add-on. Here is my code:
var tabs = require("sdk/tabs");
tabs.open("http://www.google.com");
This opens the new tab at the end of the tab list. I couldn't figure out how to force it to position the new tab immediately after the active tab.
Get the index of the current tab, then set the index of the new tab to that + 1
var tabs = require("sdk/tabs");
var index = tabs.activeTab.index;
tabs.open("http://www.google.com");
tabs.activeTab.index = index + 1;
Alternatively, if you look at the docs, you'll see that there's a constructor parameter called
inBackground: boolean. If present and true, the new tab will be opened to the right of the active tab and will not be active.
By combining this with the onOpen event, you can achieve the desired effect:
var tabs = require("sdk/tabs");
tabs.open({
url: "http://www.google.com",
inBackground: true,
onOpen: function(tab) {
tab.activate();
}
});
I haven't tested either of these, so some debugging might be needed.
Another way is using lower-level APIs like gtranslate does:
const { getMostRecentBrowserWindow } = require('sdk/window/utils')
const browser = getMostRecentBrowserWindow().gBrowser
const tab = browser.loadOneTab(url, {relatedToCurrent: true})
browser.selectedTab = tab
Note that it might not work with e10s.

How to pass a value between browser tabs?

I am trying to pass a value from one tab to another.
I tried sessionStorage and clipboard, but no luck so far. Here is the demo, and the code as well:
https://builder.addons.mozilla.org/package/154290/latest/
What it tries to do is get the selected text, and pass it to the opened tab:
// Create a new context menu item.
var menuItem = contextMenu.Item({
label: "Check with Proofread Bot",
context: contextMenu.SelectionContext(),
contentScript: 'self.on("click", function () {' +
' var text = window.getSelection().toString();' +
' sessionStorage.setItem("proofread_bot_chrome", text);' +
' self.postMessage(text);' +
'});',
onMessage: function(text) {
clipboard.set(text);
//sessionStorage.setItem("proofread_bot_chrome", text);
tabs.open({
url: "http://proofreadbot.com",
onOpen: function onOpen(tab) {
// do stuff like listen for content
// loading.
alert(clipboard.get());
alert(selection.text);
sessionStorage.setItem("proofread_bot_chrome", clipboard.get());
}
});
}
});
sessionStorage and localStorage are always bound to a domain. Content scripts run with the privileges of the web page meaning that they access the session storage for that web page - not very useful to pass data around. And they simply don't have clipboard access.
This means that you can't get around "traditional" messaging. When you open the tab you should attach a content script, wait for it to be ready (the content script can send a message to indicate that) and send it the text. Something like this:
onOpen: function(tab) {
var worker = tab.attach({
contentScript: "self.on('message', function(text) {alert(text);});" +
"self.postMessage(null);",
onMessage: function() {
worker.postMessage(text);
}
});
}
For reference: Communicating using postMessage()
You should try localStorage instead of sessionStorage. localStorage is shared between the documents from same origin.
Although it persists even on tab close, which may or may not be desirable depending on your requirement.
sessionStorage is per document, and hence not shared between tabs.

Add-on to open local folders in Firefox

I have just started making an add-on with Firefox. This add-on is written in order to open a local folder outside FF. The folder is already opened by the browser. And in the context menu you will see an option to open the folder outside the browser (I use Win7).
This is the code that I used:
var contextMenu = require("context-menu");
var menuItem = contextMenu.Item({
label: "Open Local File",
context: contextMenu.URLContext("file:///*"),
contentScript: 'self.on("click", function() {'+
'openDir(document.URL);'+
'});',
});
function openDir(val)
{
if (val == "")
{
alert("Directory not defined");
return;
}
if(navigator.userAgent.indexOf("Firefox") == -1)
{
alert("Currently active folder links supported only for Mozilla Firefox web browser");
return;
}
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var localFile =
Components.classes["#mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
var env =
Components.classes["#mozilla.org/process/environment;1"]
.createInstance(Components.interfaces.nsIEnvironment);
var systemRoot = env.get("SystemRoot");
if (systemRoot == "")
{
alert("Unable to retrieve SystemRoot environment variable");
}
localFile.initWithPath(systemRoot + "\\explorer.exe");
var process =
Components.classes["#mozilla.org/process/util;1"]
.createInstance(Components.interfaces.nsIProcess);
process.init(localFile);
process.run(false, Array(val), 1);
}
Now the problem is that when I save the add-on under http://builder.addons.mozilla.org/... it cannot be compiled. Instead a red box shows up with the message "XPI not built". This is the log:
GET https://builder.addons.mozilla.org/xpi/test/.../ 404 NOT FOUND 236ms
What should I do?
The modified code:
var contextMenu = require("context-menu");
var menuItem = contextMenu.Item({
label: "Open Local File",
contentScript: 'self.on("context", function(node)'+
'{'+
' return node.ownerDocument.URL.indexOf("file:///") == 0;'+
'});'+
'self.on("click", function(node)' +
'{' +
' self.postMessage(node.ownerDocument.URL);' +
'});',
onMessage: function(url)
{
openDir(url);
}
}) ;
function openDir(val)
{
var {Cc, Ci} = require("chrome");
var ioService = Cc["#mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
var uri = ioService.newURI(val, null, null);
if (uri instanceof Ci.nsIFileURL && uri.file.isDirectory())
{
uri.file.QueryInterface(Ci.nsILocalFile).launch();
}
}
The Add-on Builder web application is there to package up your code and create an extension - Firefox merely installs the extension once it is done. You have an issue with the Add-on Builder, not one with Firefox. I can only recommend you to file a bug report.
Your code has numerous issues however:
It seems that you want to show your context menu item on pages using the file:/// URL scheme, not on links pointing to files. There is no predefined context for this, you will have to use the content script (see Specifying Contexts > In Content Scripts. Something like:
self.on("context", function(node)
{
return node.ownerDocument.URL.indexOf("file:///") == 0;
});
Function openDir() isn't defined in the content script, it is defined in your extension. This means that you have to send a message back to your extension with the URL (see last example in Handling Menu Item Clicks). Something like this:
contentScript: 'self.on("context", ...);' +
'self.on("click", function(node, data)' +
'{' +
' self.postMessage(node.ownerDocument.URL);' +
'});',
onMessage: function(url)
{
openDir(url);
}
Checking whether your code is running in Firefox is pointless - currently, the Add-on SDK only supports Firefox.
You should not use the deprecated PrivilegeManager.enablePrivilege method - your code is already running with highest privileges. You will need to use chrome authority however, extensions built with the Add-on SDK by default cannot access low-level functionality.
You shouldn't run Windows Explorer directly, use nsILocalFile.launch(), for directories it will run Windows Explorer (or whatever action is defined in the operating system to open directories). Altogether the code in openDir() should look like this:
var {Cc, Ci} = require("chrome");
var ioService = Cc["#mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
var uri = ioService.newURI(val, null, null);
if (uri instanceof Ci.nsIFileURL && uri.file.isDirectory())
uri.file.QueryInterface(Ci.nsILocalFile).launch();
Documentation: nsIIOService, nsIFileURL.

google map infowindow's button's onclick function won't perform jquery ajax function correctly. closure or scope error?

i have a database where each row has lat/long info for goggle maps.
each row subsequently gets turned into a marker. when i click on that marker, an info window pops up.
i want the info window to have a button so that when clicked, the entry from the database will get deleted. but my button won't work. specifically, something about the eraseEntry() function attached to the onClick event isn't working. when i click the button, only the last entry of the database gets deleted, regardless of which marker i click.
var map=//make the google map
var markersArray = [];
var infoWindow = new google.maps.InfoWindow({content: ""});
var markers;
$.get("phpsqlajax_genxml.php", function(data)
{
markers = data.documentElement.getElementsByTagName("marker");
makeMarkersWithXMLinfo();
});
function makeMarkersWithXMLinfo()
{
for (var i = 0; i < markers.length; i++)
{
var name = markers[i].getAttribute("name");
var markerLocation = new google.maps.LatLng(parseFloat(markers[i].getAttribute("lat")),parseFloat(markers[i].getAttribute("lng")));
var html = "<b>" + name + "</b> <br/>" +
"</b> <br/>" + "</b> <br/>" +
"<input type='button' value='Erase Entry' onclick='eraseEntry()'/>";
var markerWithLocation = new google.maps.Marker({position: markerLocation, map: map});
var markerWithInfo = createMarker(markerWithLocation,html);
eraseEntry = function ()
{
$.get("delete.php", { identifierVar: name } );
}
}
}
function createMarker(markerWithLocation, html) {
var markerWithInfo = google.maps.event.addListener(markerWithLocation, 'click', function(){infoWindow.setContent(html); infoWindow.open(map,markerWithLocation)});
return markerWithInfo;
}
i'm able to pull from the database and create the markers just fine.
i've tried having the eraseEntry() function call another function that's outside of the makeMarkersWithXMLinf() function, but i still get the same problem. depending where i put/call those functions, sometimes javascript doesn't even think my function exists...
below's my delete.php file
<?php
require("phpsqlajax_dbinfo.php");
// Opens a connection to a MySQL server
$connection = mysql_connect ('localhost', $username, $password);
if (!$connection) {
die('Not connected : ' . mysql_error());
}
// Set the active MySQL database
$db_selected = mysql_select_db($database, $connection);
if (!$db_selected) {
die ('Can\'t use db : ' . mysql_error());
}
if(isset($_GET['identifierVar']))
{
$query = 'DELETE FROM markers WHERE name = '.(int)$_GET['identifierVar'];
$result = mysql_query($query);
}
?>
i've been testing with just unique names.
like 111, 222, 333.. etc
any help's appreciated. thanks.
identifierVar should be identifierId, where identifierId is the id of that marker. try making these delete queries with the id, its much faster and it's a unique value.
your query is probably like this: delete from x where name = '$name'. you need to limit to 1, like: delete from x where name = '$name' limit 1
after you've successfully deleted the marker from database, delete it off the map
use firebug always in your debugging

Resources