Cancel scans when directory changed.
TEST=*ImportController* and *MediaScanner*
Review URL: https://codereview.chromium.org/1045663002
Cr-Commit-Position: refs/heads/master@{#323184}
diff --git a/ui/file_manager/file_manager/background/js/media_scanner.js b/ui/file_manager/file_manager/background/js/media_scanner.js
index 02e411e..4c20d2b3 100644
--- a/ui/file_manager/file_manager/background/js/media_scanner.js
+++ b/ui/file_manager/file_manager/background/js/media_scanner.js
@@ -103,10 +103,12 @@
/** @override */
importer.DefaultMediaScanner.prototype.scanDirectory = function(directory) {
var scan = this.createScanResult_();
+ console.info(scan.name + ': Scanning directory ' + directory.fullPath);
+
var watcher = this.watcherFactory_(
/** @this {importer.DefaultMediaScanner} */
function() {
- scan.invalidateScan();
+ scan.cancel();
this.notify_(importer.ScanEvent.INVALIDATED, scan);
}.bind(this));
@@ -119,6 +121,7 @@
.then(
/** @this {importer.DefaultMediaScanner} */
function() {
+ console.info(scan.name + ': Finished.');
this.notify_(importer.ScanEvent.FINALIZED, scan);
}.bind(this));
@@ -131,10 +134,14 @@
throw new Error('Cannot scan empty list.');
}
var scan = this.createScanResult_();
+ console.info(
+ scan.name + ': Scanning fixed set of ' +
+ entries.length + ' entries.');
+
var watcher = this.watcherFactory_(
/** @this {importer.DefaultMediaScanner} */
function() {
- scan.invalidateScan();
+ scan.cancel();
this.notify_(importer.ScanEvent.INVALIDATED, scan);
}.bind(this));
@@ -148,6 +155,7 @@
.then(
/** @this {importer.DefaultMediaScanner} */
function() {
+ console.info(scan.name + ': Finished.');
this.notify_(importer.ScanEvent.FINALIZED, scan);
}.bind(this));
@@ -160,7 +168,8 @@
/**
* @param {!importer.DefaultScanResult} scan
* @param {!Array<!FileEntry>} entries
- * @return {!Promise} Resolves when scanning is finished.
+ * @return {!Promise} Resolves when scanning is finished normally
+ * or canceled.
* @private
*/
importer.DefaultMediaScanner.prototype.scanMediaFiles_ =
@@ -172,20 +181,32 @@
* to process.
* @return {!Promise}
*/
- var scanChunk = function(begin) {
+ var scanBatch = function(begin) {
+ if (scan.canceled()) {
+ console.debug(
+ scan.name + ': Skipping remaining ' +
+ (entries.length - begin) +
+ ' entries. Scan was canceled.');
+ return Promise.resolve();
+ }
+
// the second arg to slice is an exclusive end index, so we +1 batch size.
- var end = begin + importer.DefaultMediaScanner.SCAN_BATCH_SIZE + 1;
+ var end = begin + importer.DefaultMediaScanner.SCAN_BATCH_SIZE;
+ console.log(scan.name + ': Processing batch ' + begin + '-' + (end - 1));
+ var batch = entries.slice(begin, end);
+
return Promise.all(
- entries.slice(begin, end).map(handleFileEntry))
+ batch.map(handleFileEntry))
.then(
+ /** @this {importer.DefaultMediaScanner} */
function() {
if (end < entries.length) {
- return scanChunk(end);
+ return scanBatch(end);
}
});
};
- return scanChunk(0);
+ return scanBatch(0);
};
/**
@@ -321,9 +342,16 @@
importer.ScanResult.prototype.isFinal;
/**
- * @return {boolean} true if scanning is invalidated.
+ * Notifies the scan to stop working. Some in progress work
+ * may continue, but no new work will be undertaken.
*/
-importer.ScanResult.prototype.isInvalidated;
+importer.ScanResult.prototype.cancel;
+
+/**
+ * @return {boolean} True if the scan has been canceled. Some
+ * work started prior to cancelation may still be ongoing.
+ */
+importer.ScanResult.prototype.canceled;
/**
* Returns all files entries discovered so far. The list will be
@@ -335,7 +363,8 @@
importer.ScanResult.prototype.getFileEntries;
/**
- * Returns a promise that fires when scanning is complete.
+ * Returns a promise that fires when scanning is finished
+ * normally or has been canceled.
*
* @return {!Promise<!importer.ScanResult>}
*/
@@ -363,6 +392,9 @@
* <p>The scan is complete, and the object will become static once the
* {@code whenFinal} promise resolves.
*
+ * Note that classes implementing this should provide a read-only
+ * {@code name} field.
+ *
* @constructor
* @struct
* @implements {importer.ScanResult}
@@ -371,6 +403,8 @@
* generator used to dedupe within the scan results itself.
*/
importer.DefaultScanResult = function(hashGenerator) {
+ /** @private {number} */
+ this.scanId_ = importer.generateId();
/** @private {function(!FileEntry): !Promise.<string>} */
this.createHashcode_ = hashGenerator;
@@ -410,7 +444,7 @@
/**
* @private {boolean}
*/
- this.invalidated_ = false;
+ this.canceled_ = false;
/** @private {!importer.Resolver.<!importer.ScanResult>} */
this.resolver_ = new importer.Resolver();
@@ -418,6 +452,8 @@
/** @struct */
importer.DefaultScanResult.prototype = {
+ /** @return {string} */
+ get name() { return 'ScanResult(' + this.scanId_ + ')' },
/** @return {function()} */
get resolve() { return this.resolver_.resolve.bind(null, this); },
@@ -431,10 +467,6 @@
return this.resolver_.settled;
};
-importer.DefaultScanResult.prototype.isInvalidated = function() {
- return this.invalidated_;
-};
-
/** @override */
importer.DefaultScanResult.prototype.getFileEntries = function() {
return this.fileEntries_;
@@ -445,11 +477,14 @@
return this.resolver_.promise;
};
-/**
- * Invalidates this scan.
- */
-importer.DefaultScanResult.prototype.invalidateScan = function() {
- this.invalidated_ = true;
+/** @override */
+importer.DefaultScanResult.prototype.cancel = function() {
+ this.canceled_ = true;
+};
+
+/** @override */
+importer.DefaultScanResult.prototype.canceled = function() {
+ return this.canceled_;
};
/**
diff --git a/ui/file_manager/file_manager/background/js/mock_media_scanner.js b/ui/file_manager/file_manager/background/js/mock_media_scanner.js
index ddc26da..f2335ad 100644
--- a/ui/file_manager/file_manager/background/js/mock_media_scanner.js
+++ b/ui/file_manager/file_manager/background/js/mock_media_scanner.js
@@ -103,6 +103,15 @@
};
/**
+ * Asserts that the last scan was canceled. Fails if no
+ * scan exists.
+ */
+TestMediaScanner.prototype.assertLastScanCanceled = function() {
+ assertTrue(this.scans_.length > 0);
+ assertTrue(this.scans_[this.scans_.length - 1].canceled());
+};
+
+/**
* importer.MediaScanner and importer.ScanResult test double.
*
* @constructor
@@ -112,6 +121,9 @@
* @param {!Array.<!FileEntry>} fileEntries
*/
function TestScanResult(fileEntries) {
+ /** @private {number} */
+ this.scanId_ = ++TestScanResult.lastId_;
+
/**
* List of file entries found while scanning.
* @type {!Array.<!FileEntry>}
@@ -133,6 +145,9 @@
/** @type {boolean} */
this.settled_ = false;
+ /** @private {boolean} */
+ this.canceled_ = false;
+
/** @type {!Promise.<!importer.ScanResult>} */
this.whenFinal_ = new Promise(
function(resolve, reject) {
@@ -147,6 +162,15 @@
}.bind(this));
}
+/** @private {number} */
+TestScanResult.lastId_ = 0;
+
+/** @struct */
+TestScanResult.prototype = {
+ /** @return {string} */
+ get name() { return 'TestScanResult(' + this.scanId_ + ')' }
+};
+
/** @override */
TestScanResult.prototype.getFileEntries = function() {
return this.fileEntries;
@@ -168,8 +192,13 @@
};
/** @override */
-TestScanResult.prototype.isInvalidated = function() {
- return false;
+TestScanResult.prototype.cancel = function() {
+ this.canceled_ = true;
+};
+
+/** @override */
+TestScanResult.prototype.canceled = function() {
+ return this.canceled_;
};
/** @override */
diff --git a/ui/file_manager/file_manager/common/js/importer_common.js b/ui/file_manager/file_manager/common/js/importer_common.js
index 8a441f8..2ec8735 100644
--- a/ui/file_manager/file_manager/common/js/importer_common.js
+++ b/ui/file_manager/file_manager/common/js/importer_common.js
@@ -348,7 +348,7 @@
if (id) {
return id;
}
- var id = importer.generateMachineId_();
+ var id = importer.generateId();
return storage.set(importer.Setting.MACHINE_ID, id)
.then(
function() {
@@ -381,11 +381,9 @@
};
/**
- * @return {number} A relatively unique six digit integer that is most likely
- * unique to this machine among a user's machines. Used only to segregate
- * log files on sync storage.
+ * @return {number} A relatively random six digit integer.
*/
-importer.generateMachineId_ = function() {
+importer.generateId = function() {
return Math.floor(Math.random() * 899999) + 100000;
};
diff --git a/ui/file_manager/file_manager/foreground/js/import_controller.js b/ui/file_manager/file_manager/foreground/js/import_controller.js
index 058e2dd..93f18df 100644
--- a/ui/file_manager/file_manager/foreground/js/import_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/import_controller.js
@@ -80,6 +80,9 @@
this.scanner_.removeObserver(listener);
}.bind(this));
+ this.environment_.addWindowCloseListener(
+ this.onWindowClosing_.bind(this));
+
this.environment_.addVolumeUnmountListener(
this.onVolumeUnmounted_.bind(this));
@@ -128,7 +131,7 @@
switch (event) {
case importer.ScanEvent.INVALIDATED:
- this.scanManager_.reset();
+ this.onScanInvalidated_();
case importer.ScanEvent.FINALIZED:
case importer.ScanEvent.UPDATED:
this.checkState_(scan);
@@ -136,6 +139,11 @@
}
};
+/** @private */
+importer.ImportController.prototype.onWindowClosing_ = function() {
+ this.scanManager_.reset(); // Will cancel any active scans.
+};
+
/**
* @param {string} volumeId
* @private
@@ -160,10 +168,11 @@
importer.isMediaDirectory(event.newDirEntry, this.environment_)) {
this.commandWidget_.setDetailsVisible(true);
}
- this.scanManager_.clearSelectionScan();
+
+ this.scanManager_.reset();
if (this.isCurrentDirectoryScannable_()) {
this.checkState_(
- this.scanManager_.getCurrentDirectoryScan());
+ this.scanManager_.getDirectoryScan());
} else {
this.checkState_();
}
@@ -171,6 +180,15 @@
/** @private */
importer.ImportController.prototype.onSelectionChanged_ = function() {
+ // NOTE: Empty selection changed events can and will fire for a directory
+ // before we receive the the corresponding directory changed event
+ // and when the selection is empty. These are spurios events
+ // and we ignore them.
+ if (!this.scanManager_.hasSelectionScan() &&
+ this.environment_.getSelection().length === 0) {
+ return;
+ }
+
// NOTE: We clear the scan here, but don't immediately initiate
// a new scan. checkState will attempt to initialize the scan
// during normal processing.
@@ -181,7 +199,7 @@
if (this.environment_.getSelection().length === 0 &&
this.isCurrentDirectoryScannable_()) {
this.checkState_(
- this.scanManager_.getCurrentDirectoryScan());
+ this.scanManager_.getDirectoryScan());
} else {
this.checkState_();
}
@@ -199,6 +217,18 @@
this.checkState_();
};
+/** @private */
+importer.ImportController.prototype.onScanInvalidated_ = function() {
+ this.scanManager_.reset();
+ if (this.environment_.getSelection().length === 0 &&
+ this.isCurrentDirectoryScannable_()) {
+ this.checkState_(
+ this.scanManager_.getDirectoryScan());
+ } else {
+ this.checkState_();
+ }
+};
+
/**
* Does book keeping necessary to finalize the active task.
* @private
@@ -282,9 +312,11 @@
* @private
*/
importer.ImportController.prototype.cancel_ = function() {
- this.activeImport_.task.requestCancel();
- this.finalizeActiveImport_();
- this.tracker_.send(metrics.ImportEvents.IMPORT_CANCELLED);
+ if (this.activeImport_) {
+ this.activeImport_.task.requestCancel();
+ this.finalizeActiveImport_();
+ this.tracker_.send(metrics.ImportEvents.IMPORT_CANCELLED);
+ }
this.scanManager_.reset();
this.checkState_();
@@ -411,14 +443,13 @@
*/
importer.ImportController.prototype.tryScan_ = function() {
var entries = this.environment_.getSelection();
-
if (entries.length) {
if (entries.every(
importer.isEligibleEntry.bind(null, this.environment_))) {
return this.scanManager_.getSelectionScan(entries);
}
} else if (this.isCurrentDirectoryScannable_()) {
- return this.scanManager_.getCurrentDirectoryScan();
+ return this.scanManager_.getDirectoryScan();
}
return null;
@@ -802,40 +833,53 @@
this.scanner_ = scanner;
/**
- * A cache of selection scans by directory (url).
+ * The active files scan, if any.
*
* @private {importer.ScanResult}
*/
this.selectionScan_ = null;
/**
- * A cache of scans by directory (url).
+ * The active directory scan, if any.
*
- * @private {!Object.<string, !importer.ScanResult>}
+ * @private {importer.ScanResult}
*/
- this.directoryScans_ = {};
+ this.directoryScan_ = null;
};
/**
- * Forgets all scans.
+ * Cancels and forgets all scans.
*/
importer.ScanManager.prototype.reset = function() {
this.clearSelectionScan();
- this.clearDirectoryScans();
+ this.clearDirectoryScan();
};
/**
- * Forgets the selection scans for the current directory.
+ * @return {boolean} True if we have an existing selection scan.
+ */
+importer.ScanManager.prototype.hasSelectionScan = function() {
+ return !!this.selectionScan_;
+};
+
+/**
+ * Cancels and forgets the current selection scan, if any.
*/
importer.ScanManager.prototype.clearSelectionScan = function() {
+ if (this.selectionScan_) {
+ this.selectionScan_.cancel();
+ }
this.selectionScan_ = null;
};
/**
- * Forgets directory scans.
+ * Cancels and forgets the current directory scan, if any.
*/
-importer.ScanManager.prototype.clearDirectoryScans = function() {
- this.directoryScans_ = {};
+importer.ScanManager.prototype.clearDirectoryScan = function() {
+ if (this.directoryScan_) {
+ this.directoryScan_.cancel();
+ }
+ this.directoryScan_ = null;
};
/**
@@ -843,14 +887,7 @@
* if none.
*/
importer.ScanManager.prototype.getActiveScan = function() {
- if (!!this.selectionScan_) {
- return this.selectionScan_;
- }
- var directory = this.environment_.getCurrentDirectory();
- if (directory) {
- return this.directoryScans_[directory.toURL()];
- }
- return null;
+ return this.selectionScan_ || this.directoryScan_;
};
/**
@@ -859,13 +896,7 @@
* selection scan or the scan for the current directory.
*/
importer.ScanManager.prototype.isActiveScan = function(scan) {
- if (scan === this.selectionScan_) {
- return true;
- }
-
- var directory = this.environment_.getCurrentDirectory();
- return !!directory &&
- scan === this.directoryScans_[directory.toURL()];
+ return scan === this.selectionScan_ || scan === this.directoryScan_;
};
/**
@@ -888,21 +919,15 @@
*
* @return {importer.ScanResult}
*/
-importer.ScanManager.prototype.getCurrentDirectoryScan = function() {
- var directory = this.environment_.getCurrentDirectory();
- if (!directory) {
- return null;
+importer.ScanManager.prototype.getDirectoryScan = function() {
+ if (!this.directoryScan_) {
+ var directory = this.environment_.getCurrentDirectory();
+ if (directory) {
+ this.directoryScan_ = this.scanner_.scanDirectory(
+ /** @type {!DirectoryEntry} */ (directory));
+ }
}
-
- var url = directory.toURL();
- var scan = this.directoryScans_[url];
- if (!scan) {
- scan = this.scanner_.scanDirectory(
- /** @type {!DirectoryEntry} */ (directory));
- this.directoryScans_[url] = scan;
- }
-
- return scan;
+ return this.directoryScan_;
};
/**
@@ -945,6 +970,14 @@
importer.ControllerEnvironment.prototype.getFreeStorageSpace;
/**
+ * Installs a 'window closed' listener. Listener is called just
+ * just before the window is closed. Any business must be
+ * done synchronously.
+ * @param {function()} listener
+ */
+importer.ControllerEnvironment.prototype.addWindowCloseListener;
+
+/**
* Installs an 'unmount' listener. Listener is called with
* the corresponding volume id when a volume is unmounted.
* @param {function(string)} listener
@@ -1049,22 +1082,6 @@
};
/** @override */
-importer.RuntimeControllerEnvironment.prototype.addVolumeUnmountListener =
- function(listener) {
- // TODO(smckay): remove listeners when the page is torn down.
- chrome.fileManagerPrivate.onMountCompleted.addListener(
- /**
- * @param {!MountCompletedEvent} event
- * @this {importer.RuntimeControllerEnvironment}
- */
- function(event) {
- if (event.eventType === 'unmount') {
- listener(event.volumeMetadata.volumeId);
- }
- });
-};
-
-/** @override */
importer.RuntimeControllerEnvironment.prototype.getFreeStorageSpace =
function() {
// Checking DOWNLOADS returns the amount of available local storage space.
@@ -1089,6 +1106,28 @@
};
/** @override */
+importer.RuntimeControllerEnvironment.prototype.addWindowCloseListener =
+ function(listener) {
+ window.addEventListener('pagehide', listener);
+};
+
+/** @override */
+importer.RuntimeControllerEnvironment.prototype.addVolumeUnmountListener =
+ function(listener) {
+ // TODO(smckay): remove listeners when the page is torn down.
+ chrome.fileManagerPrivate.onMountCompleted.addListener(
+ /**
+ * @param {!MountCompletedEvent} event
+ * @this {importer.RuntimeControllerEnvironment}
+ */
+ function(event) {
+ if (event.eventType === 'unmount') {
+ listener(event.volumeMetadata.volumeId);
+ }
+ });
+};
+
+/** @override */
importer.RuntimeControllerEnvironment.prototype.addDirectoryChangedListener =
function(listener) {
// TODO(smckay): remove listeners when the page is torn down.
diff --git a/ui/file_manager/file_manager/foreground/js/import_controller_unittest.html b/ui/file_manager/file_manager/foreground/js/import_controller_unittest.html
index cd21039..329b290 100644
--- a/ui/file_manager/file_manager/foreground/js/import_controller_unittest.html
+++ b/ui/file_manager/file_manager/foreground/js/import_controller_unittest.html
@@ -22,6 +22,7 @@
<script src="../../common/js/metrics_events.js"></script>
<script src="../../common/js/test_tracker.js"></script>
<script src="../../common/js/volume_manager_common.js"></script>
+ <script src="../../common/js/file_type.js"></script>
<script src="../../common/js/importer_common.js"></script>
<script src="../../background/js/mock_file_operation_manager.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/import_controller_unittest.js b/ui/file_manager/file_manager/foreground/js/import_controller_unittest.js
index 3cd55df..c280757 100644
--- a/ui/file_manager/file_manager/foreground/js/import_controller_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/import_controller_unittest.js
@@ -26,6 +26,9 @@
/** @type {!importer.TestCommandWidget} */
var widget;
+/** @type {!DirectoryEntry} */
+var nonDcimDirectory;
+
/**
* @enum {string}
*/
@@ -47,6 +50,10 @@
widget = new importer.TestCommandWidget();
+ nonDcimDirectory = new MockDirectoryEntry(
+ new MockFileSystem('testFs'),
+ '/jellybeans/');
+
volumeManager = new MockVolumeManager();
MockVolumeManager.installMockSingleton(volumeManager);
@@ -95,24 +102,25 @@
],
'/DCIM');
- environment.directoryChangedListener_(EMPTY_EVENT);
+ var dcim = environment.getCurrentDirectory();
+
+ environment.directoryChangedListener(EMPTY_EVENT);
var promise = widget.updateResolver.promise.then(
+ function() {
+ // Reset the promise so we can wait on a second widget update.
+ widget.resetPromises();
+ environment.setCurrentDirectory(nonDcimDirectory);
+ environment.simulateUnmount();
+
+ environment.setCurrentDirectory(dcim);
+ environment.directoryChangedListener(EMPTY_EVENT);
+ // Return the new promise, so subsequent "thens" only
+ // fire once the widget has been updated again.
+ return widget.updateResolver.promise;
+ }).then(
function() {
- // Reset the promise so we can wait on a second widget update.
- widget.resetPromises();
-
- // Faux unmount the volume, then request an update again.
- // A fresh new scan should be started.
- environment.simulateUnmount();
-
- environment.directoryChangedListener_(EMPTY_EVENT);
- // Return the new promise, so subsequent "thens" only
- // fire once the widget has been updated again.
- return widget.updateResolver.promise;
- }).then(
- function() {
- mediaScanner.assertScanCount(2);
- });
+ mediaScanner.assertScanCount(2);
+ });
reportPromise(promise, callback);
}
@@ -128,10 +136,71 @@
],
'/DCIM');
- environment.directoryChangedListener_(EMPTY_EVENT);
+ environment.directoryChangedListener(EMPTY_EVENT);
reportPromise(widget.updateResolver.promise, callback);
}
+function testDirectoryChange_CancelsScan(callback) {
+ var controller = createController(
+ VolumeManagerCommon.VolumeType.MTP,
+ 'mtp-volume',
+ [
+ '/DCIM/',
+ '/DCIM/photos0/',
+ '/DCIM/photos0/IMG00001.jpg',
+ '/DCIM/photos0/IMG00002.jpg',
+ '/DCIM/photos1/',
+ '/DCIM/photos1/IMG00001.jpg',
+ '/DCIM/photos1/IMG00003.jpg'
+ ],
+ '/DCIM');
+
+ environment.directoryChangedListener(EMPTY_EVENT);
+ var promise = widget.updateResolver.promise.then(
+ function() {
+ // Reset the promise so we can wait on a second widget update.
+ widget.resetPromises();
+ environment.setCurrentDirectory(nonDcimDirectory);
+ environment.directoryChangedListener(EMPTY_EVENT);
+ }).then(
+ function() {
+ mediaScanner.assertScanCount(1);
+ mediaScanner.assertLastScanCanceled();
+ });
+
+ reportPromise(promise, callback);
+}
+
+function testWindowClose_CancelsScan(callback) {
+ var controller = createController(
+ VolumeManagerCommon.VolumeType.MTP,
+ 'mtp-volume',
+ [
+ '/DCIM/',
+ '/DCIM/photos0/',
+ '/DCIM/photos0/IMG00001.jpg',
+ '/DCIM/photos0/IMG00002.jpg',
+ '/DCIM/photos1/',
+ '/DCIM/photos1/IMG00001.jpg',
+ '/DCIM/photos1/IMG00003.jpg'
+ ],
+ '/DCIM');
+
+ environment.directoryChangedListener(EMPTY_EVENT);
+ var promise = widget.updateResolver.promise.then(
+ function() {
+ // Reset the promise so we can wait on a second widget update.
+ widget.resetPromises();
+ environment.windowCloseListener();
+ }).then(
+ function() {
+ mediaScanner.assertScanCount(1);
+ mediaScanner.assertLastScanCanceled();
+ });
+
+ reportPromise(promise, callback);
+}
+
function testDirectoryChange_DetailsPanelVisibility_InitialChangeDir() {
var controller = createController(
VolumeManagerCommon.VolumeType.MTP,
@@ -148,7 +217,7 @@
new MockFileSystem('testFs'),
'/DCIM/');
- environment.directoryChangedListener_(event);
+ environment.directoryChangedListener(event);
assertTrue(widget.detailsVisible);
}
@@ -170,7 +239,7 @@
// Any previous dir at all will skip the new window logic.
event.previousDirEntry = event.newDirEntry;
- environment.directoryChangedListener_(event);
+ environment.directoryChangedListener(event);
assertFalse(widget.detailsVisible);
}
@@ -185,7 +254,14 @@
],
'/DCIM');
- environment.selectionChangedListener_();
+ var fileSystem = new MockFileSystem('testFs');
+ // ensure there is some content in the scan so the code that depends
+ // on this state doesn't croak which it finds it missing.
+ environment.selection.push(
+ new MockFileEntry(fileSystem, '/DCIM/photos0/IMG00001.jpg', {size: 0}));
+
+ environment.selectionChangedListener();
+ mediaScanner.finalizeScans();
reportPromise(widget.updateResolver.promise, callback);
}
@@ -206,7 +282,7 @@
mediaScanner.fileEntries.push(
new MockFileEntry(fileSystem, '/DCIM/photos0/IMG00001.jpg', {size: 0}));
- environment.directoryChangedListener_(EMPTY_EVENT); // initiates a scan.
+ environment.directoryChangedListener(EMPTY_EVENT); // initiates a scan.
widget.resetPromises();
mediaScanner.finalizeScans();
@@ -263,19 +339,19 @@
new MockFileEntry(fileSystem, '/DCIM/photos0/IMG00001.jpg', {size: 0}));
// First we need to force the controller into a scanning state.
- environment.directoryChangedListener_(EMPTY_EVENT);
+ environment.directoryChangedListener(EMPTY_EVENT);
return widget.updateResolver.promise.then(
- function() {
- widget.resetPromises();
- mediaScanner.finalizeScans();
- return widget.updateResolver.promise.then(
- function() {
- widget.resetPromises();
- widget.click(clickSource);
- return mediaImporter.importResolver.promise;
- });
- });
+ function() {
+ widget.resetPromises();
+ mediaScanner.finalizeScans();
+ return widget.updateResolver.promise.then(
+ function() {
+ widget.resetPromises();
+ widget.click(clickSource);
+ return mediaImporter.importResolver.promise;
+ });
+ });
}
/**
@@ -394,14 +470,17 @@
/** @private {!DirectoryEntry} */
this.directory_ = directory;
- /** @private {function(string)} */
- this.volumeUnmountListener_;
+ /** @public {function()} */
+ this.windowCloseListener;
- /** @private {function()} */
- this.directoryChangedListener_;
+ /** @public {function(string)} */
+ this.volumeUnmountListener;
- /** @private {function()} */
- this.selectionChangedListener_;
+ /** @public {function()} */
+ this.directoryChangedListener;
+
+ /** @public {function()} */
+ this.selectionChangedListener;
/** @public {!Entry} */
this.selection = [];
@@ -455,21 +534,27 @@
};
/** @override */
+TestControllerEnvironment.prototype.addWindowCloseListener =
+ function(listener) {
+ this.windowCloseListener = listener;
+};
+
+/** @override */
TestControllerEnvironment.prototype.addVolumeUnmountListener =
function(listener) {
- this.volumeUnmountListener_ = listener;
+ this.volumeUnmountListener = listener;
};
/** @override */
TestControllerEnvironment.prototype.addDirectoryChangedListener =
function(listener) {
- this.directoryChangedListener_ = listener;
+ this.directoryChangedListener = listener;
};
/** @override */
TestControllerEnvironment.prototype.addSelectionChangedListener =
function(listener) {
- this.selectionChangedListener_ = listener;
+ this.selectionChangedListener = listener;
};
/** @override */
@@ -493,7 +578,7 @@
* Simulates an unmount event.
*/
TestControllerEnvironment.prototype.simulateUnmount = function() {
- this.volumeUnmountListener_(this.volumeInfo_.volumeId);
+ this.volumeUnmountListener(this.volumeInfo_.volumeId);
};
/**