|
1 /* vim:set ts=2 sw=2 sts=2 et tw=80: |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 "use strict"; |
|
7 |
|
8 this.EXPORTED_SYMBOLS = ["ScratchpadManager"]; |
|
9 |
|
10 const Cc = Components.classes; |
|
11 const Ci = Components.interfaces; |
|
12 const Cu = Components.utils; |
|
13 |
|
14 const SCRATCHPAD_WINDOW_URL = "chrome://browser/content/devtools/scratchpad.xul"; |
|
15 const SCRATCHPAD_WINDOW_FEATURES = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no"; |
|
16 |
|
17 Cu.import("resource://gre/modules/Services.jsm"); |
|
18 |
|
19 /** |
|
20 * The ScratchpadManager object opens new Scratchpad windows and manages the state |
|
21 * of open scratchpads for session restore. There's only one ScratchpadManager in |
|
22 * the life of the browser. |
|
23 */ |
|
24 this.ScratchpadManager = { |
|
25 |
|
26 _nextUid: 1, |
|
27 _scratchpads: [], |
|
28 |
|
29 /** |
|
30 * Get the saved states of open scratchpad windows. Called by |
|
31 * session restore. |
|
32 * |
|
33 * @return array |
|
34 * The array of scratchpad states. |
|
35 */ |
|
36 getSessionState: function SPM_getSessionState() |
|
37 { |
|
38 return this._scratchpads; |
|
39 }, |
|
40 |
|
41 /** |
|
42 * Restore scratchpad windows from the scratchpad session store file. |
|
43 * Called by session restore. |
|
44 * |
|
45 * @param function aSession |
|
46 * The session object with scratchpad states. |
|
47 * |
|
48 * @return array |
|
49 * The restored scratchpad windows. |
|
50 */ |
|
51 restoreSession: function SPM_restoreSession(aSession) |
|
52 { |
|
53 if (!Array.isArray(aSession)) { |
|
54 return []; |
|
55 } |
|
56 |
|
57 let wins = []; |
|
58 aSession.forEach(function(state) { |
|
59 let win = this.openScratchpad(state); |
|
60 wins.push(win); |
|
61 }, this); |
|
62 |
|
63 return wins; |
|
64 }, |
|
65 |
|
66 /** |
|
67 * Iterate through open scratchpad windows and save their states. |
|
68 */ |
|
69 saveOpenWindows: function SPM_saveOpenWindows() { |
|
70 this._scratchpads = []; |
|
71 |
|
72 function clone(src) { |
|
73 let dest = {}; |
|
74 |
|
75 for (let key in src) { |
|
76 if (src.hasOwnProperty(key)) { |
|
77 dest[key] = src[key]; |
|
78 } |
|
79 } |
|
80 |
|
81 return dest; |
|
82 } |
|
83 |
|
84 // We need to clone objects we get from Scratchpad instances |
|
85 // because such (cross-window) objects have a property 'parent' |
|
86 // that holds on to a ChromeWindow instance. This means that |
|
87 // such objects are not primitive-values-only anymore so they |
|
88 // can leak. |
|
89 |
|
90 let enumerator = Services.wm.getEnumerator("devtools:scratchpad"); |
|
91 while (enumerator.hasMoreElements()) { |
|
92 let win = enumerator.getNext(); |
|
93 if (!win.closed && win.Scratchpad.initialized) { |
|
94 this._scratchpads.push(clone(win.Scratchpad.getState())); |
|
95 } |
|
96 } |
|
97 }, |
|
98 |
|
99 /** |
|
100 * Open a new scratchpad window with an optional initial state. |
|
101 * |
|
102 * @param object aState |
|
103 * Optional. The initial state of the scratchpad, an object |
|
104 * with properties filename, text, and executionContext. |
|
105 * |
|
106 * @return nsIDomWindow |
|
107 * The opened scratchpad window. |
|
108 */ |
|
109 openScratchpad: function SPM_openScratchpad(aState) |
|
110 { |
|
111 let params = Cc["@mozilla.org/embedcomp/dialogparam;1"] |
|
112 .createInstance(Ci.nsIDialogParamBlock); |
|
113 |
|
114 params.SetNumberStrings(2); |
|
115 params.SetString(0, this.createUid()); |
|
116 |
|
117 if (aState) { |
|
118 if (typeof aState != 'object') { |
|
119 return; |
|
120 } |
|
121 |
|
122 params.SetString(1, JSON.stringify(aState)); |
|
123 } |
|
124 |
|
125 let win = Services.ww.openWindow(null, SCRATCHPAD_WINDOW_URL, "_blank", |
|
126 SCRATCHPAD_WINDOW_FEATURES, params); |
|
127 |
|
128 // Only add the shutdown observer if we've opened a scratchpad window. |
|
129 ShutdownObserver.init(); |
|
130 |
|
131 return win; |
|
132 }, |
|
133 |
|
134 /** |
|
135 * Create a unique ID for a new Scratchpad. |
|
136 */ |
|
137 createUid: function SPM_createUid() |
|
138 { |
|
139 return JSON.stringify(this._nextUid++); |
|
140 } |
|
141 }; |
|
142 |
|
143 |
|
144 /** |
|
145 * The ShutdownObserver listens for app shutdown and saves the current state |
|
146 * of the scratchpads for session restore. |
|
147 */ |
|
148 var ShutdownObserver = { |
|
149 _initialized: false, |
|
150 |
|
151 init: function SDO_init() |
|
152 { |
|
153 if (this._initialized) { |
|
154 return; |
|
155 } |
|
156 |
|
157 Services.obs.addObserver(this, "quit-application-granted", false); |
|
158 |
|
159 this._initialized = true; |
|
160 }, |
|
161 |
|
162 observe: function SDO_observe(aMessage, aTopic, aData) |
|
163 { |
|
164 if (aTopic == "quit-application-granted") { |
|
165 ScratchpadManager.saveOpenWindows(); |
|
166 this.uninit(); |
|
167 } |
|
168 }, |
|
169 |
|
170 uninit: function SDO_uninit() |
|
171 { |
|
172 Services.obs.removeObserver(this, "quit-application-granted"); |
|
173 } |
|
174 }; |