| Index: ui/file_manager/file_manager/foreground/js/import_controller.js
|
| diff --git a/ui/file_manager/file_manager/foreground/js/import_controller.js b/ui/file_manager/file_manager/foreground/js/import_controller.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6dfbfb8cbed5b21ee0376ef4a73fd8186feada35
|
| --- /dev/null
|
| +++ b/ui/file_manager/file_manager/foreground/js/import_controller.js
|
| @@ -0,0 +1,250 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +// Namespace
|
| +var importer = importer || {};
|
| +
|
| +/**
|
| + * @typedef {{
|
| + * label_id: string,
|
| + * visible: boolean,
|
| + * executable: boolean
|
| + * }}
|
| + */
|
| +importer.UpdateResponse;
|
| +
|
| +/** @enum {importer.UpdateResponse} */
|
| +importer.UpdateResponses = {
|
| + HIDDEN: {
|
| + label_id: 'CLOUD_IMPORT_BUTTON_LABEL',
|
| + visible: false,
|
| + executable: false
|
| + },
|
| + SCANNING: {
|
| + label_id: 'CLOUD_IMPORT_SCANNING_BUTTON_LABEL',
|
| + visible: true,
|
| + executable: false
|
| + },
|
| + EXECUTABLE: {
|
| + label_id: 'CLOUD_IMPORT_BUTTON_LABEL',
|
| + visible: true,
|
| + executable: true
|
| + }
|
| +};
|
| +
|
| +/**
|
| + * Class that orchestrates background activity and UI changes on
|
| + * behalf of Cloud Import.
|
| + *
|
| + * @constructor
|
| + * @struct
|
| + *
|
| + * @param {!importer.ControllerEnvironment} environment The class providing
|
| + * access to runtime environmental information, like the current directory,
|
| + * volume lookup and so-on.
|
| + * @param {!importer.MediaScanner} scanner
|
| + * @param {!importer.ImportRunner} importRunner
|
| + * @param {function()} commandUpdateHandler
|
| + */
|
| +importer.ImportController =
|
| + function(environment, scanner, importRunner, commandUpdateHandler) {
|
| +
|
| + /** @private {!importer.ControllerEnvironment} */
|
| + this.environment_ = environment;
|
| +
|
| + /** @private {!importer.ImportRunner} */
|
| + this.importRunner_ = importRunner;
|
| +
|
| + /** @private {!importer.MediaScanner} */
|
| + this.scanner_ = scanner;
|
| +
|
| + /** @private {function()} */
|
| + this.updateCommands_ = commandUpdateHandler;
|
| +
|
| + /** @private {!importer.ScanObserver} */
|
| + this.scanObserverBound_ = this.onScanEvent_.bind(this);
|
| +
|
| + this.scanner_.addObserver(this.scanObserverBound_);
|
| +
|
| + /** @private {!Object.<string, !importer.ScanResult>} */
|
| + this.directoryScans_ = {};
|
| +};
|
| +
|
| +/**
|
| + * @param {!importer.ScanEvent} event Command event.
|
| + * @param {importer.ScanResult} result
|
| + */
|
| +importer.ImportController.prototype.onScanEvent_ = function(event, result) {
|
| + // TODO(smckay): only do this if this is a directory scan.
|
| + if (event === importer.ScanEvent.FINALIZED) {
|
| + this.updateCommands_();
|
| + }
|
| +};
|
| +
|
| +/**
|
| + * Executes import against the current directory. Should only
|
| + * be called when the current directory has been validated
|
| + * by calling "update" on this class.
|
| + */
|
| +importer.ImportController.prototype.execute = function() {
|
| + metrics.recordEnum('CloudImport.UserAction', 'IMPORT_INITIATED');
|
| + var result = this.getScanForImport_();
|
| + this.importRunner_.importFromScanResult(result);
|
| +};
|
| +
|
| +/**
|
| + * @return {!importer.UpdateResponse} response
|
| + */
|
| +importer.ImportController.prototype.update = function() {
|
| +
|
| + // If there is no Google Drive mount, Drive may be disabled
|
| + // or the machine may be running in guest mode.
|
| + if (!this.environment_.isGoogleDriveMounted()) {
|
| + return importer.UpdateResponses.HIDDEN;
|
| + }
|
| +
|
| + var entries = this.environment_.getSelection();
|
| +
|
| + // Enabled if user has a selection and it consists entirely of files
|
| + // that:
|
| + // 1) are of a recognized media type
|
| + // 2) reside on a removable media device
|
| + // 3) in the DCIM dir
|
| + if (entries.length) {
|
| + if (entries.every(
|
| + importer.isEligibleEntry.bind(null, this.environment_))) {
|
| + // TODO(smckay): Include entry count in label.
|
| + return importer.UpdateResponses.EXECUTABLE;
|
| + }
|
| + } else if (this.isCurrentDirectoryScannable_()) {
|
| + var scan = this.getCurrentDirectoryScan_();
|
| + return scan.isFinal() ?
|
| + importer.UpdateResponses.EXECUTABLE :
|
| + importer.UpdateResponses.SCANNING;
|
| + }
|
| +
|
| + return importer.UpdateResponses.HIDDEN;
|
| +};
|
| +
|
| +/**
|
| + * @return {boolean} true if the current directory is scan eligible.
|
| + * @private
|
| + */
|
| +importer.ImportController.prototype.isCurrentDirectoryScannable_ =
|
| + function() {
|
| + var directory = this.environment_.getCurrentDirectory();
|
| + return !!directory &&
|
| + importer.isMediaDirectory(directory, this.environment_);
|
| +};
|
| +
|
| +/**
|
| + * Get or create scan for the current directory or file selection.
|
| + *
|
| + * @return {!importer.ScanResult} A scan result object that may be
|
| + * actively scanning.
|
| + * @private
|
| + */
|
| +importer.ImportController.prototype.getScanForImport_ = function() {
|
| + var entries = this.environment_.getSelection();
|
| +
|
| + if (entries.length) {
|
| + if (entries.every(
|
| + importer.isEligibleEntry.bind(null, this.environment_))) {
|
| + return this.scanner_.scan(entries);
|
| + }
|
| + } else {
|
| + return this.getCurrentDirectoryScan_();
|
| + }
|
| +};
|
| +
|
| +/**
|
| + * Get or create scan for the current directory.
|
| + *
|
| + * @return {!importer.ScanResult} A scan result object that may be
|
| + * actively scanning.
|
| + * @private
|
| + */
|
| +importer.ImportController.prototype.getCurrentDirectoryScan_ = function() {
|
| + console.assert(this.isCurrentDirectoryScannable_());
|
| + var directory = this.environment_.getCurrentDirectory();
|
| + var url = directory.toURL();
|
| + var scan = this.directoryScans_[url];
|
| + if (!scan) {
|
| + scan = this.scanner_.scan([directory]);
|
| + // TODO(smckay): evict scans when a device is unmounted or changed.
|
| + this.directoryScans_[url] = scan;
|
| + }
|
| + return scan;
|
| +};
|
| +
|
| +/**
|
| + * Interface abstracting away the concrete file manager available
|
| + * to commands. By hiding file manager we make it easy to test
|
| + * ImportController.
|
| + *
|
| + * @interface
|
| + * @extends {VolumeManagerCommon.VolumeInfoProvider}
|
| + */
|
| +importer.ControllerEnvironment = function() {};
|
| +
|
| +/**
|
| + * Returns the current file selection, if any. May be empty.
|
| + * @return {!Array.<!Entry>}
|
| + */
|
| +importer.ControllerEnvironment.prototype.getSelection;
|
| +
|
| +/**
|
| + * Returns the directory entry for the current directory.
|
| + * @return {!DirectoryEntry}
|
| + */
|
| +importer.ControllerEnvironment.prototype.getCurrentDirectory;
|
| +
|
| +/**
|
| + * Returns true if the Drive mount is present.
|
| + * @return {boolean}
|
| + */
|
| +importer.ControllerEnvironment.prototype.isGoogleDriveMounted;
|
| +
|
| +
|
| +/**
|
| + * Class providing access to various pieces of information in the
|
| + * FileManager environment, like the current directory, volumeinfo lookup
|
| + * By hiding file manager we make it easy to test importer.ImportController.
|
| + *
|
| + * @constructor
|
| + * @implements {importer.ControllerEnvironment}
|
| + *
|
| + * @param {!FileManager} fileManager
|
| + */
|
| +importer.RuntimeControllerEnvironment = function(fileManager) {
|
| + /** @private {!FileManager} */
|
| + this.fileManager_ = fileManager;
|
| +};
|
| +
|
| +/** @override */
|
| +importer.RuntimeControllerEnvironment.prototype.getSelection =
|
| + function() {
|
| + return this.fileManager_.getSelection().entries;
|
| +};
|
| +
|
| +/** @override */
|
| +importer.RuntimeControllerEnvironment.prototype.getCurrentDirectory =
|
| + function() {
|
| + return /** @type {!DirectoryEntry} */ (
|
| + this.fileManager_.getCurrentDirectoryEntry());
|
| +};
|
| +
|
| +/** @override */
|
| +importer.RuntimeControllerEnvironment.prototype.getVolumeInfo =
|
| + function(entry) {
|
| + return this.fileManager_.volumeManager.getVolumeInfo(entry);
|
| +};
|
| +
|
| +/** @override */
|
| +importer.RuntimeControllerEnvironment.prototype.isGoogleDriveMounted =
|
| + function() {
|
| + var drive = this.fileManager_.volumeManager.getCurrentProfileVolumeInfo(
|
| + VolumeManagerCommon.VolumeType.DRIVE);
|
| + return !!drive;
|
| +};
|
|
|