Infocatcher / Private_Tab

Adds private tabs, restartless extension for Firefox (20.0+) and SeaMonkey (2.17+)
https://addons.mozilla.org/addon/private-tab/
Other
86 stars 20 forks source link

Works only in Gecko 20.0 and higher because used API doesn't exist in older versions!

WebExtensions and compatibility with Firefox 57+

Issue #254 + Private Tab WE repository

Known issues:

Styles:

You can use .tabbrowser-tab[privateTab-isPrivate] (private tab), #main-window[privateTab-selectedTabIsPrivate] (selected tab is private) and #main-window[privateTab-isPrivate] (built-in private window) selectors in styles for userChrome.css/Stylish.
Example styles:

Options

See extensions.privateTab.* preferences in about:config page, some descriptions can be found in defaults/preferences/prefs.js.

Keyboard shortcuts:

You can modify keyboard shortcuts through about:config page, see notes about extensions.privateTab.key.* preferences in defaults/preferences/prefs.js.

Troubleshooting:

Try new clean Firefox profile to ensure that there are no conflicts with another extensions or some specific configuration.

Debug logs:

Options in about:config:

Then use Browser Console (formerly Error Console, Ctrl+Shift+J) to see messages like [Private Tab] ….

API for other extensions:

Events:

You can listen for following events:

event.type event.target event.detail Description
PrivateTab:PrivateChanged tab 1 – private tab
0 – not private
Changed private state of the tab
event.explicitOriginalTarget – initial tab in case of toggling using duplication (Firefox 51+, Private Tab 0.2.1.3+)
PrivateTab:OpenInNewTab tab 1 – may be opened as child tab Link was opened in new private tab
PrivateTab:OpenNewTab tab 1 – opened using middle-click
(or left-click with any modifier)
Opened new (empty) private tab
API functions:

boolean privateTab.isTabPrivate(in DOMNode tab)
void privateTab.isTabPrivateAsync(in DOMNode tab, in function callback[, in object context])
boolean privateTab.toggleTabPrivate(in DOMNode tab[, in boolean isPrivate])
DOMNode privateTab.duplicateTabAndTogglePrivate(in DOMNode tab[, in boolean isPrivate])
DOMNode privateTab.replaceTabAndTogglePrivate(in DOMNode tab[, in boolean isPrivate[, in function onSuccessCallback]])
void privateTab.readyToOpenTab(in boolean isPrivate)
void privateTab.readyToOpenTabs(in boolean isPrivate)
boolean privateTab.hasClosedTabs
void privateTab.forgetClosedTabs()
boolean privateTab.tabLabelIsEmpty(in string tabLabel[, in boolean isEmpty])

privateTab.isTabPrivate()

Investigates that the tab are private (true) or not (false), example:

// Close all (visible) private tabs:
Array.slice(gBrowser.visibleTabs || gBrowser.tabs).forEach(function(tab) {
    if(privateTab.isTabPrivate(tab))
        gBrowser.removeTab(tab);
});
privateTab.isTabPrivateAsync()

The same as privateTab.isTabPrivate, but get real state of nsILoadContext.usePrivateBrowsing in multi-process mode (Electrolysis aka e10s), Private Tab 0.2.1+.
Not needed in most cases!

// Asynchronously get privacy state of given tab.
// In most cases should be replaced with synchronous privateTab.isTabPrivate()
privateTab.isTabPrivateAsync(gBrowser.selectedTab, function(isPrivate) {
    alert("Selected tab is " + (isPrivate ? "private" : "not private"));
});
privateTab.toggleTabPrivate()

Changes tab private state:
Toggle: privateTab.toggleTabPrivate(tab)
Make private: privateTab.toggleTabPrivate(tab, true)
Make not private: privateTab.toggleTabPrivate(tab, false)

// Make all (visible) tabs private:
Array.forEach(
    gBrowser.visibleTabs || gBrowser.tabs,
    function(tab) {
        if(!privateTab.isTabPrivate(tab))
            privateTab.toggleTabPrivate(tab, true);
    }
);
privateTab.duplicateTabAndTogglePrivate()

