Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | 'use strict'; |
michael@0 | 5 | |
michael@0 | 6 | const { Loader } = require('sdk/test/loader'); |
michael@0 | 7 | const { show, hide } = require('sdk/ui/sidebar/actions'); |
michael@0 | 8 | const { isShowing } = require('sdk/ui/sidebar/utils'); |
michael@0 | 9 | const { getMostRecentBrowserWindow, isWindowPrivate } = require('sdk/window/utils'); |
michael@0 | 10 | const { open, close, focus, promise: windowPromise } = require('sdk/window/helpers'); |
michael@0 | 11 | const { setTimeout } = require('sdk/timers'); |
michael@0 | 12 | const { isPrivate } = require('sdk/private-browsing'); |
michael@0 | 13 | const { data } = require('sdk/self'); |
michael@0 | 14 | const { URL } = require('sdk/url'); |
michael@0 | 15 | |
michael@0 | 16 | const { BUILTIN_SIDEBAR_MENUITEMS, isSidebarShowing, |
michael@0 | 17 | getSidebarMenuitems, getExtraSidebarMenuitems, makeID, simulateCommand, |
michael@0 | 18 | simulateClick, isChecked } = require('./sidebar/utils'); |
michael@0 | 19 | |
michael@0 | 20 | exports.testSideBarIsInNewPrivateWindows = function(assert, done) { |
michael@0 | 21 | const { Sidebar } = require('sdk/ui/sidebar'); |
michael@0 | 22 | let testName = 'testSideBarIsInNewPrivateWindows'; |
michael@0 | 23 | let sidebar = Sidebar({ |
michael@0 | 24 | id: testName, |
michael@0 | 25 | title: testName, |
michael@0 | 26 | url: 'data:text/html;charset=utf-8,'+testName |
michael@0 | 27 | }); |
michael@0 | 28 | |
michael@0 | 29 | let startWindow = getMostRecentBrowserWindow(); |
michael@0 | 30 | let ele = startWindow.document.getElementById(makeID(testName)); |
michael@0 | 31 | assert.ok(ele, 'sidebar element was added'); |
michael@0 | 32 | |
michael@0 | 33 | open(null, { features: { private: true } }).then(function(window) { |
michael@0 | 34 | let ele = window.document.getElementById(makeID(testName)); |
michael@0 | 35 | assert.ok(isPrivate(window), 'the new window is private'); |
michael@0 | 36 | assert.ok(!!ele, 'sidebar element was added'); |
michael@0 | 37 | |
michael@0 | 38 | sidebar.destroy(); |
michael@0 | 39 | assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE'); |
michael@0 | 40 | assert.ok(!startWindow.document.getElementById(makeID(testName)), 'sidebar id DNE'); |
michael@0 | 41 | |
michael@0 | 42 | return close(window); |
michael@0 | 43 | }).then(done).then(null, assert.fail); |
michael@0 | 44 | } |
michael@0 | 45 | |
michael@0 | 46 | // Disabled in order to land other fixes, see bug 910647 for further details. |
michael@0 | 47 | /* |
michael@0 | 48 | exports.testSidebarIsOpenInNewPrivateWindow = function(assert, done) { |
michael@0 | 49 | const { Sidebar } = require('sdk/ui/sidebar'); |
michael@0 | 50 | let testName = 'testSidebarIsOpenInNewPrivateWindow'; |
michael@0 | 51 | let window = getMostRecentBrowserWindow(); |
michael@0 | 52 | |
michael@0 | 53 | let sidebar = Sidebar({ |
michael@0 | 54 | id: testName, |
michael@0 | 55 | title: testName, |
michael@0 | 56 | url: 'data:text/html;charset=utf-8,'+testName |
michael@0 | 57 | }); |
michael@0 | 58 | |
michael@0 | 59 | assert.equal(isPrivate(window), false, 'the window is not private'); |
michael@0 | 60 | |
michael@0 | 61 | sidebar.on('show', function() { |
michael@0 | 62 | assert.equal(isSidebarShowing(window), true, 'the sidebar is showing'); |
michael@0 | 63 | assert.equal(isShowing(sidebar), true, 'the sidebar is showing'); |
michael@0 | 64 | |
michael@0 | 65 | windowPromise(window.OpenBrowserWindow({private: true}), 'DOMContentLoaded').then(function(window2) { |
michael@0 | 66 | assert.equal(isPrivate(window2), true, 'the new window is private'); |
michael@0 | 67 | |
michael@0 | 68 | let sidebarEle = window2.document.getElementById('sidebar'); |
michael@0 | 69 | |
michael@0 | 70 | // wait for the sidebar to load something |
michael@0 | 71 | function onSBLoad() { |
michael@0 | 72 | sidebarEle.contentDocument.getElementById('web-panels-browser').addEventListener('load', function() { |
michael@0 | 73 | assert.equal(isSidebarShowing(window), true, 'the sidebar is showing in old window still'); |
michael@0 | 74 | assert.equal(isSidebarShowing(window2), true, 'the sidebar is showing in the new private window'); |
michael@0 | 75 | assert.equal(isShowing(sidebar), true, 'the sidebar is showing'); |
michael@0 | 76 | |
michael@0 | 77 | sidebar.destroy(); |
michael@0 | 78 | close(window2).then(done); |
michael@0 | 79 | }, true); |
michael@0 | 80 | } |
michael@0 | 81 | |
michael@0 | 82 | sidebarEle.addEventListener('load', onSBLoad, true); |
michael@0 | 83 | |
michael@0 | 84 | assert.pass('waiting for the sidebar to open...'); |
michael@0 | 85 | }, assert.fail).then(null, assert.fail); |
michael@0 | 86 | }); |
michael@0 | 87 | |
michael@0 | 88 | sidebar.show(); |
michael@0 | 89 | } |
michael@0 | 90 | */ |
michael@0 | 91 | // TEST: edge case where web panel is destroyed while loading |
michael@0 | 92 | exports.testDestroyEdgeCaseBugWithPrivateWindow = function(assert, done) { |
michael@0 | 93 | const { Sidebar } = require('sdk/ui/sidebar'); |
michael@0 | 94 | let testName = 'testDestroyEdgeCaseBug'; |
michael@0 | 95 | let window = getMostRecentBrowserWindow(); |
michael@0 | 96 | let sidebar = Sidebar({ |
michael@0 | 97 | id: testName, |
michael@0 | 98 | title: testName, |
michael@0 | 99 | url: 'data:text/html;charset=utf-8,'+testName |
michael@0 | 100 | }); |
michael@0 | 101 | |
michael@0 | 102 | // NOTE: purposely not listening to show event b/c the event happens |
michael@0 | 103 | // between now and then. |
michael@0 | 104 | sidebar.show(); |
michael@0 | 105 | |
michael@0 | 106 | assert.equal(isPrivate(window), false, 'the new window is not private'); |
michael@0 | 107 | assert.equal(isSidebarShowing(window), true, 'the sidebar is showing'); |
michael@0 | 108 | |
michael@0 | 109 | //assert.equal(isShowing(sidebar), true, 'the sidebar is showing'); |
michael@0 | 110 | |
michael@0 | 111 | open(null, { features: { private: true } }).then(focus).then(function(window2) { |
michael@0 | 112 | assert.equal(isPrivate(window2), true, 'the new window is private'); |
michael@0 | 113 | assert.equal(isSidebarShowing(window2), false, 'the sidebar is not showing'); |
michael@0 | 114 | assert.equal(isShowing(sidebar), false, 'the sidebar is not showing'); |
michael@0 | 115 | |
michael@0 | 116 | sidebar.destroy(); |
michael@0 | 117 | assert.pass('destroying the sidebar'); |
michael@0 | 118 | |
michael@0 | 119 | close(window2).then(function() { |
michael@0 | 120 | let loader = Loader(module); |
michael@0 | 121 | |
michael@0 | 122 | assert.equal(isPrivate(window), false, 'the current window is not private'); |
michael@0 | 123 | |
michael@0 | 124 | let sidebar = loader.require('sdk/ui/sidebar').Sidebar({ |
michael@0 | 125 | id: testName, |
michael@0 | 126 | title: testName, |
michael@0 | 127 | url: 'data:text/html;charset=utf-8,'+ testName, |
michael@0 | 128 | onShow: function() { |
michael@0 | 129 | assert.pass('onShow works for Sidebar'); |
michael@0 | 130 | loader.unload(); |
michael@0 | 131 | |
michael@0 | 132 | let sidebarMI = getSidebarMenuitems(); |
michael@0 | 133 | for (let mi of sidebarMI) { |
michael@0 | 134 | assert.ok(BUILTIN_SIDEBAR_MENUITEMS.indexOf(mi.getAttribute('id')) >= 0, 'the menuitem is for a built-in sidebar') |
michael@0 | 135 | assert.ok(!isChecked(mi), 'no sidebar menuitem is checked'); |
michael@0 | 136 | } |
michael@0 | 137 | assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE'); |
michael@0 | 138 | assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing'); |
michael@0 | 139 | |
michael@0 | 140 | done(); |
michael@0 | 141 | } |
michael@0 | 142 | }) |
michael@0 | 143 | |
michael@0 | 144 | sidebar.show(); |
michael@0 | 145 | assert.pass('showing the sidebar'); |
michael@0 | 146 | }).then(null, assert.fail); |
michael@0 | 147 | }).then(null, assert.fail); |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | exports.testShowInPrivateWindow = function(assert, done) { |
michael@0 | 151 | const { Sidebar } = require('sdk/ui/sidebar'); |
michael@0 | 152 | let testName = 'testShowInPrivateWindow'; |
michael@0 | 153 | let window1 = getMostRecentBrowserWindow(); |
michael@0 | 154 | let url = 'data:text/html;charset=utf-8,'+testName; |
michael@0 | 155 | |
michael@0 | 156 | let sidebar1 = Sidebar({ |
michael@0 | 157 | id: testName, |
michael@0 | 158 | title: testName, |
michael@0 | 159 | url: url |
michael@0 | 160 | }); |
michael@0 | 161 | let menuitemID = makeID(sidebar1.id); |
michael@0 | 162 | |
michael@0 | 163 | assert.equal(sidebar1.url, url, 'url getter works'); |
michael@0 | 164 | assert.equal(isShowing(sidebar1), false, 'the sidebar is not showing'); |
michael@0 | 165 | assert.ok(!isChecked(window1.document.getElementById(menuitemID)), |
michael@0 | 166 | 'the menuitem is not checked'); |
michael@0 | 167 | assert.equal(isSidebarShowing(window1), false, 'the new window sidebar is not showing'); |
michael@0 | 168 | |
michael@0 | 169 | windowPromise(window1.OpenBrowserWindow({ private: true }), 'load').then(function(window) { |
michael@0 | 170 | let { document } = window; |
michael@0 | 171 | assert.equal(isWindowPrivate(window), true, 'new window is private'); |
michael@0 | 172 | assert.equal(isPrivate(window), true, 'new window is private'); |
michael@0 | 173 | |
michael@0 | 174 | sidebar1.show().then( |
michael@0 | 175 | function good() { |
michael@0 | 176 | assert.equal(isShowing(sidebar1), true, 'the sidebar is showing'); |
michael@0 | 177 | assert.ok(!!document.getElementById(menuitemID), |
michael@0 | 178 | 'the menuitem exists on the private window'); |
michael@0 | 179 | assert.equal(isSidebarShowing(window), true, 'the new window sidebar is showing'); |
michael@0 | 180 | |
michael@0 | 181 | sidebar1.destroy(); |
michael@0 | 182 | assert.equal(isSidebarShowing(window), false, 'the new window sidebar is showing'); |
michael@0 | 183 | assert.ok(!window1.document.getElementById(menuitemID), |
michael@0 | 184 | 'the menuitem on the new window dne'); |
michael@0 | 185 | |
michael@0 | 186 | // test old window state |
michael@0 | 187 | assert.equal(isSidebarShowing(window1), false, 'the old window sidebar is not showing'); |
michael@0 | 188 | assert.equal(window1.document.getElementById(menuitemID), |
michael@0 | 189 | null, |
michael@0 | 190 | 'the menuitem on the old window dne'); |
michael@0 | 191 | |
michael@0 | 192 | close(window).then(done).then(null, assert.fail); |
michael@0 | 193 | }, |
michael@0 | 194 | function bad() { |
michael@0 | 195 | assert.fail('a successful show should not happen here..'); |
michael@0 | 196 | }); |
michael@0 | 197 | }).then(null, assert.fail); |
michael@0 | 198 | } |
michael@0 | 199 | |
michael@0 | 200 | // If the module doesn't support the app we're being run in, require() will |
michael@0 | 201 | // throw. In that case, remove all tests above from exports, and add one dummy |
michael@0 | 202 | // test that passes. |
michael@0 | 203 | try { |
michael@0 | 204 | require('sdk/ui/sidebar'); |
michael@0 | 205 | } |
michael@0 | 206 | catch (err) { |
michael@0 | 207 | if (!/^Unsupported Application/.test(err.message)) |
michael@0 | 208 | throw err; |
michael@0 | 209 | |
michael@0 | 210 | module.exports = { |
michael@0 | 211 | 'test Unsupported Application': assert => assert.pass(err.message) |
michael@0 | 212 | } |
michael@0 | 213 | } |