I am creating a simple bootstrapped add-on for Firefox. I need to capture the current URL from the browser through sidebar with a button click.
My bootstrap.js:
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import('resource://gre/modules/Services.jsm');
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
/*start - windowlistener*/
var windowListener = {
//DO NOT EDIT HERE
onOpenWindow: function (aXULWindow) {
// Wait for the window to finish loading
let aDOMWindow =aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowInternal||Ci.nsIDOMWindow);
aDOMWindow.addEventListener("load", function () {
aDOMWindow.removeEventListener("load", arguments.callee, false);
windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
}, false);
},
onCloseWindow: function (aXULWindow) {},
onWindowTitleChange: function (aXULWindow, aNewTitle) {},
register: function () {
// Load into any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
}
// Listen to new windows
Services.wm.addListener(windowListener);
},
unregister: function () {
// Unload from any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.unloadFromWindow(aDOMWindow, aXULWindow);
}
//Stop listening so future added windows dont get this attached
Services.wm.removeListener(windowListener);
},
//END - DO NOT EDIT HERE
loadIntoWindow: function (aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
//START - EDIT BELOW HERE
var browser = aDOMWindow.document.querySelector('#browser')
if (browser) {
var splitter = aDOMWindow.document.createElement('splitter');
var propsToSet = {
id: 'demo-sidebar-with-html_splitter',
//I'm just copying what Mozilla does for their social sidebar splitter
// I left it out, but you can leave it in to see how you can style
// the splitter
class: 'sidebar-splitter'
}
for (var p in propsToSet) {
splitter.setAttribute(p, propsToSet[p]);
}
var sidebar = aDOMWindow.document.createElement('vbox');
var propsToSet = {
id: 'demo-sidebar-with-html_sidebar',
//Mozilla uses persist width here, I don't know what it does and can't
// see it how makes a difference so I left it out
//persist: 'width'
}
for (var p in propsToSet) {
sidebar.setAttribute(p, propsToSet[p]);
}
var htmlVal = loadJsonHTML(0);
var sidebarBrowser = aDOMWindow.document.createElement('browser');
var propsToSet = {
id: 'demo-sidebar-with-html_browser',
type: 'content',
context: 'contentAreaContextMenu',
disableglobalhistory: 'true',
tooltip: 'aHTMLTooltip',
autoscrollpopup: 'autoscroller',
flex: '1', //do not remove this
//you should change these widths to how you want
style: 'min-width: 14em; width: 18em; max-width: 36em;',
//or just set this to some URL like http://www.bing.com/
src: 'data:text/html,'+ htmlVal
}
for (var p in propsToSet) {
sidebarBrowser.setAttribute(p, propsToSet[p]);
}
browser.appendChild(splitter);
sidebar.appendChild(sidebarBrowser);
browser.appendChild(sidebar);
}
//END - EDIT BELOW HERE
},
unloadFromWindow: function (aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
//START - EDIT BELOW HERE
var splitter = aDOMWindow.document
.querySelector('#demo-sidebar-with-html_splitter');
if (splitter) {
var sidebar = aDOMWindow.document
.querySelector('#demo-sidebar-with-html_sidebar');
splitter.parentNode.removeChild(splitter);
sidebar.parentNode.removeChild(sidebar);
}
//END - EDIT BELOW HERE
}
};
/*end - windowlistener*/
function startup(aData, aReason) {
windowListener.register();
}
function shutdown(aData, aReason) {
if (aReason == APP_SHUTDOWN) return;
windowListener.unregister();
}
function loadJsonHTML(val=0){
var fileContent = "";
var localFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
//full path is okay if directory exists
localFile.initWithPath("/Users/tinuy/Desktop/test_addodn/input.txt");
//otherwise specify directory, create it if necessary, and append leaf.
//localFile.initWithPath("C:\Users\tinuy\Documents\test\input.txt");
if ( localFile.exists() == false ) {
fileContent = "File does not exist";
}
var istream = Cc["@mozilla.org/network/file-input-stream;1"]
.createInstance(Ci.nsIFileInputStream);
istream.init(localFile, 0x01, 4, null);
var fileScriptableIO = Cc["@mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
fileScriptableIO.init(istream);
// parse the XML into our internal document
istream.QueryInterface(Ci.nsILineInputStream);
//fileContent = fileScriptableIO.read( '1' );
var csize = 0;
while ((csize = fileScriptableIO.available()) != 0) {
fileContent += fileScriptableIO.read( csize );
}
var array = fileContent.split("&");
fileScriptableIO.close();
istream.close();
return makeHTML(array[val], val);
}
function makeHTML(value, key){
var arrValues = value.split(",");
var htmlContent = '<div name="content" class="content">' +
'<p> Name :' + arrValues[0] + '</p>';
htmlContent += '<p> Price :' + arrValues[2] + '</p>';
htmlContent += '<p> Color :' + arrValues[3] + '</p>';
htmlContent += '<p> UID :' + arrValues[1] + '</p>';
htmlContent += '<p><input type="radio" name="valid" value="yes" />Yes ' +
'<input type="radio" name="valid" value="no" /> No</p>' +
'<p><input type="text" placeholder="Reason" name="checkreason"></p>' +
'<p><input type="text" placeholder="Feedback" name="feedback"></p>' +
'</div><div><button name="load" type="button" id="loadit" onclick="loadHtml()" ' +
'loadurl="'+arrValues[4]+'">Load</button> <button name="save" type="button">' +
'Save </button> <button name="next" type="button" key="'+key+'">Next </button> ' +
'</div> <script> function loadHtml() {' +
'var a = gBrowser.contentWindow.location.href ;alert(a);' +
'} </script>';
return htmlContent;
}
function install() {}
function uninstall() {}
I tried all suggestions from Get current page URL from a firefox sidebar extension but nothing worked.
However, from the fact that you have set:
var propsToSet = {
id: 'demo-sidebar-with-html_browser',
type: 'content', //<---------------------------This
the <browser>
type
to content
, I am assuming one of two things:
<browser>
through the src
attribute.
<browser>
you have loaded into the sidebar and are unaware of the restrictions which setting the <browser>
type
to content
imposes upon the code you load into the <browser>
.
<browser>
. You should consider restructuring your code such that access to chrome privileges is not required from the content that is in the <browser>
. In other words, if possible, you should write your code such that you do not need to have access to the URL, or other information, directly from code running in the <browser>
you insert. However, doing so may end up being significantly more complex.Getting access to chrome privileges within the <browser>
you are adding:
Setting the <browser>
type
to content
is for:
A browser for content. The content that is loaded inside the browser is not allowed to access the chrome above it.
Setting the <browser>
type
to chrome
is for:
(default behaviour): A browser, intended to be used for loading privileged content using a chrome:// URI. Don't use for content from web, as this may cause serious security problems!
To set the the <browser>
type
to chrome
you can do:
var propsToSet = {
id: 'demo-sidebar-with-html_browser',
type: 'chrome', //<---------------------------This
The code provided by Noitidart comes close to what you need. However, it needs to be slightly modified, as gBrowser.currentURI
is a nsIURI, not a string). Thus, you need to use gBrowser.currentURI.spec
. You can get it working by changing your makeHTML()
to:
function makeHTML(value, key){
var arrValues = value.split(",");
var htmlContent = '<html><head></head>'
+ '<body style="background-color: white;">'
+ ' <div name="content" class="content">'
+ ' <p> Name :' + arrValues[0] + '</p>';
htmlContent += '<p> Price :' + arrValues[2] + '</p>';
htmlContent += '<p> Color :' + arrValues[3] + '</p>';
htmlContent += '<p> UID :' + arrValues[1] + '</p>';
htmlContent +=
' <p><input type="radio" name="valid" value="yes" />Yes '
+ ' <input type="radio" name="valid" value="no" /> No</p>'
+ ' <p><input type="text" placeholder="Reason" name="checkreason" /></p>'
+ ' <p><input type="text" placeholder="Feedback" name="feedback" /></p>'
+ ' </div>'
+ ' <div>'
+ ' <button name="load" type="button" id="loadit" onclick="loadHtml()" '
+ ' loadurl="' + arrValues[4] + '">Load</button>'
+ ' <button name="save" type="button">Save </button>'
+ ' <button name="next" type="button" key="' + key + '">Next </button>'
+ ' </div>'
+ ' <script>'
+ ' function loadHtml() {'
+ ' const Cu = Components.utils;'
+ ' Cu.import("resource://gre/modules/Services.jsm");'
+ ' var win = Services.wm.getMostRecentWindow("navigator:browser");'
+ ' if (win) {'
+ ' var url = win.gBrowser.currentURI.spec;'
+ ' alert("URL=" + url);'
+ ' }'
+ ' }'
+ ' </script>'
+ '</body></html>';
return htmlContent;
}
Security concerns:
There are some really significant security concerns that you may be running into. Just from the fact that you want the URL for the current page implies that you may be rapidly approaching where these are a real issue. It is going to depend on what exactly you are going to do. Given that you are not providing that information, I am not going to go too in depth as to what the issues are. However, you should read "Firefox Security Basics for Developers" and "Security best practices in extensions"
Additional information about sidebars:
You should seriously consider creating an Add-on SDK based add-on, instead of a bootstrap one, and using the ui/sidebar API.
If you are interested, I created some code which can be used to create a "sidebar" that is located at the top, left, right, or bottom of the active tab, or in a separate window (similar to what the devtools panel will do). The sidebar created is associated with the currently active tab, not all tabs (I guess I should have made it an option to have it associated with all tabs, or just the current tab) in my answer to: "How to create a bottom-docked panel with XUL in Firefox?" and "Firefox Extension, Window related sidebar"