Skip to content
This repository has been archived by the owner on Feb 26, 2022. It is now read-only.

Commit

Permalink
Bug 840014: tabs.open() and windows.open() now take a isPrivate option
Browse files Browse the repository at this point in the history
  • Loading branch information
erikvold committed Feb 17, 2013
1 parent 682a69c commit dd39cbf
Show file tree
Hide file tree
Showing 14 changed files with 133 additions and 23 deletions.
4 changes: 4 additions & 0 deletions doc/module-source/sdk/tabs.md
Expand Up @@ -139,6 +139,10 @@ opened in the first tab in that window. This is an optional property.
If present and true, the new tab will be opened to the right of the active tab
and will not be active. This is an optional property.

@prop isPrivate {boolean}
Boolean which will determine if a private tab should be opened.
Private browsing mode must be supported in order to do this.

@prop [isPinned] {boolean}
If present and true, then the new tab will be pinned as an
[app tab](http://support.mozilla.com/en-US/kb/what-are-app-tabs).
Expand Down
4 changes: 4 additions & 0 deletions doc/module-source/sdk/windows.md
Expand Up @@ -118,6 +118,10 @@ If the only option being used is `url`, then a bare string URL can be passed to
String URL to be opened in the new window.
This is a required property.

@prop isPrivate {boolean}
Boolean which will determine if a private window should be opened.
Private browsing mode must be supported in order to do this.

@prop [onOpen] {function}
A callback function that is called when the window has opened. This does not
mean that the URL content has loaded, only that the window itself is fully
Expand Down
1 change: 1 addition & 0 deletions lib/sdk/tabs/common.js
Expand Up @@ -13,6 +13,7 @@ function Options(options) {
url: { is: ["string"] },
inBackground: { is: ["undefined", "boolean"] },
isPinned: { is: ["undefined", "boolean"] },
isPrivate: { is: ["undefined", "boolean"] },
onOpen: { is: ["undefined", "function"] },
onClose: { is: ["undefined", "function"] },
onReady: { is: ["undefined", "function"] },
Expand Down
49 changes: 44 additions & 5 deletions lib/sdk/tabs/tabs-firefox.js
Expand Up @@ -4,19 +4,58 @@
'use strict';

// TODO: BUG 792670 - remove dependency below
const { browserWindows } = require('../windows');
const { browserWindows: windows } = require('../windows');
const { tabs } = require('../windows/tabs-firefox');
const { isPrivate } = require('../private-browsing');
const { isWindowPBSupported } = require('../private-browsing/utils')

Object.defineProperties(tabs, {
open: { value: function open(options) {
if (options.inNewWindow)
if (options.inNewWindow) {
// `tabs` option is under review and may be removed.
return browserWindows.open({ tabs: [ options ] });
// Open in active window if new window was not required.
return browserWindows.activeWindow.tabs.open(options);
windows.open({
tabs: [ options ],
isPrivate: options.isPrivate
});
return undefined;
}
// Open in active window if new window was not required..


let activeWindow = windows.activeWindow;
let privateState = !!options.isPrivate;
// if the active window is in the state that we need then use it
if (!isWindowPBSupported || privateState === isPrivate(activeWindow)) {
activeWindow.tabs.open(options);
}
else {
// find a window in the state that we need
let window = getWindow(privateState);
if (window) {
window.tabs.open(options);
}
// open a window in the state that we need
else {
windows.open({
tabs: [ options ],
isPrivate: options.isPrivate
});
}
}

return undefined;
}}
});

function getWindow(privateState) {
for each (let window in windows) {
if (privateState === isPrivate(window)) {
return window;
}
}
return null;
}

// Workaround for bug 674195. Freezing objects from other compartments fail,
// so we use `Object.freeze` from the same component as objects
// `hasOwnProperty`. Since `hasOwnProperty` here will be from other component
Expand Down
7 changes: 5 additions & 2 deletions lib/sdk/tabs/utils.js
Expand Up @@ -102,10 +102,13 @@ function openTab(window, url, options) {
return window.BrowserApp.addTab(url, {
selected: options.inBackground ? false : true,
pinned: options.isPinned || false,
isPrivate: options.private || false
isPrivate: options.isPrivate || false
});
}
return window.gBrowser.addTab(url);
let tab = window.gBrowser.addTab(url);
if (!options.inBackground)
activateTab(tab);
return tab;
};
exports.openTab = openTab;

Expand Down
7 changes: 5 additions & 2 deletions lib/sdk/windows/firefox.js
Expand Up @@ -68,7 +68,7 @@ const BrowserWindowTrait = Trait.compose(
this._tabOptions = [ Options(options.url) ];
}

this._private = !!options.private;
this._isPrivate = !!options.isPrivate;

this._load();

Expand Down Expand Up @@ -211,7 +211,10 @@ const browserWindows = Trait.resolve({ toString: null }).compose(
open: function open(options) {
if (typeof options === "string")
// `tabs` option is under review and may be removed.
options = { tabs: [Options(options)] };
options = {
tabs: [Options(options)],
isPrivate: options.isPrivate
};
return BrowserWindow(options);
},

Expand Down
2 changes: 1 addition & 1 deletion lib/sdk/windows/loader.js
Expand Up @@ -41,7 +41,7 @@ const WindowLoader = Trait.compose({
_load: function _load() {
if (this.__window) return;
this._window = openDialog({
private: this._private,
private: this._isPrivate,
args: this._tabOptions.map(function(options) options.url).join("|")
});
},
Expand Down
3 changes: 2 additions & 1 deletion lib/sdk/windows/tabs-fennec.js
Expand Up @@ -53,7 +53,8 @@ const Tabs = Class({
}

let rawTab = openTab(windowNS(activeWin).window, options.url, {
inBackground: options.inBackground
inBackground: options.inBackground,
isPrivate: options.isPrivate
});

// by now the tab has been created
Expand Down
14 changes: 9 additions & 5 deletions lib/sdk/windows/tabs-firefox.js
Expand Up @@ -13,9 +13,10 @@ const { Tab } = require("../tabs/tab");
const { EventEmitter } = require("../deprecated/events");
const { EVENTS } = require("../tabs/events");
const { getOwnerWindow, getActiveTab, getTabs,
openTab, activateTab } = require("../tabs/utils");
openTab } = require("../tabs/utils");
const { Options } = require("../tabs/common");
const { observer: tabsObserver } = require("../tabs/observer");
const { isWindowPrivate } = require("../private-browsing/utils");

const TAB_BROWSER = "tabbrowser";

Expand Down Expand Up @@ -152,11 +153,14 @@ const TabList = List.resolve({ constructor: "_init" }).compose(
_activeTab: null,

open: function open(options) {
let window = this._window;
let chromeWindow = window._window;
options = Options(options);
this._window._tabOptions.push(options);
let tab = openTab(this._window._window, options.url);
if (!options.inBackground)
activateTab(tab);

// save the tab options
window._tabOptions.push(options);
// open the tab
let tab = openTab(chromeWindow, options.url, options);
}
// This is ugly, but necessary. Will be removed by #596248
}).resolve({ toString: null })
Expand Down
2 changes: 1 addition & 1 deletion test/private-browsing/tabs.js
Expand Up @@ -12,7 +12,7 @@ exports.testIsPrivateOnTab = function(test) {
test.assert(!pb.isPrivate(chromeWindow), 'the top level window is not private');

let rawTab = openTab(chromeWindow, 'data:text/html,<h1>Hi!</h1>', {
private: true
isPrivate: true
});

// test that the tab is private
Expand Down
2 changes: 1 addition & 1 deletion test/private-browsing/windows.js
Expand Up @@ -32,7 +32,7 @@ exports.testPerWindowPrivateBrowsingGetter = function(assert, done) {

exports.testIsPrivateOnWindowOn = function(assert, done) {
windows.open({
private: true,
isPrivate: true,
onOpen: function(window) {
assert.equal(isPrivate(window), true, 'isPrivate for a window is true when it should be');
assert.equal(isPrivate(window.tabs[0]), true, 'isPrivate for a tab is false when it should be');
Expand Down
14 changes: 10 additions & 4 deletions test/test-private-browsing.js
Expand Up @@ -7,6 +7,7 @@ const { Ci } = require('chrome');
const { pb, pbUtils, getOwnerWindow } = require('./private-browsing/helper');
const { merge } = require('sdk/util/object');
const windows = require('sdk/windows').browserWindows;
const tabs = require('sdk/tabs');
const winUtils = require('sdk/window/utils');
const { is } = require('sdk/system/xul-app');
const { isPrivate } = require('private-browsing');
Expand Down Expand Up @@ -64,22 +65,27 @@ exports.testGetOwnerWindow = function(test) {
let chromeWindow = getOwnerWindow(window);
test.assert(chromeWindow instanceof Ci.nsIDOMWindow, 'associated window is found');

window.tabs.open({
tabs.open({
url: 'about:blank',
private: true, // should be ignored in this case
isPrivate: true,
onOpen: function(tab) {
// test that getOwnerWindow works as expected
if (is('Fennec')) {
test.assertNotStrictEqual(chromeWindow, getOwnerWindow(tab));
test.assert(getOwnerWindow(tab) instanceof Ci.nsIDOMWindow);
}
else {
test.assertStrictEqual(chromeWindow, getOwnerWindow(tab), 'associated window is the same for window and window\'s tab');
if (pbUtils.isWindowPBSupported) {
test.assertNotStrictEqual(chromeWindow, getOwnerWindow(tab), 'associated window is not the same for window and window\'s tab');
}
else {
test.assertStrictEqual(chromeWindow, getOwnerWindow(tab), 'associated window is the same for window and window\'s tab');
}
}

// test that the tab is not private
// private flag should be ignored by default
test.assert(!isPrivate(tab));
// test.assert(!isPrivate(tab));

tab.close(function() test.done());
}
Expand Down
24 changes: 23 additions & 1 deletion test/test-tabs-common.js
Expand Up @@ -6,6 +6,8 @@
const { Loader } = require('sdk/test/loader');
const { browserWindows } = require('sdk/windows');
const tabs = require('sdk/tabs');
const { isPrivate } = require('sdk/private-browsing');
const { isWindowPBSupported, isTabPBSupported } = require('sdk/private-browsing/utils');

const URL = 'data:text/html;charset=utf-8,<html><head><title>#title#</title></head></html>';

Expand Down Expand Up @@ -289,8 +291,28 @@ exports.testTabContentTypeAndReload = function(test) {
}
else {
test.assertEqual(tab.contentType, "text/xml");
tab.close(function() test.done());
tab.close(function() {
test.done();
});
}
}
});
};

// test that it is possible to open a private tab
exports.testTabOpenPrivate = function(test) {
test.waitUntilDone();

tabs.open({
url: 'about:mozilla',
isPrivate: true,
onReady: function(tab) {
test.assertEqual(tab.url, 'about:mozilla', 'opened correct tab');
test.assertEqual(isPrivate(tab), (isWindowPBSupported || isTabPBSupported), 'tab is private');

tab.close(function() {
test.done();
});
}
});
}
23 changes: 23 additions & 0 deletions test/windows/test-firefox-windows.js
Expand Up @@ -12,6 +12,8 @@ const wm = Cc['@mozilla.org/appshell/window-mediator;1'].
const { browserWindows } = require("sdk/windows");
const tabs = require("sdk/tabs");
const { WindowTracker } = require("sdk/deprecated/window-utils");
const { isPrivate } = require('sdk/private-browsing');
const { isWindowPBSupported } = require('sdk/private-browsing/utils');

// TEST: open & close window
exports.testOpenAndCloseWindow = function(test) {
Expand Down Expand Up @@ -370,3 +372,24 @@ exports.testTrackWindows = function(test) {

openWindow();
}

// test that it is possible to open a private window
exports.testWindowOpenPrivate = function(test) {
test.waitUntilDone();

browserWindows.open({
url: 'about:mozilla',
isPrivate: true,
onOpen: function(window) {
let tab = window.tabs[0];
tab.once('ready', function() {
test.assertEqual(tab.url, 'about:mozilla', 'opened correct tab');
test.assertEqual(isPrivate(tab), isWindowPBSupported, 'tab is private');

tab.close(function() {
test.done();
});
});
}
});
}

0 comments on commit dd39cbf

Please sign in to comment.