Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ui / file_manager / gallery / js / background.js
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
3 // found in the LICENSE file.
4
5 'use strict';
6
7 /**
8  * @param {Object.<string, string>} stringData String data.
9  * @param {VolumeManager} volumeManager Volume manager.
10  */
11 function BackgroundComponents(stringData, volumeManager) {
12   /**
13    * String data.
14    * @type {Object.<string, string>}
15    */
16   this.stringData = stringData;
17
18   /**
19    * Volume manager.
20    * @type {VolumeManager}
21    */
22   this.volumeManager = volumeManager;
23
24   Object.freeze(this);
25 }
26
27 /**
28  * Loads background component.
29  * @return {Promise} Promise fulfilled with BackgroundComponents.
30  */
31 BackgroundComponents.load = function() {
32   var stringDataPromise = new Promise(function(fulfill) {
33     chrome.fileBrowserPrivate.getStrings(function(stringData) {
34       loadTimeData.data = stringData;
35       fulfill(stringData);
36     });
37   });
38
39   // VolumeManager should be obtained after stringData initialized.
40   var volumeManagerPromise = stringDataPromise.then(function() {
41     return new Promise(function(fulfill) {
42       VolumeManager.getInstance(fulfill);
43     });
44   });
45
46   return Promise.all([stringDataPromise, volumeManagerPromise]).then(
47       function(args) {
48         return new BackgroundComponents(args[0], args[1]);
49       });
50 };
51
52 /**
53  * Promise to be fulfilled with singleton instance of background components.
54  * @type {Promise}
55  */
56 var backgroundComponentsPromise = BackgroundComponents.load();
57
58 /**
59  * Resolves file system names and obtains entries.
60  * @param {Array.<FileEntry>} entries Names of isolated file system.
61  * @return {Promise} Promise to be fulfilled with an entry array.
62  */
63 function resolveEntries(entries) {
64   return new Promise(function(fulfill, reject) {
65     chrome.fileBrowserPrivate.resolveIsolatedEntries(entries,
66                                                      function(externalEntries) {
67       if (!chrome.runtime.lastError)
68         fulfill(externalEntries);
69       else
70         reject(chrome.runtime.lastError);
71     });
72   });
73 }
74
75 /**
76  * Obtains child entries.
77  * @param {DirectoryEntry} entry Directory entry.
78  * @return {Promise} Promise to be fulfilled with child entries.
79  */
80 function getChildren(entry) {
81   var reader = entry.createReader();
82   var readEntries = function() {
83     return new Promise(reader.readEntries.bind(reader)).then(function(entries) {
84       if (entries.length === 0)
85         return [];
86       return readEntries().then(function(nextEntries) {
87         return entries.concat(nextEntries);
88       });
89     });
90   };
91   return readEntries().then(function(entries) {
92     return entries.sort(function(a, b) {
93       return a.name.localeCompare(b.name);
94     });
95   });
96 }
97
98 /**
99  * Promise to be fulfilled with single application window.
100  * This can be null when the window is not opened.
101  * @type {Promise}
102  */
103 var appWindowPromise = null;
104
105 /**
106  * Promise to be fulfilled with entries that are used for reopening the
107  * application window.
108  * @type {Promise}
109  */
110 var reopenEntriesPromsie = null;
111
112 /**
113  * Launches the application with entries.
114  *
115  * @param {Promise} selectedEntriesPromise Promise to be fulfilled with the
116  *     entries that are stored in the external file system (not in the isolated
117  *     file system).
118  * @return {Promise} Promise to be fulfilled after the application is launched.
119  */
120 function launch(selectedEntriesPromise) {
121   // If there is the previous window, close the window.
122   if (appWindowPromise) {
123     reopenEntriesPromsie = selectedEntriesPromise;
124     appWindowPromise.then(function(appWindow) {
125       appWindow.close();
126     });
127     return Promise.reject('The window has already opened.');
128   }
129   reopenEntriesPromsie = null;
130
131   // Create a new window.
132   appWindowPromise = new Promise(function(fulfill) {
133     chrome.app.window.create(
134         'gallery.html',
135         {
136           id: 'gallery',
137           innerBounds: {
138             minWidth: 820,
139             minHeight: 544
140           },
141           frame: 'none'
142         },
143         function(appWindow) {
144           appWindow.contentWindow.addEventListener(
145               'load', fulfill.bind(null, appWindow));
146           appWindow.onClosed.addListener(function() {
147             appWindowPromise = null;
148             if (reopenEntriesPromsie)
149               launch(reopenEntriesPromsie);
150           });
151         });
152   });
153
154   // If only 1 entry is selected, retrieve entries in the same directory.
155   // Otherwise, just use the selectedEntries as an entry set.
156   var allEntriesPromise = selectedEntriesPromise.then(function(entries) {
157     if (entries.length === 1) {
158       var parentPromise = new Promise(entries[0].getParent.bind(entries[0]));
159       return parentPromise.then(getChildren).then(function(entries) {
160         return entries.filter(FileType.isImage);
161       });
162     } else {
163       return entries;
164     }
165   });
166
167   // Initialize the window document.
168   return Promise.all([
169     appWindowPromise,
170     backgroundComponentsPromise,
171   ]).then(function(args) {
172     args[0].contentWindow.initialize(args[1]);
173     return Promise.all([
174       allEntriesPromise,
175       selectedEntriesPromise
176     ]).then(function(entries) {
177       args[0].contentWindow.loadEntries(entries[0], entries[1]);
178     });
179   });
180 }
181
182 chrome.app.runtime.onLaunched.addListener(function(launchData) {
183   // Skip if files are not selected.
184   if (!launchData || !launchData.items || launchData.items.length === 0)
185     return;
186
187   // Obtains entries in non-isolated file systems.
188   // The entries in launchData are stored in the isolated file system.
189   // We need to map the isolated entries to the normal entries to retrieve their
190   // parent directory.
191   var isolatedEntries = launchData.items.map(function(item) {
192     return item.entry;
193   });
194   var selectedEntriesPromise = backgroundComponentsPromise.then(function() {
195     return resolveEntries(isolatedEntries);
196   });
197
198   launch(selectedEntriesPromise).catch(function(error) {
199     console.error(error.stack || error);
200   });
201 });
202
203 // If is is run in the browser test, wait for the test resources are installed
204 // as a component extension, and then load the test resources.
205 if (chrome.test) {
206   chrome.runtime.onMessageExternal.addListener(function(message) {
207     if (message.name !== 'testResourceLoaded')
208       return;
209     var script = document.createElement('script');
210     script.src =
211         'chrome-extension://ejhcmmdhhpdhhgmifplfmjobgegbibkn' +
212         '/gallery/test_loader.js';
213     document.documentElement.appendChild(script);
214   });
215 }