summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhirono <hirono@chromium.org>2015-03-11 22:04:28 -0700
committerCommit bot <commit-bot@chromium.org>2015-03-12 05:05:30 +0000
commit86aa57796c183cf2782c972025ed33c403ac067b (patch)
tree0f145dcafc926100a173aba42f0600d712fd52e3
parentc1456d32aa5911ef628cc77703e0c0487321aec5 (diff)
downloadchromium_src-86aa57796c183cf2782c972025ed33c403ac067b.zip
chromium_src-86aa57796c183cf2782c972025ed33c403ac067b.tar.gz
chromium_src-86aa57796c183cf2782c972025ed33c403ac067b.tar.bz2
Files.app: Fix race condition in VolumeManager.
Gallery sometimes misses drive volume by the following logic. It also can be happened to Files.app. 1. chrome.fileManagerPrivate.getVolumeMetadataList 2. Before complete #1, drive volume is mounted. 3. After complete #1, register a listener to onMountCompleted event. BUG=466467 TEST=FileManagerJsTest.VolumeManager Review URL: https://codereview.chromium.org/988713003 Cr-Commit-Position: refs/heads/master@{#320235}
-rw-r--r--ui/file_manager/file_manager/background/js/volume_manager.js70
-rw-r--r--ui/file_manager/file_manager/background/js/volume_manager_unittest.js30
2 files changed, 69 insertions, 31 deletions
diff --git a/ui/file_manager/file_manager/background/js/volume_manager.js b/ui/file_manager/file_manager/background/js/volume_manager.js
index 565ab06..5563cf7 100644
--- a/ui/file_manager/file_manager/background/js/volume_manager.js
+++ b/ui/file_manager/file_manager/background/js/volume_manager.js
@@ -625,7 +625,34 @@ VolumeManager.getInstance = function(opt_callback) {
VolumeManager.revokeInstanceForTesting = function() {
VolumeManager.instancePromise_ = null;
VolumeManager.instance_ = null;
-}
+};
+
+/**
+ * Adds new volume info from the given volumeMetadata. If the corresponding
+ * volume info has already been added, the volumeMetadata is ignored.
+ * @param {!VolumeMetadata} volumeMetadata
+ * @return {!Promise<!VolumeInfo>}
+ * @private
+ */
+VolumeManager.prototype.addVolumeMetadata_ = function(volumeMetadata) {
+ return new Promise(function(callback) {
+ volumeManagerUtil.createVolumeInfo(volumeMetadata, callback);
+ }).then(function(volumeInfo) {
+ if (this.volumeInfoList.findIndex(volumeInfo.volumeId) === -1) {
+ this.volumeInfoList.add(volumeInfo);
+
+ // Update the network connection status, because until the drive is
+ // initialized, the status is set to not ready.
+ // TODO(mtomasz): The connection status should be migrated into
+ // VolumeMetadata.
+ if (volumeMetadata.volumeType ===
+ VolumeManagerCommon.VolumeType.DRIVE) {
+ this.onDriveConnectionStatusChanged_();
+ }
+ }
+ return volumeInfo;
+ }.bind(this));
+};
/**
* Initializes mount points.
@@ -634,6 +661,8 @@ VolumeManager.revokeInstanceForTesting = function() {
* @private
*/
VolumeManager.prototype.initialize_ = function(callback) {
+ chrome.fileManagerPrivate.onMountCompleted.addListener(
+ this.onMountCompleted_.bind(this));
console.debug('Requesting volume list.');
chrome.fileManagerPrivate.getVolumeMetadataList(function(volumeMetadataList) {
console.debug('Volume list fetched with: ' + volumeMetadataList.length +
@@ -644,23 +673,16 @@ VolumeManager.prototype.initialize_ = function(callback) {
// volumes in the volumeMetadataList are mounted. crbug.com/135477.
this.mountQueue_.run(function(inCallback) {
// Create VolumeInfo for each volume.
- var group = new AsyncUtil.Group();
- for (var i = 0; i < volumeMetadataList.length; i++) {
- console.debug('Initializing volume: ' + volumeMetadataList[i].volumeId);
- group.add(function(volumeMetadata, continueCallback) {
- volumeManagerUtil.createVolumeInfo(
- volumeMetadata,
+ Promise.all([
+ volumeMetadataList.map(function(volumeMetadata) {
+ console.debug(
+ 'Initializing volume: ' + volumeMetadata.volumeId);
+ return this.addVolumeMetadata_(volumeMetadata).then(
function(volumeInfo) {
- this.volumeInfoList.add(volumeInfo);
- if (volumeMetadata.volumeType ===
- VolumeManagerCommon.VolumeType.DRIVE)
- this.onDriveConnectionStatusChanged_();
console.debug('Initialized volume: ' + volumeInfo.volumeId);
- continueCallback();
- }.bind(this));
- }.bind(this, volumeMetadataList[i]));
- }
- group.run(function() {
+ });
+ }.bind(this))
+ ]).then(function() {
console.debug('Initialized all volumes.');
// Call the callback of the initialize function.
callback();
@@ -669,9 +691,6 @@ VolumeManager.prototype.initialize_ = function(callback) {
inCallback();
});
}.bind(this));
-
- chrome.fileManagerPrivate.onMountCompleted.addListener(
- this.onMountCompleted_.bind(this));
}.bind(this));
};
@@ -693,20 +712,9 @@ VolumeManager.prototype.onMountCompleted_ = function(event) {
VolumeManagerCommon.VolumeError.UNKNOWN_FILESYSTEM ||
event.status ===
VolumeManagerCommon.VolumeError.UNSUPPORTED_FILESYSTEM) {
- volumeManagerUtil.createVolumeInfo(
- event.volumeMetadata,
+ this.addVolumeMetadata_(event.volumeMetadata).then(
function(volumeInfo) {
- this.volumeInfoList.add(volumeInfo);
this.finishRequest_(requestKey, event.status, volumeInfo);
-
- if (volumeInfo.volumeType ===
- VolumeManagerCommon.VolumeType.DRIVE) {
- // Update the network connection status, because until the
- // drive is initialized, the status is set to not ready.
- // TODO(mtomasz): The connection status should be migrated
- // into VolumeMetadata.
- this.onDriveConnectionStatusChanged_();
- }
callback();
}.bind(this));
} else {
diff --git a/ui/file_manager/file_manager/background/js/volume_manager_unittest.js b/ui/file_manager/file_manager/background/js/volume_manager_unittest.js
index d7e97b7..e77a34e 100644
--- a/ui/file_manager/file_manager/background/js/volume_manager_unittest.js
+++ b/ui/file_manager/file_manager/background/js/volume_manager_unittest.js
@@ -251,3 +251,33 @@ function testVolumeInfoListWhenReady(callback) {
assertEquals(volumeInfo, volumes[1]);
}), callback);
}
+
+function testDriveMountedDuringInitialization(callback) {
+ var sendMetadataListCallback;
+ chrome.fileManagerPrivate.getVolumeMetadataList = function(callback) {
+ sendMetadataListCallback = callback;
+ };
+
+ // Start initialization.
+ var instancePromise = VolumeManager.getInstance();
+
+ // Drive is mounted during initialization.
+ chrome.fileManagerPrivate.onMountCompleted.dispatchEvent({
+ eventType: 'mount',
+ status: 'success',
+ volumeMetadata: {
+ volumeId: 'drive',
+ volumeType: VolumeManagerCommon.VolumeType.DRIVE,
+ sourcePath: '/drive',
+ profile: getMockProfile()
+ }
+ });
+
+ // Complete initialization.
+ sendMetadataListCallback([]);
+
+ reportPromise(instancePromise.then(function(volumeManager) {
+ assertTrue(!!volumeManager.getCurrentProfileVolumeInfo(
+ VolumeManagerCommon.VolumeType.DRIVE));
+ }), callback);
+}