OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 * Represents each volume, such as "drive", "download directory", each "USB | 6 * Represents each volume, such as "drive", "download directory", each "USB |
7 * flush storage", or "mounted zip archive" etc. | 7 * flush storage", or "mounted zip archive" etc. |
8 * | 8 * |
9 * @constructor | 9 * @constructor |
10 * @struct | 10 * @struct |
11 * | 11 * |
12 * @param {VolumeManagerCommon.VolumeType} volumeType The type of the volume. | 12 * @param {VolumeManagerCommon.VolumeType} volumeType The type of the volume. |
13 * @param {string} volumeId ID of the volume. | 13 * @param {string} volumeId ID of the volume. |
14 * @param {FileSystem} fileSystem The file system object for this volume. | 14 * @param {FileSystem} fileSystem The file system object for this volume. |
15 * @param {(string|undefined)} error The error if an error is found. | 15 * @param {(string|undefined)} error The error if an error is found. |
16 * @param {(string|undefined)} deviceType The type of device | 16 * @param {(string|undefined)} deviceType The type of device |
17 * ('usb'|'sd'|'optical'|'mobile'|'unknown') (as defined in | 17 * ('usb'|'sd'|'optical'|'mobile'|'unknown') (as defined in |
18 * chromeos/disks/disk_mount_manager.cc). Can be undefined. | 18 * chromeos/disks/disk_mount_manager.cc). Can be undefined. |
19 * @param {(string|undefined)} devicePath Identifier of the device that the | 19 * @param {(string|undefined)} devicePath Identifier of the device that the |
20 * volume belongs to. Can be undefined. | 20 * volume belongs to. Can be undefined. |
21 * @param {boolean} isReadOnly True if the volume is read only. | 21 * @param {boolean} isReadOnly True if the volume is read only. |
22 * @param {!{displayName:string, isCurrentProfile:boolean}} profile Profile | 22 * @param {!{displayName:string, isCurrentProfile:boolean}} profile Profile |
23 * information. | 23 * information. |
24 * @param {string} label Label of the volume. | 24 * @param {string} label Label of the volume. |
25 * @param {(string|undefined)} extensionId Id of the extension providing this | 25 * @param {(string|undefined)} extensionId Id of the extension providing this |
26 * volume. Empty for native volumes. | 26 * volume. Empty for native volumes. |
27 * @param {boolean} hasMedia When true the volume has been identified | 27 * @param {boolean} hasMedia When true the volume has been identified |
28 * as containing media such as photos or videos. | 28 * as containing media such as photos or videos. |
29 * @param {boolean} configurable When true, then the volume can be configured. | 29 * @param {boolean} configurable When true, then the volume can be configured. |
| 30 * @param {VolumeManagerCommon.Source} source Source of the volume's data. |
30 */ | 31 */ |
31 function VolumeInfo( | 32 function VolumeInfo( |
32 volumeType, | 33 volumeType, |
33 volumeId, | 34 volumeId, |
34 fileSystem, | 35 fileSystem, |
35 error, | 36 error, |
36 deviceType, | 37 deviceType, |
37 devicePath, | 38 devicePath, |
38 isReadOnly, | 39 isReadOnly, |
39 profile, | 40 profile, |
40 label, | 41 label, |
41 extensionId, | 42 extensionId, |
42 hasMedia, | 43 hasMedia, |
43 configurable) { | 44 configurable, |
| 45 source) { |
44 this.volumeType_ = volumeType; | 46 this.volumeType_ = volumeType; |
45 this.volumeId_ = volumeId; | 47 this.volumeId_ = volumeId; |
46 this.fileSystem_ = fileSystem; | 48 this.fileSystem_ = fileSystem; |
47 this.label_ = label; | 49 this.label_ = label; |
48 this.displayRoot_ = null; | 50 this.displayRoot_ = null; |
49 | 51 |
50 /** @type {Object.<string, !FakeEntry>} */ | 52 /** @type {Object.<string, !FakeEntry>} */ |
51 this.fakeEntries_ = {}; | 53 this.fakeEntries_ = {}; |
52 | 54 |
53 /** @type {Promise.<!DirectoryEntry>} */ | 55 /** @type {Promise.<!DirectoryEntry>} */ |
(...skipping 22 matching lines...) Expand all Loading... |
76 // or not. (If error is empty string, the mount is successfully done). | 78 // or not. (If error is empty string, the mount is successfully done). |
77 // TODO(hidehiko): Rename to make this more understandable. | 79 // TODO(hidehiko): Rename to make this more understandable. |
78 this.error_ = error; | 80 this.error_ = error; |
79 this.deviceType_ = deviceType; | 81 this.deviceType_ = deviceType; |
80 this.devicePath_ = devicePath; | 82 this.devicePath_ = devicePath; |
81 this.isReadOnly_ = isReadOnly; | 83 this.isReadOnly_ = isReadOnly; |
82 this.profile_ = Object.freeze(profile); | 84 this.profile_ = Object.freeze(profile); |
83 this.extensionId_ = extensionId; | 85 this.extensionId_ = extensionId; |
84 this.hasMedia_ = hasMedia; | 86 this.hasMedia_ = hasMedia; |
85 this.configurable_ = configurable; | 87 this.configurable_ = configurable; |
| 88 this.source_ = source; |
86 } | 89 } |
87 | 90 |
88 VolumeInfo.prototype = /** @struct */ { | 91 VolumeInfo.prototype = /** @struct */ { |
89 /** | 92 /** |
90 * @return {VolumeManagerCommon.VolumeType} Volume type. | 93 * @return {VolumeManagerCommon.VolumeType} Volume type. |
91 */ | 94 */ |
92 get volumeType() { | 95 get volumeType() { |
93 return this.volumeType_; | 96 return this.volumeType_; |
94 }, | 97 }, |
95 /** | 98 /** |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 * @return {boolean} True if the volume contains media. | 166 * @return {boolean} True if the volume contains media. |
164 */ | 167 */ |
165 get hasMedia() { | 168 get hasMedia() { |
166 return this.hasMedia_; | 169 return this.hasMedia_; |
167 }, | 170 }, |
168 /** | 171 /** |
169 * @return {boolean} True if the volume is configurable. | 172 * @return {boolean} True if the volume is configurable. |
170 */ | 173 */ |
171 get configurable() { | 174 get configurable() { |
172 return this.configurable_; | 175 return this.configurable_; |
| 176 }, |
| 177 /** |
| 178 * @return {VolumeManagerCommon.Source} Source of the volume's data. |
| 179 */ |
| 180 get source() { |
| 181 return this.source_; |
173 } | 182 } |
174 }; | 183 }; |
175 | 184 |
176 /** | 185 /** |
177 * Starts resolving the display root and obtains it. It may take long time for | 186 * Starts resolving the display root and obtains it. It may take long time for |
178 * Drive. Once resolved, it is cached. | 187 * Drive. Once resolved, it is cached. |
179 * | 188 * |
180 * @param {function(!DirectoryEntry)=} opt_onSuccess Success callback with the | 189 * @param {function(!DirectoryEntry)=} opt_onSuccess Success callback with the |
181 * display root directory as an argument. | 190 * display root directory as an argument. |
182 * @param {function(*)=} opt_onFailure Failure callback. | 191 * @param {function(*)=} opt_onFailure Failure callback. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 break; | 256 break; |
248 default: | 257 default: |
249 // TODO(mtomasz): Calculate volumeLabel for all types of volumes in the | 258 // TODO(mtomasz): Calculate volumeLabel for all types of volumes in the |
250 // C++ layer. | 259 // C++ layer. |
251 localizedLabel = volumeMetadata.volumeLabel || | 260 localizedLabel = volumeMetadata.volumeLabel || |
252 volumeMetadata.volumeId.split(':', 2)[1]; | 261 volumeMetadata.volumeId.split(':', 2)[1]; |
253 break; | 262 break; |
254 } | 263 } |
255 | 264 |
256 console.debug('Requesting file system.'); | 265 console.debug('Requesting file system.'); |
257 var configurable = false; | |
258 | |
259 return new Promise( | 266 return new Promise( |
260 function(resolve, reject) { | 267 function(resolve, reject) { |
261 if (volumeMetadata.volumeType !== | 268 chrome.fileSystem.requestFileSystem( |
262 VolumeManagerCommon.VolumeType.PROVIDED) { | 269 { |
263 resolve(); | 270 volumeId: volumeMetadata.volumeId, |
264 } | 271 writable: !volumeMetadata.isReadOnly |
265 | 272 }, |
266 chrome.fileManagerPrivate.getProvidingExtensions( | 273 function(isolatedFileSystem) { |
267 function(extensions) { | 274 if (chrome.runtime.lastError) |
268 if (chrome.runtime.lastError) { | |
269 reject(chrome.runtime.lastError.message); | 275 reject(chrome.runtime.lastError.message); |
270 return; | 276 else |
271 } | 277 resolve(isolatedFileSystem); |
272 configurable = extensions.some(function(extension) { | |
273 return extension.extensionId === volumeMetadata.extensionId && | |
274 extension.configurable; | |
275 }); | |
276 resolve(); | |
277 }); | 278 }); |
278 }) | 279 }) |
279 .then( | 280 .then( |
280 function() { | 281 /** |
281 return new Promise(function(resolve, reject) { | 282 * @param {!FileSystem} isolatedFileSystem |
282 chrome.fileSystem.requestFileSystem( | 283 */ |
283 { | 284 function(isolatedFileSystem) { |
284 volumeId: volumeMetadata.volumeId, | 285 // Since File System API works on isolated entries only, we need to |
285 writable: !volumeMetadata.isReadOnly | 286 // convert it back to external one. |
286 }, | 287 // TODO(mtomasz): Make Files app work on isolated entries. |
287 function(isolatedFileSystem) { | 288 return new Promise(function(resolve, reject) { |
288 if (chrome.runtime.lastError) | 289 chrome.fileManagerPrivate.resolveIsolatedEntries( |
289 reject(chrome.runtime.lastError.message); | 290 [isolatedFileSystem.root], |
290 else | 291 function(entries) { |
291 resolve(isolatedFileSystem); | 292 if (chrome.runtime.lastError) |
292 }); | 293 reject(chrome.runtime.lastError.message); |
293 }); | 294 else if (!entries[0]) |
294 }) | 295 reject('Resolving for external context failed.'); |
295 .then( | 296 else |
296 /** | 297 resolve(entries[0].filesystem); |
297 * @param {!FileSystem} isolatedFileSystem | |
298 */ | |
299 function(isolatedFileSystem) { | |
300 // Since File System API works on isolated entries only, we need to | |
301 // convert it back to external one. | |
302 // TODO(mtomasz): Make Files app work on isolated entries. | |
303 return new Promise(function(resolve, reject) { | |
304 chrome.fileManagerPrivate.resolveIsolatedEntries( | |
305 [isolatedFileSystem.root], | |
306 function(entries) { | |
307 if (chrome.runtime.lastError) | |
308 reject(chrome.runtime.lastError.message); | |
309 else if (!entries[0]) | |
310 reject('Resolving for external context failed.'); | |
311 else | |
312 resolve(entries[0].filesystem); | |
313 }); | |
314 }); | 298 }); |
315 }) | |
316 .then( | |
317 /** | |
318 * @param {!FileSystem} fileSystem | |
319 */ | |
320 function(fileSystem) { | |
321 console.debug('File system obtained: ' + volumeMetadata.volumeId); | |
322 if (volumeMetadata.volumeType === | |
323 VolumeManagerCommon.VolumeType.DRIVE) { | |
324 // After file system is mounted, we "read" drive grand root | |
325 // entry at first. This triggers full feed fetch on background. | |
326 // Note: we don't need to handle errors here, because even if | |
327 // it fails, accessing to some path later will just become | |
328 // a fast-fetch and it re-triggers full-feed fetch. | |
329 fileSystem.root.createReader().readEntries( | |
330 function() { /* do nothing */ }, | |
331 function(error) { | |
332 console.error( | |
333 'Triggering full feed fetch is failed: ' + | |
334 error.name); | |
335 }); | |
336 } | |
337 return new VolumeInfo( | |
338 /** @type {VolumeManagerCommon.VolumeType} */ | |
339 (volumeMetadata.volumeType), | |
340 volumeMetadata.volumeId, | |
341 fileSystem, | |
342 volumeMetadata.mountCondition, | |
343 volumeMetadata.deviceType, | |
344 volumeMetadata.devicePath, | |
345 volumeMetadata.isReadOnly, | |
346 volumeMetadata.profile, | |
347 localizedLabel, | |
348 volumeMetadata.extensionId, | |
349 volumeMetadata.hasMedia, | |
350 configurable); | |
351 }) | |
352 .catch( | |
353 /** | |
354 * @param {*} error | |
355 */ | |
356 function(error) { | |
357 console.error('Failed to mount a file system: ' + | |
358 volumeMetadata.volumeId + ' because of: ' + | |
359 (error.stack || error)); | |
360 return new VolumeInfo( | |
361 /** @type {VolumeManagerCommon.VolumeType} */ | |
362 (volumeMetadata.volumeType), | |
363 volumeMetadata.volumeId, | |
364 null, // File system is not found. | |
365 volumeMetadata.mountCondition, | |
366 volumeMetadata.deviceType, | |
367 volumeMetadata.devicePath, | |
368 volumeMetadata.isReadOnly, | |
369 volumeMetadata.profile, | |
370 localizedLabel, | |
371 volumeMetadata.extensionId, | |
372 volumeMetadata.hasMedia, | |
373 configurable); | |
374 }); | 299 }); |
| 300 }) |
| 301 .then( |
| 302 /** |
| 303 * @param {!FileSystem} fileSystem |
| 304 */ |
| 305 function(fileSystem) { |
| 306 console.debug('File system obtained: ' + volumeMetadata.volumeId); |
| 307 if (volumeMetadata.volumeType === |
| 308 VolumeManagerCommon.VolumeType.DRIVE) { |
| 309 // After file system is mounted, we "read" drive grand root |
| 310 // entry at first. This triggers full feed fetch on background. |
| 311 // Note: we don't need to handle errors here, because even if |
| 312 // it fails, accessing to some path later will just become |
| 313 // a fast-fetch and it re-triggers full-feed fetch. |
| 314 fileSystem.root.createReader().readEntries( |
| 315 function() { /* do nothing */ }, |
| 316 function(error) { |
| 317 console.error( |
| 318 'Triggering full feed fetch is failed: ' + |
| 319 error.name); |
| 320 }); |
| 321 } |
| 322 return new VolumeInfo( |
| 323 /** @type {VolumeManagerCommon.VolumeType} */ |
| 324 (volumeMetadata.volumeType), |
| 325 volumeMetadata.volumeId, |
| 326 fileSystem, |
| 327 volumeMetadata.mountCondition, |
| 328 volumeMetadata.deviceType, |
| 329 volumeMetadata.devicePath, |
| 330 volumeMetadata.isReadOnly, |
| 331 volumeMetadata.profile, |
| 332 localizedLabel, |
| 333 volumeMetadata.extensionId, |
| 334 volumeMetadata.hasMedia, |
| 335 volumeMetadata.configurable, |
| 336 /** @type {VolumeManagerCommon.Source} */ |
| 337 (volumeMetadata.source)); |
| 338 }) |
| 339 .catch( |
| 340 /** |
| 341 * @param {*} error |
| 342 */ |
| 343 function(error) { |
| 344 console.error('Failed to mount a file system: ' + |
| 345 volumeMetadata.volumeId + ' because of: ' + |
| 346 (error.stack || error)); |
| 347 return new VolumeInfo( |
| 348 /** @type {VolumeManagerCommon.VolumeType} */ |
| 349 (volumeMetadata.volumeType), |
| 350 volumeMetadata.volumeId, |
| 351 null, // File system is not found. |
| 352 volumeMetadata.mountCondition, |
| 353 volumeMetadata.deviceType, |
| 354 volumeMetadata.devicePath, |
| 355 volumeMetadata.isReadOnly, |
| 356 volumeMetadata.profile, |
| 357 localizedLabel, |
| 358 volumeMetadata.extensionId, |
| 359 volumeMetadata.hasMedia, |
| 360 volumeMetadata.configurable, |
| 361 /** @type {VolumeManagerCommon.Source} */ |
| 362 (volumeMetadata.source)); |
| 363 }); |
375 }; | 364 }; |
376 | 365 |
377 /** | 366 /** |
378 * The order of the volume list based on root type. | 367 * The order of the volume list based on root type. |
379 * @type {Array.<VolumeManagerCommon.VolumeType>} | 368 * @type {Array.<VolumeManagerCommon.VolumeType>} |
380 * @const | 369 * @const |
381 * @private | 370 * @private |
382 */ | 371 */ |
383 volumeManagerUtil.volumeListOrder_ = [ | 372 volumeManagerUtil.volumeListOrder_ = [ |
384 VolumeManagerCommon.VolumeType.DRIVE, | 373 VolumeManagerCommon.VolumeType.DRIVE, |
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 this.isDriveBased; | 1101 this.isDriveBased; |
1113 | 1102 |
1114 /** | 1103 /** |
1115 * Whether the entry is read only or not. | 1104 * Whether the entry is read only or not. |
1116 * @type {boolean} | 1105 * @type {boolean} |
1117 */ | 1106 */ |
1118 this.isReadOnly = isReadOnly; | 1107 this.isReadOnly = isReadOnly; |
1119 | 1108 |
1120 Object.freeze(this); | 1109 Object.freeze(this); |
1121 } | 1110 } |
OLD | NEW |