I am writing a Firefox add-on, and I am using the high-level Firefox Add-on SDK API.
My add-on opens a new window, and opens several tabs in that window.
How can I get this new window to open in the background? I do not want its opening to disrupt the user's focus on the active window.
When opening a tab, there is an inBackground option that can be used for this.
I have searched the windows module documentation high and low, but I cannot find a similar option for when creating new windows!
How do I open this new window in the background?
If Mozilla forbids me from doing so, is there a way I can very quickly push the new window to the background just after it opens, so that it is minimally disruptive?
Not disallowed. Perfectly fine. Do it with a features option of alwaysLowered I think.
Full list of features found here: https://developer.mozilla.org/en-US/docs/Web/API/window.open#Position_and_size_features
var sa = Cc["#mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray);
var wuri = Cc["#mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
wuri.data = 'about:blank';
sa.AppendElement(wuri);
let features = "chrome,dialog=no,alwaysLowered";
var wantTabs = false;
if (wantTabs) {
features += ',all';
}
/*var sDOMWin = aTab.ownerGlobal; //source DOMWindow*/
if (PrivateBrowsingUtils.permanentPrivateBrowsing/* || PrivateBrowsingUtils.isWindowPrivate(sDOMWin)*/) {
features += ",private";
} else {
features += ",non-private";
}
var XULWindow = Services.ww.openWindow(null, 'chrome://browser/content/browser.xul', null, features, sa);
You can tag this code onto the end to do something after the XULWindow loads:
XULWindow.addEventListener('load', function() {
//can lower or raise the window z-index here
var DOMWindow = XULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
DOMWindow.gBrowser.selectedTab.linkedBrowser.webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL);
}, false);
Related
I want to use different XPCOM interfaces in Firefox Extension, here is an example taken from their API:
var domWindowUtils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
But I can't use it in my background script because object Window is undefined:
window.QueryInterface is not a function
Please guide me in right direction.
P.S. What is actually available in a global scope for background scripts? I can't seem to find a single clue in documentation.
The issue is that Firefox extensions do not run in the context of any particular window. As such, they often do not have the window object defined, or it is defined as something which you are not expecting if you are not familiar with writing extension code. This is particularly true if you are approaching this from the point of view of writing JavaScript for use within an HTML page. Extensions operate in a significantly larger context which includes the entire browser and all windows and tabs. Thus, there is no automatically appropriate window to use as the window object. In the context of an extension, each HTML page is just a part of the whole.
You can obtain each primary browser window through the use of nsIWindowMediator. The following function, from MDN, will run the function you pass to it once for each open window:
Components.utils.import("resource://gre/modules/Services.jsm");
function forEachOpenWindow(todo) // Apply a function to all open browser windows
{
var windows = Services.wm.getEnumerator("navigator:browser");
while (windows.hasMoreElements())
todo(windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow));
}
You will often want to find the window for the most recent browser/tab which was accessed by the user. The following code will define and set the window variable to the most recently used browser/tab. It will work either in the Add-on SDK, or in overlay/bootstrap extensions depending on which portion you un-comment.
For more information about using windows in a Firefox extension, you should see Working with windows in chrome code and perhaps Tabbed browser.
if (window === null || typeof window !== "object") {
//If you do not already have a window reference, you need to obtain one:
// Add a "/" to un-comment the code appropriate for your add-on type.
/* Add-on SDK:
var window = require('sdk/window/utils').getMostRecentBrowserWindow();
//*/
/* Overlay and bootstrap (from almost any context/scope):
var window=Components.classes["#mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator)
.getMostRecentWindow("navigator:browser");
//*/
}
Alternately using Services.jsm to access nsIWindowMediator:
/* Overlay and bootstrap:
Components.utils.import("resource://gre/modules/Services.jsm");
//*/
if (window === null || typeof window !== "object") {
//If you do not already have a window reference, you need to obtain one:
// Add a "/" to un-comment the code appropriate for your add-on type.
/* Add-on SDK:
var window = require('sdk/window/utils').getMostRecentBrowserWindow();
//*/
/* Overlay and bootstrap (from almost any context/scope):
var window = Services.wm.getMostRecentWindow("navigator:browser");
//*/
}
Here are some additional variables which might be useful to have available, depending on what you are doing:
if (typeof document === "undefined") {
//If there is no document defined, get it
var document = window.content.document;
}
if (typeof gBrowser === "undefined") {
//If there is no gBrowser defined, get it
var gBrowser = window.gBrowser;
}
var tab = gBrowser.selectedTab;
var browserForTab = gBrowser.getBrowserForTab( tab );
var notificationBox = gBrowser.getNotificationBox( browserForTab );
var ownerDocument = gBrowser.ownerDocument;
NOTE: The content of this answer was primarily taken from my answers here and here, but is based on code from MDN. For me, the code to traverse all open browser windows has its origin in the original article the MDN article How to convert an overlay extension to restartless is based on.
A quick and dirty way for testing, and sometimes real application is Services.wm.getMostRecentWindow('navigator:browser'), or you can use null or any other windowType.
---Update----
After experimenting more with this, I've determined that the contentScript I have written is not the problem here. For example, if I reduce the extension to merely:
var buttons = require('sdk/ui/button/action');
var data = require("sdk/self").data;
var self = require("sdk/self");
var button = buttons.ActionButton({
id: "library-link",
label: "External Resource Locator",
icon: self.data.url("icon-16.png"),
});
The button will still appear when I run the extension through the SDK, but will not appear when I install the xpi in a current firefox browser (version 38, on some platforms). This problem seems to be occurring at a very basic level in their design process.
I am trying to write a simple extension for firefox which appends a form to the current page and posts data to another site. It can be called by an action button or through a context menu item.
I have been developing with the add-on sdk and it is working perfectly when I use cfx run to test it. However, after doing cfx xpi and installing the extension into my firefox browser, it does not work at all. The action button and context menu item do not appear, and although the extension shows up under add-ons -> extensions as installed and enabled, none of the images packaged with the xpi will display.
I am not sure what could be causing this, and my code is fairly brief, so I will add my entire main.js:
var buttons = require('sdk/ui/button/action');
var data = require("sdk/self").data;
var contextMenu = require("sdk/context-menu");
var self = require("sdk/self");
var menuItem = contextMenu.Item({
label: "Look for selected text in the Library of Babel",
context: contextMenu.SelectionContext(),
contentScript: 'self.on("click", function () {' +
'var text = window.getSelection().toString();' +
'var formext = document.createElement("form");' +
'formext.setAttribute("method", "POST");' +
'formext.setAttribute("action", "https://libraryofbabel.info/resourcelocator.cgi");' +
'var hiddenField = document.createElement("input");' +
' hiddenField.setAttribute("type", "hidden");' +
'hiddenField.setAttribute("name", "extension");' +
' hiddenField.setAttribute("value", window.getSelection().toString());' +
' formext.appendChild(hiddenField);' +
' document.body.appendChild(formext);' +
' formext.submit();' +
'});',
image: self.data.url("icon-16.png")
});
var button = buttons.ActionButton({
id: "library-link",
label: "External Resource Locator",
icon: {
"16": "./icon-16.png",
"32": "./icon-32.png",
"64": "./icon-64.png"
},
onClick: function() {
require("sdk/tabs").activeTab.attach({
contentScriptFile: data.url("form.js")
});
}
});
I've noticed that when I run cfx xpi the automatically generated install.rdf file says the maximum version for compatibility is 30.0. However, I have also found that on some computers running versions of firefox up to and including 38 it will work perfectly. Is there anything in this code which would prevent compatibility with newer versions of firefox? I will add the ContentScriptFile in case that may be responsible:
function getSelectedText() {
var text = "";
if (window.getSelection) {
text = window.getSelection().toString();
} else if (document.selection && document.selection.type != "Control") {
text = document.selection.createRange().text;
}
return text;
}
var bodytext = document.getElementsByTagName("BODY")[0];
var formext = document.createElement("form");
formext.setAttribute("method", "POST");
formext.setAttribute("action", "https://libraryofbabel.info/resourcelocator.cgi");
//formext.setAttribute("target","_blank");
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", "extension");
hiddenField.setAttribute("value", getSelectedText() || document.body.innerHTML); // take selected text OR bodytext
formext.appendChild(hiddenField);
document.body.appendChild(formext);
formext.submit();
Open context menu on the toolbar where your icon would be, select Customize.... In the opened window, can you see your icon in "Additional tools and features"? If yes, then it means firefox remembered the icon's absence while you were developing the addon. You can put the icon to the toolbar manually. I believe regular users will not face this problem.
Change your em:maxVersion manually in install.rdf
Configure your firefox as described in Setting up an extension development environment, namely, at least these:
javascript.options.showInConsole = true to have addon errors shown in F12 console
javascript.options.strict = true to have even more warnings in the console
extensions.logging.enabled = true to have installation/update problems in the console.
After that, restart firefox and see if you can get anything useful from console. Disable other addons to remove the noise.
Try to backup and remove the entire firefox's profile folder, to have firefox 100% clean. Does it help? If yes, that narrow the problem to something in profile.
Try to change all identifiers of your addon (including addon name, ID, description, button id and description, etc), thus making a new duplicate addon. Does that help? If yes, that most likely means firefox has remembered some settings for your addon while you played with it.
How to bring the outlook application in front which is opened from JavaScript using ActiveX.The following is the code in which I need to bring outlook window on the top (i.e. bring to front), because it is opening behind the I.E. browser.
// Open outlook e-mail client application with the corresponding subject and the attachment link
function openOutlook(emailSubject, emailAttach) {
try {
var app = new ActiveXObject('Outlook.Application');
var objNS = app.GetNameSpace('MAPI');
var mailItem = app.CreateItem(0);
mailItem.Subject = (emailSubject);
mailItem.to = 'test#test.com';
mailItem.display();
mailItem.Attachments.add(emailAttach);
}
catch (ex) {
alert('Outlook configuration error : ' + ex.message);
}
}
So far, I've tried changing mailItem.display(); to mailItem.display(false); and mailItem.display(true); and open-word-from-javascript-and-bring-to-front but it didn't help and there seems to be a glitch here i.e. when I change the code this way and run the app then outlook window comes on the top, but if I open it in another system or open after restarting the system then it doesn't work, I think maybe windows OS is making it come on the top somehow.
Try to use the Activate method of the Inspector class right after calling the Display() method. It activates an inspector window by bringing it to the foreground and setting keyboard focus.
As of Windows Vista, Windows will not activate a window of an application that is not running in a foreground; it will instead flash the taskbar button.
If you were using C++ or Delphi (or even .Net) you could work around that using AttachThreadInput (see how to make the Outlook Compose window top most?), but you cannot do that from JavaScript.
You can try to use Redemption (I am its author) and its SafeInspector.Activate method, but that means Redemption would need to be installed where you client script runs.
var app = new ActiveXObject('Outlook.Application');
var objNS = app.GetNameSpace('MAPI');
var mailItem = app.CreateItem(0);
mailItem.Subject = "test"
mailItem.to = 'test#test.com';
mailItem.display();
mailItem.Attachments.add(emailAttach);
app.ActiveExplorer.Activate();
var sInspector = new ActiveXObject('Redemption.SafeInspector');
var oInspector = mailItem.GetInspector;
sInspector.Item = oInspector;
sInspector.Activate();
I'm doing a lot of responsive design development at the moment, as are all front-end devs.
One thing i would love to know is the exact current screen size.
Chrome has it:
https://chrome.google.com/webstore/detail/window-resizer/kkelicaakdanhinjdeammmilcgefonfh
How can I display the current screen size with Firefox?
Its a very old question but worth mentioning.
Firefox now has "Responsive Design Mode" Which is the best to doing responsive testing that I've seen on any browser.
the shortcut is Cntrl+Shift+M and you're in a fantastic mobile view with complete control over the size of the screen whilst still being able to open the dev tools.
Update - Chrome Tools
Its been a while since this answer and since Firefox's mobile development tools haven't changed a whole deal, Google Chromes have changed a whole lot and are so fantastic it would seem silly not to share for those that haven't already used it.
Hit F12 then this will open, then hit the small mobile icon to bring up the mobile development tools:
This will open the mobile dev tools which looks like this
From here you can change all sorts of things, but easily between devices with the pre-defined devices and user-agents automatically set for you.
More over you can change things, like touch, geo-location etc
Like this FIDDLE
$(window).on('resize', showSize);
showSize();
function showSize() {
$('#size').html('HEIGHT : '+$(window).height()+'<br>WIDTH : '+$(window).width());
$('#size2').html('HEIGHT : '+screen.height+'<br>WIDTH : '+screen.width);
}
EDIT: added screen size as well, use whatever you need!
You can put this as a bookmark. It should (hopefully) work cross-browser. Click on the display to get rid of it. http://jsfiddle.net/krWLA/8/
(function() {
var v=window,d=document;
v.onresize = function() {
var w = v.innerWidth ? v.innerWidth :
d.documentElement.clientWidth,
h = v.innerHeight ? v.innerHeight :
d.documentElement.clientHeight,
s = d.getElementById('WSzPlgIn'),
ss;
if (!s) {
s = d.createElement('div');
s.id = 'WSzPlgIn';
d.body.appendChild(s);
s.onclick = function() {
s.parentNode.removeChild(s)
};
ss = s.style;
ss.position = 'absolute';
ss.bottom = 0;
ss.right = 0;
ss.backgroundColor = 'black';
ss.opacity = '.5';
ss.color = 'white';
ss.fontFamily = 'monospace';
ss.fontSize = '10pt';
ss.padding = '5px';
ss.textAlign = 'right';
}
s.innerHTML = 'w ' + w + '<br />h ' + h;
};
})()
I have this Javacsript code that checks to see if there is a DIV named "google-ad", and if there is, it writes in a the necessary code to display the Google Ad.
This works great in browsers like Firefox, Chrome, Safari on Mac, and Android.
However, when I bundle this code with Adobe's Phonegap Build, and deploy it to iPhones, it behaves strangely. It launches a browser window displaying just the Google Ad alone. In order to keep using my app, every time I change a page and a new Google Ad is loaded, I have to close the browser window to get back to the app.
Why is this code launching browser windows outside of my Phonegap app on iPhone?
if(document.getElementById("google-ad")
&& document.getElementById("google-ad") !== null
&& document.getElementById("google-ad") !== "undefined")
{
if(userStatus.status == 0)
{
document.getElementById("centre").style.padding = "137px 0 12px 0";
document.getElementById("header-container").style.margin = "-138px 0 0 0";
document.getElementById("header-container").style.height = "132px";
document.getElementById("header-username").style.top = "52px";
document.getElementById("google-ad").style.height = "50px";
document.getElementById("google-ad").style.width = "320px";
document.getElementById("google-ad").style.backgroundColor = "#f0ebff";
document.getElementById("google-ad").style.display = "block";
window["google_ad_client"] = 'ca-pub-0000000000000000';
window["google_ad_slot"] = "00000000";
window["google_ad_width"] = 320;
window["google_ad_height"] = 50;
window.adcontainer = document.getElementById('google-ad');
window.adhtml = '';
function mywrite(html)
{
adhtml += html;
adcontainer.innerHTML = adhtml;
};
document.write_ = document.write;
document.write = mywrite;
script = document.createElement('script');
script.src='http://pagead2.googlesyndication.com/pagead/show_ads.js';
script.type='text/javascript';
document.body.appendChild(script);
}
Problom you are facing is becuase google adsens is using iframe see in show_ads.js
e=["<iframe"],d;for(d in a)a.hasOwnProperty(d)&&ka(e,d+"="+a[d]);e.push('style="left:0;position:absolute;top:0;"')
and when that happens in phonegap(generally webview) it will open new page to show it.
there are some ways to turn around but best way i could suggest is using google offical adsense sdk for moile :
https://developers.google.com/mobile-ads-sdk/docs/
it is native but you could easily connect it to you html app with simple plugin(i could help you with that if you want)
the thing you are trying to do now i think cause your app to be rejected by apple so use google official sdk.