addon-sdk/source/lib/sdk/windows/firefox.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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 { Cc, Ci, Cr } = require('chrome'),
michael@0 7 { Trait } = require('../deprecated/traits'),
michael@0 8 { List } = require('../deprecated/list'),
michael@0 9 { EventEmitter } = require('../deprecated/events'),
michael@0 10 { WindowTabs, WindowTabTracker } = require('./tabs-firefox'),
michael@0 11 { WindowDom } = require('./dom'),
michael@0 12 { WindowLoader } = require('./loader'),
michael@0 13 { isBrowser, getWindowDocShell, windows: windowIterator } = require('../window/utils'),
michael@0 14 { Options } = require('../tabs/common'),
michael@0 15 apiUtils = require('../deprecated/api-utils'),
michael@0 16 unload = require('../system/unload'),
michael@0 17 windowUtils = require('../deprecated/window-utils'),
michael@0 18 { WindowTrackerTrait } = windowUtils,
michael@0 19 { ns } = require('../core/namespace'),
michael@0 20 { observer: windowObserver } = require('./observer'),
michael@0 21 { getOwnerWindow } = require('../private-browsing/window/utils');
michael@0 22 const { windowNS } = require('../window/namespace');
michael@0 23 const { isPrivateBrowsingSupported } = require('../self');
michael@0 24 const { ignoreWindow } = require('sdk/private-browsing/utils');
michael@0 25 const { viewFor } = require('../view/core');
michael@0 26
michael@0 27 /**
michael@0 28 * Window trait composes safe wrappers for browser window that are E10S
michael@0 29 * compatible.
michael@0 30 */
michael@0 31 const BrowserWindowTrait = Trait.compose(
michael@0 32 EventEmitter,
michael@0 33 WindowDom.resolve({ close: '_close' }),
michael@0 34 WindowTabs,
michael@0 35 WindowTabTracker,
michael@0 36 WindowLoader,
michael@0 37 /* WindowSidebars, */
michael@0 38 Trait.compose({
michael@0 39 _emit: Trait.required,
michael@0 40 _close: Trait.required,
michael@0 41 _load: Trait.required,
michael@0 42 /**
michael@0 43 * Constructor returns wrapper of the specified chrome window.
michael@0 44 * @param {nsIWindow} window
michael@0 45 */
michael@0 46 constructor: function BrowserWindow(options) {
michael@0 47 // Register this window ASAP, in order to avoid loop that would try
michael@0 48 // to create this window instance over and over (see bug 648244)
michael@0 49 windows.push(this);
michael@0 50
michael@0 51 // make sure we don't have unhandled errors
michael@0 52 this.on('error', console.exception.bind(console));
michael@0 53
michael@0 54 if ('onOpen' in options)
michael@0 55 this.on('open', options.onOpen);
michael@0 56 if ('onClose' in options)
michael@0 57 this.on('close', options.onClose);
michael@0 58 if ('onActivate' in options)
michael@0 59 this.on('activate', options.onActivate);
michael@0 60 if ('onDeactivate' in options)
michael@0 61 this.on('deactivate', options.onDeactivate);
michael@0 62 if ('window' in options)
michael@0 63 this._window = options.window;
michael@0 64
michael@0 65 if ('tabs' in options) {
michael@0 66 this._tabOptions = Array.isArray(options.tabs) ?
michael@0 67 options.tabs.map(Options) :
michael@0 68 [ Options(options.tabs) ];
michael@0 69 }
michael@0 70 else if ('url' in options) {
michael@0 71 this._tabOptions = [ Options(options.url) ];
michael@0 72 }
michael@0 73
michael@0 74 this._isPrivate = isPrivateBrowsingSupported && !!options.isPrivate;
michael@0 75
michael@0 76 this._load();
michael@0 77
michael@0 78 windowNS(this._public).window = this._window;
michael@0 79 getOwnerWindow.implement(this._public, getChromeWindow);
michael@0 80 viewFor.implement(this._public, getChromeWindow);
michael@0 81
michael@0 82 return this;
michael@0 83 },
michael@0 84 destroy: function () this._onUnload(),
michael@0 85 _tabOptions: [],
michael@0 86 _onLoad: function() {
michael@0 87 try {
michael@0 88 this._initWindowTabTracker();
michael@0 89 this._loaded = true;
michael@0 90 }
michael@0 91 catch(e) {
michael@0 92 this._emit('error', e);
michael@0 93 }
michael@0 94
michael@0 95 this._emitOnObject(browserWindows, 'open', this._public);
michael@0 96 },
michael@0 97 _onUnload: function() {
michael@0 98 if (!this._window)
michael@0 99 return;
michael@0 100 if (this._loaded)
michael@0 101 this._destroyWindowTabTracker();
michael@0 102
michael@0 103 this._emitOnObject(browserWindows, 'close', this._public);
michael@0 104 this._window = null;
michael@0 105 windowNS(this._public).window = null;
michael@0 106 // Removing reference from the windows array.
michael@0 107 windows.splice(windows.indexOf(this), 1);
michael@0 108 this._removeAllListeners();
michael@0 109 },
michael@0 110 close: function close(callback) {
michael@0 111 // maybe we should deprecate this with message ?
michael@0 112 if (callback) this.on('close', callback);
michael@0 113 return this._close();
michael@0 114 }
michael@0 115 })
michael@0 116 );
michael@0 117
michael@0 118 /**
michael@0 119 * Gets a `BrowserWindowTrait` for the given `chromeWindow` if previously
michael@0 120 * registered, `null` otherwise.
michael@0 121 */
michael@0 122 function getRegisteredWindow(chromeWindow) {
michael@0 123 for each (let window in windows) {
michael@0 124 if (chromeWindow === window._window)
michael@0 125 return window;
michael@0 126 }
michael@0 127
michael@0 128 return null;
michael@0 129 }
michael@0 130
michael@0 131 /**
michael@0 132 * Wrapper for `BrowserWindowTrait`. Creates new instance if wrapper for
michael@0 133 * window doesn't exists yet. If wrapper already exists then returns it
michael@0 134 * instead.
michael@0 135 * @params {Object} options
michael@0 136 * Options that are passed to the the `BrowserWindowTrait`
michael@0 137 * @returns {BrowserWindow}
michael@0 138 * @see BrowserWindowTrait
michael@0 139 */
michael@0 140 function BrowserWindow(options) {
michael@0 141 let window = null;
michael@0 142
michael@0 143 if ("window" in options)
michael@0 144 window = getRegisteredWindow(options.window);
michael@0 145
michael@0 146 return (window || BrowserWindowTrait(options))._public;
michael@0 147 }
michael@0 148 // to have proper `instanceof` behavior will go away when #596248 is fixed.
michael@0 149 BrowserWindow.prototype = BrowserWindowTrait.prototype;
michael@0 150 exports.BrowserWindow = BrowserWindow;
michael@0 151
michael@0 152 const windows = [];
michael@0 153
michael@0 154 const browser = ns();
michael@0 155
michael@0 156 function onWindowActivation (chromeWindow, event) {
michael@0 157 if (!isBrowser(chromeWindow)) return; // Ignore if it's not a browser window.
michael@0 158
michael@0 159 let window = getRegisteredWindow(chromeWindow);
michael@0 160
michael@0 161 if (window)
michael@0 162 window._emit(event.type, window._public);
michael@0 163 else
michael@0 164 window = BrowserWindowTrait({ window: chromeWindow });
michael@0 165
michael@0 166 browser(browserWindows).internals._emit(event.type, window._public);
michael@0 167 }
michael@0 168
michael@0 169 windowObserver.on("activate", onWindowActivation);
michael@0 170 windowObserver.on("deactivate", onWindowActivation);
michael@0 171
michael@0 172 /**
michael@0 173 * `BrowserWindows` trait is composed out of `List` trait and it represents
michael@0 174 * "live" list of currently open browser windows. Instance mutates itself
michael@0 175 * whenever new browser window gets opened / closed.
michael@0 176 */
michael@0 177 // Very stupid to resolve all `toStrings` but this will be fixed by #596248
michael@0 178 const browserWindows = Trait.resolve({ toString: null }).compose(
michael@0 179 List.resolve({ constructor: '_initList' }),
michael@0 180 EventEmitter.resolve({ toString: null }),
michael@0 181 WindowTrackerTrait.resolve({ constructor: '_initTracker', toString: null }),
michael@0 182 Trait.compose({
michael@0 183 _emit: Trait.required,
michael@0 184 _add: Trait.required,
michael@0 185 _remove: Trait.required,
michael@0 186
michael@0 187 // public API
michael@0 188
michael@0 189 /**
michael@0 190 * Constructor creates instance of `Windows` that represents live list of open
michael@0 191 * windows.
michael@0 192 */
michael@0 193 constructor: function BrowserWindows() {
michael@0 194 browser(this._public).internals = this;
michael@0 195
michael@0 196 this._trackedWindows = [];
michael@0 197 this._initList();
michael@0 198 this._initTracker();
michael@0 199 unload.ensure(this, "_destructor");
michael@0 200 },
michael@0 201 _destructor: function _destructor() {
michael@0 202 this._removeAllListeners('open');
michael@0 203 this._removeAllListeners('close');
michael@0 204 this._removeAllListeners('activate');
michael@0 205 this._removeAllListeners('deactivate');
michael@0 206 this._clear();
michael@0 207
michael@0 208 delete browser(this._public).internals;
michael@0 209 },
michael@0 210 /**
michael@0 211 * This property represents currently active window.
michael@0 212 * Property is non-enumerable, in order to preserve array like enumeration.
michael@0 213 * @type {Window|null}
michael@0 214 */
michael@0 215 get activeWindow() {
michael@0 216 let window = windowUtils.activeBrowserWindow;
michael@0 217 // Bug 834961: ignore private windows when they are not supported
michael@0 218 if (ignoreWindow(window))
michael@0 219 window = windowIterator()[0];
michael@0 220 return window ? BrowserWindow({window: window}) : null;
michael@0 221 },
michael@0 222 open: function open(options) {
michael@0 223 if (typeof options === "string") {
michael@0 224 // `tabs` option is under review and may be removed.
michael@0 225 options = {
michael@0 226 tabs: [Options(options)],
michael@0 227 isPrivate: isPrivateBrowsingSupported && options.isPrivate
michael@0 228 };
michael@0 229 }
michael@0 230 return BrowserWindow(options);
michael@0 231 },
michael@0 232
michael@0 233 /**
michael@0 234 * Internal listener which is called whenever new window gets open.
michael@0 235 * Creates wrapper and adds to this list.
michael@0 236 * @param {nsIWindow} chromeWindow
michael@0 237 */
michael@0 238 _onTrack: function _onTrack(chromeWindow) {
michael@0 239 if (!isBrowser(chromeWindow)) return;
michael@0 240 let window = BrowserWindow({ window: chromeWindow });
michael@0 241 this._add(window);
michael@0 242 this._emit('open', window);
michael@0 243 },
michael@0 244
michael@0 245 /**
michael@0 246 * Internal listener which is called whenever window gets closed.
michael@0 247 * Cleans up references and removes wrapper from this list.
michael@0 248 * @param {nsIWindow} window
michael@0 249 */
michael@0 250 _onUntrack: function _onUntrack(chromeWindow) {
michael@0 251 if (!isBrowser(chromeWindow)) return;
michael@0 252 let window = BrowserWindow({ window: chromeWindow });
michael@0 253 this._remove(window);
michael@0 254 this._emit('close', window);
michael@0 255
michael@0 256 // Bug 724404: do not leak this module and linked windows:
michael@0 257 // We have to do it on untrack and not only when `_onUnload` is called
michael@0 258 // when windows are closed, otherwise, we will leak on addon disabling.
michael@0 259 window.destroy();
michael@0 260 }
michael@0 261 }).resolve({ toString: null })
michael@0 262 )();
michael@0 263
michael@0 264 function getChromeWindow(window) {
michael@0 265 return windowNS(window).window;
michael@0 266 }
michael@0 267
michael@0 268 exports.browserWindows = browserWindows;

mercurial