OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @param {!Object.<string, string>} stringData String data. | 6 * Configuration of the Gallery window. |
7 * @param {!VolumeManager} volumeManager Volume manager. | 7 * @type {Object} |
8 * @constructor | |
9 * @struct | |
10 */ | 8 */ |
11 function BackgroundComponents(stringData, volumeManager) { | 9 var windowCreateOptions = { |
12 /** | 10 id: 'gallery', |
13 * String data. | 11 innerBounds: { |
14 * @type {!Object.<string, string>} | 12 minWidth: 820, |
15 */ | 13 minHeight: 554 |
16 this.stringData = stringData; | 14 }, |
17 | 15 frame: 'none' |
18 /** | |
19 * Volume manager. | |
20 * @type {!VolumeManager} | |
21 */ | |
22 this.volumeManager = volumeManager; | |
23 } | |
24 | |
25 /** | |
26 * Loads background component. | |
27 * @return {!Promise} Promise fulfilled with BackgroundComponents. | |
28 */ | |
29 BackgroundComponents.load = function() { | |
30 var stringDataPromise = new Promise(function(fulfill) { | |
31 chrome.fileManagerPrivate.getStrings(function(stringData) { | |
32 loadTimeData.data = stringData; | |
33 fulfill(stringData); | |
34 }); | |
35 }); | |
36 | |
37 // VolumeManager should be obtained after stringData initialized. | |
38 var volumeManagerPromise = stringDataPromise.then(function() { | |
39 return new Promise(function(fulfill) { | |
40 VolumeManager.getInstance(fulfill); | |
41 }); | |
42 }); | |
43 | |
44 return Promise.all([stringDataPromise, volumeManagerPromise]).then( | |
45 function(args) { | |
46 return new BackgroundComponents(args[0], args[1]); | |
47 }); | |
48 }; | 16 }; |
49 | 17 |
50 /** | 18 /** |
51 * Resolves file system names and obtains entries. | 19 * Backgound object. This is necessary for AppWindowWrapper. |
52 * @param {!Array.<!FileEntry>} entries Names of isolated file system. | 20 * @type {BackgroundBase} |
53 * @return {!Promise} Promise to be fulfilled with an entry array. | |
54 */ | 21 */ |
55 function resolveEntries(entries) { | 22 var background = new BackgroundBase(); |
56 return new Promise(function(fulfill, reject) { | 23 |
24 | |
25 // Initializes the strings. This needs for the volume manager. | |
26 var loadTimeDataPromise = new Promise(function(fulfill, reject) { | |
27 chrome.fileManagerPrivate.getStrings(function(stringData) { | |
28 loadTimeData.data = stringData; | |
29 fulfill(); | |
30 }); | |
31 }); | |
32 | |
33 // Initializes the volume manager. This needs for isolated entries. | |
34 var volumeManagerPromise = new Promise(function(fulfill, reject) { | |
35 VolumeManager.getInstance(fulfill); | |
36 }); | |
37 | |
38 /** | |
39 * Queue to serialize initialization. | |
40 * @type {AsyncUtil.Queue} | |
fukino
2015/02/16 04:16:38
nit: This annotation looks incorrect.
yoshiki
2015/02/16 07:35:55
Done.
yoshiki
2015/02/16 07:35:55
Done.
| |
41 */ | |
42 window.initializePromise = Promise.all([loadTimeDataPromise, | |
43 volumeManagerPromise]); | |
44 | |
45 // Registers the handlers. | |
46 chrome.app.runtime.onLaunched.addListener(onLaunched); | |
47 | |
48 /** | |
49 * Called when an app is launched. | |
50 * @param {Object} launchData Launch data. | |
51 */ | |
52 function onLaunched(launchData) { | |
fukino
2015/02/16 04:16:38
nit: Could you move inline comments from the previ
yoshiki
2015/02/16 07:35:55
Done.
| |
53 if (!launchData || !launchData.items || launchData.items.length == 0) | |
54 return; | |
55 | |
56 initializePromise.then(function() { | |
57 var isolatedEntries = launchData.items.map(function(item) { | |
58 return item.entry; | |
59 }); | |
60 | |
57 chrome.fileManagerPrivate.resolveIsolatedEntries( | 61 chrome.fileManagerPrivate.resolveIsolatedEntries( |
58 entries, function(externalEntries) { | 62 isolatedEntries, |
59 if (!chrome.runtime.lastError) | 63 function(externalEntries) { |
60 fulfill(externalEntries); | 64 var urls = util.entriesToURLs(externalEntries); |
61 else | 65 openGalleryWindow(urls, false); |
62 reject(chrome.runtime.lastError); | |
63 }); | 66 }); |
64 }); | 67 }); |
65 } | 68 } |
66 | 69 |
67 /** | 70 /** |
68 * Promise to be fulfilled with singleton instance of background components. | 71 * Returns a function to generate an ID for window. |
69 * @type {Promise} | 72 * @return {function():string} Function which returns an unique id. |
70 */ | 73 */ |
71 var backgroundComponentsPromise = null; | 74 var generateWindowId = (function() { |
75 var seq = 0; | |
76 return function() { | |
77 return 'GALLERY_' + seq++; | |
78 }; | |
79 })(); | |
72 | 80 |
73 /** | 81 /** |
74 * Promise to be fulfilled with single application window. | 82 * Opens gallery window. |
75 * This can be null when the window is not opened. | 83 * @param {Array.<string>} urls List of URL to show. |
76 * @type {Promise} | 84 * @param {boolean} reopen True if reopen, false otherwise. |
85 * @return {Promise} Promise to be fulfilled on success, or rejected on error. | |
77 */ | 86 */ |
78 var appWindowPromise = null; | 87 function openGalleryWindow(urls, reopen) { |
88 return new Promise(function(fulfill, reject) { | |
89 util.URLsToEntries(urls).then(function(result) { | |
90 fulfill(util.entriesToURLs(result.entries)); | |
91 }).catch(reject); | |
92 }).then(function(urls) { | |
93 if (urls.length === 0) | |
94 return Promise.reject('No file to open.'); | |
79 | 95 |
80 /** | 96 var windowId = generateWindowId(); |
81 * Promise to be fulfilled with entries that are used for reopening the | |
82 * application window. | |
83 * @type {Promise} | |
84 */ | |
85 var reopenEntriesPromise = null; | |
86 | 97 |
87 /** | 98 // Opens a window. |
88 * Launches the application with entries. | 99 return new Promise(function(fulfill, reject) { |
89 * | 100 var gallery = new AppWindowWrapper('gallery.html', |
90 * @param {!Promise} selectedEntriesPromise Promise to be fulfilled with the | 101 windowId, |
91 * entries that are stored in the external file system (not in the isolated | 102 windowCreateOptions); |
92 * file system). | 103 |
93 * @return {!Promise} Promise to be fulfilled after the application is launched. | 104 gallery.launch( |
94 */ | 105 {urls: urls}, |
95 function launch(selectedEntriesPromise) { | 106 reopen, |
96 // If there is the previous window, close the window. | 107 fulfill.bind(null, gallery)); |
97 if (appWindowPromise) { | 108 }).then(function(gallery) { |
98 reopenEntriesPromise = selectedEntriesPromise; | 109 var galleryDocument = gallery.rawAppWindow.contentWindow.document; |
99 appWindowPromise.then(function(appWindow) { | 110 if (galleryDocument.readyState == 'complete') |
100 appWindow.close(); | 111 return gallery; |
112 | |
113 return new Promise(function(fulfill, reject) { | |
114 galleryDocument.addEventListener( | |
115 'DOMContentLoaded', fulfill.bind(null, gallery)); | |
116 }); | |
101 }); | 117 }); |
102 return Promise.reject('The window has already opened.'); | 118 }).then(function(gallery) { |
103 } | 119 gallery.rawAppWindow.focus(); |
104 reopenEntriesPromise = null; | 120 return gallery.rawAppWindow; |
105 | 121 }).catch(function(error) { |
106 // Create a new window. | 122 console.error('Launch failed' + error.stack || error); |
107 appWindowPromise = new Promise(function(fulfill) { | 123 return Promise.reject(error); |
108 chrome.app.window.create( | |
109 'gallery.html', | |
110 { | |
111 id: 'gallery', | |
112 innerBounds: { | |
113 minWidth: 820, | |
114 minHeight: 544 | |
115 }, | |
116 frame: 'none' | |
117 }, | |
118 function(appWindow) { | |
119 appWindow.contentWindow.addEventListener( | |
120 'load', fulfill.bind(null, appWindow)); | |
121 appWindow.onClosed.addListener(function() { | |
122 appWindowPromise = null; | |
123 if (reopenEntriesPromise) { | |
124 // TODO(hirono): This is workaround for crbug.com/442217. Remove | |
125 // this after fixing it. | |
126 setTimeout(function() { | |
127 if (reopenEntriesPromise) | |
128 launch(reopenEntriesPromise); | |
129 }, 500); | |
130 } | |
131 }); | |
132 }); | |
133 }); | |
134 | |
135 // Initialize the window document. | |
136 return Promise.all([ | |
137 appWindowPromise, | |
138 backgroundComponentsPromise | |
139 ]).then(function(args) { | |
140 var appWindow = /** @type {!chrome.app.window.AppWindow} */ (args[0]); | |
141 var galleryWindow = /** @type {!GalleryWindow} */ (appWindow.contentWindow); | |
142 galleryWindow.initialize(args[1]); | |
143 return selectedEntriesPromise.then(function(entries) { | |
144 galleryWindow.loadEntries(entries); | |
145 }); | |
146 }); | 124 }); |
147 } | 125 } |
148 | 126 |
149 // If the script is loaded from unit test, chrome.app.runtime is not defined. | |
150 // In this case, does not run the initialization code for the application. | |
151 if (chrome.app.runtime) { | |
152 backgroundComponentsPromise = BackgroundComponents.load(); | |
153 chrome.app.runtime.onLaunched.addListener(function(launchData) { | |
154 // Skip if files are not selected. | |
155 if (!launchData || !launchData.items || launchData.items.length === 0) | |
156 return; | |
157 | |
158 // Obtains entries in non-isolated file systems. | |
159 // The entries in launchData are stored in the isolated file system. | |
160 // We need to map the isolated entries to the normal entries to retrieve | |
161 // their parent directory. | |
162 var isolatedEntries = launchData.items.map(function(item) { | |
163 return item.entry; | |
164 }); | |
165 var selectedEntriesPromise = backgroundComponentsPromise.then(function() { | |
166 return resolveEntries(isolatedEntries); | |
167 }); | |
168 | |
169 launch(selectedEntriesPromise).catch(function(error) { | |
170 console.error(error.stack || error); | |
171 }); | |
172 }); | |
173 } | |
174 | |
175 // If is is run in the browser test, wait for the test resources are installed | 127 // If is is run in the browser test, wait for the test resources are installed |
176 // as a component extension, and then load the test resources. | 128 // as a component extension, and then load the test resources. |
177 if (chrome.test) { | 129 if (chrome.test) { |
178 // Sets a global flag that we are in tests, so other components are aware of | 130 // Sets a global flag that we are in tests, so other components are aware of |
179 // it. | 131 // it. |
180 window.IN_TEST = true; | 132 window.IN_TEST = true; |
181 | 133 |
182 /** @type {string} */ | 134 /** @type {string} */ |
183 window.testExtensionId = 'ejhcmmdhhpdhhgmifplfmjobgegbibkn'; | 135 window.testExtensionId = 'ejhcmmdhhpdhhgmifplfmjobgegbibkn'; |
184 chrome.runtime.onMessageExternal.addListener(function(message) { | 136 chrome.runtime.onMessageExternal.addListener(function(message) { |
185 if (message.name !== 'testResourceLoaded') | 137 if (message.name !== 'testResourceLoaded') |
186 return; | 138 return; |
187 var script = document.createElement('script'); | 139 var script = document.createElement('script'); |
188 script.src = | 140 script.src = |
189 'chrome-extension://' + window.testExtensionId + | 141 'chrome-extension://' + window.testExtensionId + |
190 '/gallery/test_loader.js'; | 142 '/gallery/test_loader.js'; |
191 document.documentElement.appendChild(script); | 143 document.documentElement.appendChild(script); |
192 }); | 144 }); |
193 } | 145 } |
OLD | NEW |