Add-ons using the techniques described in this document are considered a legacy technology in Firefox. Don't use these techniques to develop new add-ons. Use WebExtensions instead. If you maintain an add-on which uses the techniques described here, consider migrating it to use WebExtensions.
From Firefox 53 onwards, no new legacy add-ons will be accepted on addons.mozilla.org (AMO).
From Firefox 57 onwards, WebExtensions will be the only supported extension type, and Firefox will not load other types.
Even before Firefox 57, changes coming up in the Firefox platform will break many legacy extensions. These changes include multiprocess Firefox (e10s), sandboxing, and multiple content processes. Legacy extensions that are affected by these changes should migrate to WebExtensions if they can. See the "Compatibility Milestones" document for more.
A wiki page containing resources, migration paths, office hours, and more, is available to help developers transition to the new technologies.
Stable
Check whether a given object is private, so an add-on can respect private browsing
Usage
Per-window private browsing
Private browsing status is a property of an individual browser window.
The user enters private browsing by opening a new private browser window. When they do this, any existing non-private windows are kept open, so the user will typically have both private and non-private windows open at the same time.
Opting into private browsing
Add-ons built using the SDK must opt into private browsing by setting the following key in their package.json
file:
"permissions": {"private-browsing": true}
If an add-on has not opted in, then the high-level SDK modules will not expose private windows, or objects (such as tabs) that are associated with private windows:
-
the
windows
module will not list any private browser windows, generate any events for private browser windows, or let the add-on open any private browser windows -
the
tabs
module will not list any tabs that belong to private browser windows, and the add-on won't receive any events for such tabs -
any
ui
components will not be displayed in private browser windows -
any menus or menu items created using the
context-menu
will not be shown in context menus that belong to private browser windows -
the
page-mod
module will not attach content scripts to documents belonging to private browser windows -
any
panel
objects will not be shown if the active window is a private browser window -
the
selection
module will not include any selections made in private browser windows
Add-ons that have opted in will see private windows, so they will need to use the private-browsing
module to check whether objects are private, so as to avoid storing data derived from such objects.
Additionally, add-ons that use low-level modules such as window/utils
may see private browser windows with certain functions, even if they have not explicitly opted into private browsing.
Respecting private browsing
The private-browsing
module exports a single function isPrivate()
that takes an object, which may be a BrowserWindow
, tab
, or worker
, as an argument. It returns true
only if the object is:
- a private window, or
- a tab belonging to a private window, or
- a worker that's associated with a document hosted in a private window
- any window, tab, or worker if the browser has been configured to never remember history (Options->Privacy->History)
Add-ons can use this API to decide whether or not to store user data. For example, here's an add-on that stores the titles of tabs the user loads, and uses isPrivate()
to exclude the titles of tabs that were loaded into private windows:
var simpleStorage = require("simple-storage"); if (!simpleStorage.storage.titles) simpleStorage.storage.titles = []; require("tabs").on("ready", function(tab) { if (!require("sdk/private-browsing").isPrivate(tab)) { console.log("storing..."); simpleStorage.storage.titles.push(tab.title); } else { console.log("not storing, private data"); } });
Here's an add-on that uses a page-mod to log the content of pages loaded by the user, unless the page is private. In the handler for the page-mod's attach
event, it passes the worker into isPrivate()
:
var pageMod = require("sdk/page-mod"); var privateBrowsing = require("sdk/private-browsing"); var loggingScript = "self.port.on('log-content', function() {" + " console.log(document.body.innerHTML);" + "});"; function logPublicPageContent(worker) { if (privateBrowsing.isPrivate(worker)) { console.log("private window, doing nothing"); } else { worker.port.emit("log-content"); } } pageMod.PageMod({ include: "*", contentScript: loggingScript, onAttach: logPublicPageContent });
Tracking private-browsing exit
Sometimes it can be useful to cache some data from private windows while they are open, as long as you don't store it after the private browsing windows have been closed. For example, the "Downloads" window might want to display all downloads while there are still some private windows open, then clean out all the private data when all private windows have closed.
To do this with the SDK, you can listen to the system event named "last-pb-context-exited":
var events = require("sdk/system/events"); function listener(event) { console.log("last private window closed"); } events.on("last-pb-context-exited", listener);
Globals
Functions
isPrivate(object)
Function to check whether the given object is private. It takes an object as an argument, and returns true
only if the object is:
- a private
BrowserWindow
or - a
tab
belonging to a private window, or - a
worker
that's associated with a document hosted in a private window
Parameters
object : any
The object to check. This may be a BrowserWindow
, tab
, or worker
.