Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: ui/file_manager/file_manager/foreground/js/import_controller.js

Issue 792233009: Reflect scanning status in command UI. Only allow import once scanning is complete. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix FM.jstests.cc && Finalize scan results in MediaImportHandlerTest...unbreaking the test. Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 // Namespace
6 var importer = importer || {};
7
8 /**
9 * @typedef {{
10 * label_id: string,
11 * visible: boolean,
12 * executable: boolean
13 * }}
14 */
15 importer.UpdateResponse;
16
17 /** @enum {importer.UpdateResponse} */
18 importer.UpdateResponses = {
19 HIDDEN: {
20 label_id: 'CLOUD_IMPORT_BUTTON_LABEL',
21 visible: false,
22 executable: false
23 },
24 SCANNING: {
25 label_id: 'CLOUD_IMPORT_SCANNING_BUTTON_LABEL',
26 visible: true,
27 executable: false
28 },
29 EXECUTABLE: {
30 label_id: 'CLOUD_IMPORT_BUTTON_LABEL',
31 visible: true,
32 executable: true
33 }
34 };
35
36 /**
37 * Class that orchestrates background activity and UI changes on
38 * behalf of Cloud Import.
39 *
40 * @constructor
41 * @struct
42 *
43 * @param {!importer.ControllerEnvironment} environment The class providing
44 * access to runtime environmental information, like the current directory,
45 * volume lookup and so-on.
46 * @param {!importer.MediaScanner} scanner
47 * @param {!importer.ImportRunner} importRunner
48 * @param {function()} commandUpdateHandler
49 */
50 importer.ImportController =
51 function(environment, scanner, importRunner, commandUpdateHandler) {
52
53 /** @private {!importer.ControllerEnvironment} */
54 this.environment_ = environment;
55
56 /** @private {!importer.ImportRunner} */
57 this.importRunner_ = importRunner;
58
59 /** @private {!importer.MediaScanner} */
60 this.scanner_ = scanner;
61
62 /** @private {function()} */
63 this.updateCommands_ = commandUpdateHandler;
64
65 /** @private {!importer.ScanObserver} */
66 this.scanObserverBound_ = this.onScanEvent_.bind(this);
67
68 this.scanner_.addObserver(this.scanObserverBound_);
69
70 /** @private {!Object.<string, !importer.ScanResult>} */
71 this.directoryScans_ = {};
72 };
73
74 /**
75 * @param {!importer.ScanEvent} event Command event.
76 * @param {importer.ScanResult} result
77 */
78 importer.ImportController.prototype.onScanEvent_ = function(event, result) {
79 // TODO(smckay): only do this if this is a directory scan.
80 if (event === importer.ScanEvent.FINALIZED) {
81 this.updateCommands_();
82 }
83 };
84
85 /**
86 * Executes import against the current directory. Should only
87 * be called when the current directory has been validated
88 * by calling "update" on this class.
89 */
90 importer.ImportController.prototype.execute = function() {
91 metrics.recordEnum('CloudImport.UserAction', 'IMPORT_INITIATED');
92 var result = this.getScanForImport_();
93 this.importRunner_.importFromScanResult(result);
94 };
95
96 /**
97 * @return {!importer.UpdateResponse} response
98 */
99 importer.ImportController.prototype.update = function() {
100
101 // If there is no Google Drive mount, Drive may be disabled
102 // or the machine may be running in guest mode.
103 if (!this.environment_.isGoogleDriveMounted()) {
104 return importer.UpdateResponses.HIDDEN;
105 }
106
107 var entries = this.environment_.getSelection();
108
109 // Enabled if user has a selection and it consists entirely of files
110 // that:
111 // 1) are of a recognized media type
112 // 2) reside on a removable media device
113 // 3) in the DCIM dir
114 if (entries.length) {
115 if (entries.every(
116 importer.isEligibleEntry.bind(null, this.environment_))) {
117 // TODO(smckay): Include entry count in label.
118 return importer.UpdateResponses.EXECUTABLE;
119 }
120 } else if (this.isCurrentDirectoryScannable_()) {
121 var scan = this.getCurrentDirectoryScan_();
122 return scan.isFinal() ?
123 importer.UpdateResponses.EXECUTABLE :
124 importer.UpdateResponses.SCANNING;
125 }
126
127 return importer.UpdateResponses.HIDDEN;
128 };
129
130 /**
131 * @return {boolean} true if the current directory is scan eligible.
132 * @private
133 */
134 importer.ImportController.prototype.isCurrentDirectoryScannable_ =
135 function() {
136 var directory = this.environment_.getCurrentDirectory();
137 return !!directory &&
138 importer.isMediaDirectory(directory, this.environment_);
139 };
140
141 /**
142 * Get or create scan for the current directory or file selection.
143 *
144 * @return {!importer.ScanResult} A scan result object that may be
145 * actively scanning.
146 * @private
147 */
148 importer.ImportController.prototype.getScanForImport_ = function() {
149 var entries = this.environment_.getSelection();
150
151 if (entries.length) {
152 if (entries.every(
153 importer.isEligibleEntry.bind(null, this.environment_))) {
154 return this.scanner_.scan(entries);
155 }
156 } else {
157 return this.getCurrentDirectoryScan_();
158 }
159 };
160
161 /**
162 * Get or create scan for the current directory.
163 *
164 * @return {!importer.ScanResult} A scan result object that may be
165 * actively scanning.
166 * @private
167 */
168 importer.ImportController.prototype.getCurrentDirectoryScan_ = function() {
169 console.assert(this.isCurrentDirectoryScannable_());
170 var directory = this.environment_.getCurrentDirectory();
171 var url = directory.toURL();
172 var scan = this.directoryScans_[url];
173 if (!scan) {
174 scan = this.scanner_.scan([directory]);
175 // TODO(smckay): evict scans when a device is unmounted or changed.
176 this.directoryScans_[url] = scan;
177 }
178 return scan;
179 };
180
181 /**
182 * Interface abstracting away the concrete file manager available
183 * to commands. By hiding file manager we make it easy to test
184 * ImportController.
185 *
186 * @interface
187 * @extends {VolumeManagerCommon.VolumeInfoProvider}
188 */
189 importer.ControllerEnvironment = function() {};
190
191 /**
192 * Returns the current file selection, if any. May be empty.
193 * @return {!Array.<!Entry>}
194 */
195 importer.ControllerEnvironment.prototype.getSelection;
196
197 /**
198 * Returns the directory entry for the current directory.
199 * @return {!DirectoryEntry}
200 */
201 importer.ControllerEnvironment.prototype.getCurrentDirectory;
202
203 /**
204 * Returns true if the Drive mount is present.
205 * @return {boolean}
206 */
207 importer.ControllerEnvironment.prototype.isGoogleDriveMounted;
208
209
210 /**
211 * Class providing access to various pieces of information in the
212 * FileManager environment, like the current directory, volumeinfo lookup
213 * By hiding file manager we make it easy to test importer.ImportController.
214 *
215 * @constructor
216 * @implements {importer.ControllerEnvironment}
217 *
218 * @param {!FileManager} fileManager
219 */
220 importer.RuntimeControllerEnvironment = function(fileManager) {
221 /** @private {!FileManager} */
222 this.fileManager_ = fileManager;
223 };
224
225 /** @override */
226 importer.RuntimeControllerEnvironment.prototype.getSelection =
227 function() {
228 return this.fileManager_.getSelection().entries;
229 };
230
231 /** @override */
232 importer.RuntimeControllerEnvironment.prototype.getCurrentDirectory =
233 function() {
234 return /** @type {!DirectoryEntry} */ (
235 this.fileManager_.getCurrentDirectoryEntry());
236 };
237
238 /** @override */
239 importer.RuntimeControllerEnvironment.prototype.getVolumeInfo =
240 function(entry) {
241 return this.fileManager_.volumeManager.getVolumeInfo(entry);
242 };
243
244 /** @override */
245 importer.RuntimeControllerEnvironment.prototype.isGoogleDriveMounted =
246 function() {
247 var drive = this.fileManager_.volumeManager.getCurrentProfileVolumeInfo(
248 VolumeManagerCommon.VolumeType.DRIVE);
249 return !!drive;
250 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698