1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/lib/sdk/windows/loader.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,126 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +'use strict'; 1.8 + 1.9 +module.metadata = { 1.10 + "stability": "unstable" 1.11 +}; 1.12 + 1.13 +const { Cc, Ci } = require('chrome'), 1.14 + { setTimeout } = require('../timers'), 1.15 + { Trait } = require('../deprecated/traits'), 1.16 + { openDialog } = require('../window/utils'), 1.17 + 1.18 + ON_LOAD = 'load', 1.19 + ON_UNLOAD = 'unload', 1.20 + STATE_LOADED = 'complete'; 1.21 + 1.22 +/** 1.23 + * Trait provides private `_window` property and requires `_onLoad` property 1.24 + * that will be called when `_window` is loaded. If `_window` property value 1.25 + * is changed with already loaded window `_onLoad` still will be called. 1.26 + */ 1.27 +const WindowLoader = Trait.compose({ 1.28 + /** 1.29 + * Internal listener that is called when window is loaded. 1.30 + * Please keep in mind that this trait will not handle exceptions that may 1.31 + * be thrown by this method so method itself should take care of 1.32 + * handling them. 1.33 + * @param {nsIWindow} window 1.34 + */ 1.35 + _onLoad: Trait.required, 1.36 + _tabOptions: Trait.required, 1.37 + /** 1.38 + * Internal listener that is called when `_window`'s DOM 'unload' event 1.39 + * is dispatched. Please note that this trait will not handle exceptions that 1.40 + * may be thrown by this method so method itself should take care of 1.41 + * handling them. 1.42 + */ 1.43 + _onUnload: Trait.required, 1.44 + _load: function _load() { 1.45 + if (this.__window) 1.46 + return; 1.47 + 1.48 + this._window = openDialog({ 1.49 + private: this._isPrivate, 1.50 + args: this._tabOptions.map(function(options) options.url).join("|") 1.51 + }); 1.52 + }, 1.53 + /** 1.54 + * Private window who's load event is being tracked. Once window is loaded 1.55 + * `_onLoad` is called. 1.56 + * @type {nsIWindow} 1.57 + */ 1.58 + get _window() this.__window, 1.59 + set _window(window) { 1.60 + let _window = this.__window; 1.61 + if (!window) window = null; 1.62 + 1.63 + if (window !== _window) { 1.64 + if (_window) { 1.65 + _window.removeEventListener(ON_UNLOAD, this.__unloadListener, false); 1.66 + _window.removeEventListener(ON_LOAD, this.__loadListener, false); 1.67 + } 1.68 + 1.69 + if (window) { 1.70 + window.addEventListener( 1.71 + ON_UNLOAD, 1.72 + this.__unloadListener || 1.73 + (this.__unloadListener = this._unloadListener.bind(this)) 1.74 + , 1.75 + false 1.76 + ); 1.77 + 1.78 + this.__window = window; 1.79 + 1.80 + // If window is not loaded yet setting up a listener. 1.81 + if (STATE_LOADED != window.document.readyState) { 1.82 + window.addEventListener( 1.83 + ON_LOAD, 1.84 + this.__loadListener || 1.85 + (this.__loadListener = this._loadListener.bind(this)) 1.86 + , 1.87 + false 1.88 + ); 1.89 + } 1.90 + else { // If window is loaded calling listener next turn of event loop. 1.91 + this._onLoad(window) 1.92 + } 1.93 + } 1.94 + else { 1.95 + this.__window = null; 1.96 + } 1.97 + } 1.98 + }, 1.99 + __window: null, 1.100 + /** 1.101 + * Internal method used for listening 'load' event on the `_window`. 1.102 + * Method takes care of removing itself from 'load' event listeners once 1.103 + * event is being handled. 1.104 + */ 1.105 + _loadListener: function _loadListener(event) { 1.106 + let window = this._window; 1.107 + if (!event.target || event.target.defaultView != window) return; 1.108 + window.removeEventListener(ON_LOAD, this.__loadListener, false); 1.109 + this._onLoad(window); 1.110 + }, 1.111 + __loadListener: null, 1.112 + /** 1.113 + * Internal method used for listening 'unload' event on the `_window`. 1.114 + * Method takes care of removing itself from 'unload' event listeners once 1.115 + * event is being handled. 1.116 + */ 1.117 + _unloadListener: function _unloadListener(event) { 1.118 + let window = this._window; 1.119 + if (!event.target 1.120 + || event.target.defaultView != window 1.121 + || STATE_LOADED != window.document.readyState 1.122 + ) return; 1.123 + window.removeEventListener(ON_UNLOAD, this.__unloadListener, false); 1.124 + this._onUnload(window); 1.125 + }, 1.126 + __unloadListener: null 1.127 +}); 1.128 +exports.WindowLoader = WindowLoader; 1.129 +