Fix crash on key events in touchview.
[chromium-blink-merge.git] / ui / file_manager / gallery / js / background.js
blob61ea019d2f1723588bc96580eeea76886ec7484a
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.
5 'use strict';
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;
18   /**
19    * Volume manager.
20    * @type {VolumeManager}
21    */
22   this.volumeManager = volumeManager;
24   Object.freeze(this);
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   });
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   });
46   return Promise.all([stringDataPromise, volumeManagerPromise]).then(
47       function(args) {
48         return new BackgroundComponents(args[0], args[1]);
49       });
52 /**
53  * Promise to be fulfilled with singleton instance of background components.
54  * @type {Promise}
55  */
56 var backgroundComponentsPromise = BackgroundComponents.load();
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   });
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();
94 /**
95  * Promise to be fulfilled with single application window.
96  * @param {AppWindow}
97  */
98 var appWindowPromise = null;
100 chrome.app.runtime.onLaunched.addListener(function(launchData) {
101   // Skip if files are not selected.
102   if (!launchData || !launchData.items || launchData.items.length == 0)
103     return;
105   // Obtains entries in non-isolated file systems.
106   // The entries in launchData are stored in the isolated file system.
107   // We need to map the isolated entries to the normal entries to retrieve their
108   // parent directory.
109   var isolatedEntries = launchData.items.map(function(item) {
110     return item.entry;
111   });
112   var selectedEntriesPromise = backgroundComponentsPromise.then(function() {
113     return resolveEntries(isolatedEntries);
114   });
116   // If only 1 entry is selected, retrieve entries in the same directory.
117   // Otherwise, just use the selectedEntries as an entry set.
118   var allEntriesPromise = selectedEntriesPromise.then(function(entries) {
119     if (entries.length === 1) {
120       var parent = new Promise(entries[0].getParent.bind(entries[0]));
121       return parent.then(getChildren).then(function(entries) {
122         return entries.filter(FileType.isImageOrVideo);
123       });
124     } else {
125       return entries;
126     }
127   });
129   // Store the selected and all entries to the launchData.
130   launchData.entriesPromise = Promise.all([selectedEntriesPromise,
131                                            allEntriesPromise]).then(
132       function(args) {
133         return Object.freeze({
134           selectedEntries: args[0],
135           allEntries: args[1]
136         });
137       });
139   // Close previous window.
140   var closePromise;
141   if (appWindowPromise) {
142     closePromise = appWindowPromise.then(function(appWindow) {
143       return new Promise(function(fulfill) {
144         appWindow.close();
145         appWindow.onClosed.addListener(fulfill);
146       });
147     });
148   } else {
149     closePromise = Promise.resolve();
150   }
151   var createdWindowPromise = closePromise.then(function() {
152     return new Promise(function(fulfill) {
153       chrome.app.window.create(
154           'gallery.html',
155           {
156             id: 'gallery',
157             minWidth: 160,
158             minHeight: 100,
159             frame: 'none'
160           },
161           function(appWindow) {
162             appWindow.contentWindow.addEventListener(
163                 'load', fulfill.bind(null, appWindow));
164           });
165     });
166   });
167   appWindowPromise = Promise.all([
168     createdWindowPromise,
169     backgroundComponentsPromise,
170   ]).then(function(args) {
171     args[0].contentWindow.initialize(args[1]);
172     return args[0];
173   });
175   // Open entries.
176   Promise.all([
177     appWindowPromise,
178     allEntriesPromise,
179     selectedEntriesPromise
180   ]).then(function(args) {
181     args[0].contentWindow.loadEntries(args[1], args[2]);
182   }).catch(function(error) {
183     console.error(error.stack || error);
184   });