Duplicate already opened tab in private or non-private tab.

// Duplicate selected tab and toggle private state of duplicated tab
var tab = gBrowser.selectedTab;
var pos = "_tPos" in tab
    ? tab._tPos
    : Array.prototype.indexOf.call(gBrowser.tabs, tab); // SeaMonkey
var dupTab = gBrowser.selectedTab = privateTab.duplicateTabAndTogglePrivate(tab);
gBrowser.moveTabTo(dupTab, pos + 1); // Place right after initial tab
privateTab.replaceTabAndTogglePrivate()

Changes tab private state using tab duplication (for Firefox 52+):

// Duplicate selected tab, toggle private state of duplicated tab and then close initial tab
privateTab.replaceTabAndTogglePrivate(gBrowser.selectedTab);
// The same as above + also load new URL into duplicated tab (Private Tab 0.2.3+)
privateTab.replaceTabAndTogglePrivate(gBrowser.selectedTab, undefined, function onSuccess(dupTab) {
    dupTab.linkedBrowser.loadURI("https://example.com/");
});
privateTab.readyToOpenTab()

Allows to open private or not private tab (independent of any inheritance mechanism), example:

// Open in private tab:
privateTab.readyToOpenTab(true);
gBrowser.addTab("https://mozilla.org/");
// Open in not private tab:
privateTab.readyToOpenTab(false);
gBrowser.addTab("https://mozilla.org/");
privateTab.readyToOpenTabs()

Allows to open many private or not private tabs (independent of any inheritance mechanism), example:

// Open in private tabs:
privateTab.readyToOpenTabs(true);
gBrowser.addTab("https://mozilla.org/");
gBrowser.addTab("https://addons.mozilla.org/");
// ...
privateTab.stopToOpenTabs();
privateTab.hasClosedTabs

Only for extensions.privateTab.rememberClosedPrivateTabs = true, Private Tab 0.1.7.4+.
Return true, if there is at least one private tab in undo close list, example:

if(privateTab.hasClosedTabs)
    alert("We have at least one closed private tabs");
else
    alert("We don't have closed private tabs");
privateTab.forgetClosedTabs()

Only for extensions.privateTab.rememberClosedPrivateTabs = true, Private Tab 0.1.7.4+.
Forget about all closed private tabs in window, example:

// Forget about all closed private tabs in window
privateTab.forgetClosedTabs();
privateTab.tabLabelIsEmpty()

Mark tab label as empty (or non-empty), example:

// Mark tab label/URI as empty:
if("tabLabelIsEmpty" in privateTab) // Private Tab 0.1.7.2+
    privateTab.tabLabelIsEmpty("chrome://speeddial/content/speeddial.xul", true);
// Check state:
var isEmpty = privateTab.tabLabelIsEmpty("chrome://speeddial/content/speeddial.xul");
// Restore state (e.g. for restartless extensions):
privateTab.tabLabelIsEmpty("chrome://speeddial/content/speeddial.xul", false);

Note: used global storage for labels (not per-window)! So, it's enough to call this function only once.

Backward compatibility:

Check for Private Tab installed (and enabled):

if("privateTab" in window) {
    // Do something with "privateTab" object
}
Code examples:

Open link in private tab using FireGestures extension:

// Remember the active tab's position
var tab = gBrowser.selectedTab;
var pos = "_tPos" in tab
    ? tab._tPos
    : Array.prototype.indexOf.call(gBrowser.tabs, tab); // SeaMonkey
// Get the DOM node at the starting point of gesture
var srcNode = FireGestures.sourceNode;
// Get the link URL inside the node
var linkURL = FireGestures.getLinkURL(srcNode);
if (!linkURL)
    throw "Not on a link";
// Check the URL is safe
FireGestures.checkURL(linkURL, srcNode.ownerDocument);
// Open link in new private tab
privateTab.readyToOpenTab(true);
var newPrivateTab = gBrowser.addTab(linkURL);
gBrowser.moveTabTo(newPrivateTab, pos + 1); // Place right after initial tab