// Copyright (c) 2012 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.

/**
 * Represents each volume, such as "drive", "download directory", each "USB
 * flush storage", or "mounted zip archive" etc.
 *
 * @param {VolumeManagerCommon.VolumeType} volumeType The type of the volume.
 * @param {string} volumeId ID of the volume.
 * @param {FileSystem} fileSystem The file system object for this volume.
 * @param {(string|undefined)} error The error if an error is found.
 * @param {(string|undefined)} deviceType The type of device
 *     ('usb'|'sd'|'optical'|'mobile'|'unknown') (as defined in
 *     chromeos/disks/disk_mount_manager.cc). Can be undefined.
 * @param {(string|undefined)} devicePath Identifier of the device that the
 *     volume belongs to. Can be undefined.
 * @param {boolean} isReadOnly True if the volume is read only.
 * @param {!{displayName:string, isCurrentProfile:boolean}} profile Profile
 *     information.
 * @param {string} label Label of the volume.
 * @param {(string|undefined)} extensionId Id of the extension providing this
 *     volume. Empty for native volumes.
 * @constructor
 */
function VolumeInfo(
    volumeType,
    volumeId,
    fileSystem,
    error,
    deviceType,
    devicePath,
    isReadOnly,
    profile,
    label,
    extensionId) {
  this.volumeType_ = volumeType;
  this.volumeId_ = volumeId;
  this.fileSystem_ = fileSystem;
  this.label_ = label;
  this.displayRoot_ = null;
  this.fakeEntries_ = {};
  this.displayRoot_ = null;
  this.displayRootPromise_ = null;

  if (volumeType === VolumeManagerCommon.VolumeType.DRIVE) {
    // TODO(mtomasz): Convert fake entries to DirectoryProvider.
    this.fakeEntries_[VolumeManagerCommon.RootType.DRIVE_OFFLINE] = {
      isDirectory: true,
      rootType: VolumeManagerCommon.RootType.DRIVE_OFFLINE,
      toURL: function() { return 'fake-entry://drive_offline'; }
    };
    this.fakeEntries_[VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME] = {
      isDirectory: true,
      rootType: VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME,
      toURL: function() { return 'fake-entry://drive_shared_with_me'; }
    };
    this.fakeEntries_[VolumeManagerCommon.RootType.DRIVE_RECENT] = {
      isDirectory: true,
      rootType: VolumeManagerCommon.RootType.DRIVE_RECENT,
      toURL: function() { return 'fake-entry://drive_recent'; }
    };
  }

  // Note: This represents if the mounting of the volume is successfully done
  // or not. (If error is empty string, the mount is successfully done).
  // TODO(hidehiko): Rename to make this more understandable.
  this.error_ = error;
  this.deviceType_ = deviceType;
  this.devicePath_ = devicePath;
  this.isReadOnly_ = isReadOnly;
  this.profile_ = Object.freeze(profile);
  this.extensionId_ = extensionId;

  Object.seal(this);
}

VolumeInfo.prototype = {
  /**
   * @return {VolumeManagerCommon.VolumeType} Volume type.
   */
  get volumeType() {
    return this.volumeType_;
  },
  /**
   * @return {string} Volume ID.
   */
  get volumeId() {
    return this.volumeId_;
  },
  /**
   * @return {FileSystem} File system object.
   */
  get fileSystem() {
    return this.fileSystem_;
  },
  /**
   * @return {DirectoryEntry} Display root path. It is null before finishing to
   * resolve the entry.
   */
  get displayRoot() {
    return this.displayRoot_;
  },
  /**
   * @return {Object.<string, Object>} Fake entries.
   */
  get fakeEntries() {
    return this.fakeEntries_;
  },
  /**
   * @return {(string|undefined)} Error identifier.
   */
  get error() {
    return this.error_;
  },
  /**
   * @return {(string|undefined)} Device type identifier.
   */
  get deviceType() {
    return this.deviceType_;
  },
  /**
   * @return {(string|undefined)} Device identifier.
   */
  get devicePath() {
    return this.devicePath_;
  },
  /**
   * @return {boolean} Whether read only or not.
   */
  get isReadOnly() {
    return this.isReadOnly_;
  },
  /**
   * @return {!{displayName:string, isCurrentProfile:boolean}} Profile data.
   */
  get profile() {
    return this.profile_;
  },
  /**
   * @return {string} Label for the volume.
   */
  get label() {
    return this.label_;
  },
  /**
   * @return {(string|undefined)} Id of an extennsion providing this volume.
   */
  get extensionId() {
    return this.extensionId_;
  }
};

/**
 * Starts resolving the display root and obtains it.  It may take long time for
 * Drive. Once resolved, it is cached.
 *
 * @param {function(DirectoryEntry)=} opt_onSuccess Success callback with the
 *     display root directory as an argument.
 * @param {function(*)=} opt_onFailure Failure callback.
 * @return {Promise}
 */
VolumeInfo.prototype.resolveDisplayRoot = function(opt_onSuccess,
                                                   opt_onFailure) {
  if (!this.displayRootPromise_) {
    // TODO(mtomasz): Do not add VolumeInfo which failed to resolve root, and
    // remove this if logic. Call opt_onSuccess() always, instead.
    if (this.volumeType !== VolumeManagerCommon.VolumeType.DRIVE) {
      if (this.fileSystem_)
        this.displayRootPromise_ = Promise.resolve(this.fileSystem_.root);
      else
        this.displayRootPromise_ = Promise.reject(this.error);
    } else {
      // For Drive, we need to resolve.
      var displayRootURL = this.fileSystem_.root.toURL() + '/root';
      this.displayRootPromise_ = new Promise(
          window.webkitResolveLocalFileSystemURL.bind(null, displayRootURL));
    }

    // Store the obtained displayRoot.
    this.displayRootPromise_.then(function(displayRoot) {
      this.displayRoot_ = displayRoot;
    }.bind(this));
  }
  if (opt_onSuccess)
    this.displayRootPromise_.then(opt_onSuccess, opt_onFailure);
  return this.displayRootPromise_;
};

/**
 * Utilities for volume manager implementation.
 */
var volumeManagerUtil = {};

/**
 * Throws an Error when the given error is not in
 * VolumeManagerCommon.VolumeError.
 *
 * @param {string} error Status string usually received from APIs.
 */
volumeManagerUtil.validateError = function(error) {
  for (var key in VolumeManagerCommon.VolumeError) {
    if (error === VolumeManagerCommon.VolumeError[key])
      return;
  }

  throw new Error('Invalid mount error: ' + error);
};

/**
 * Builds the VolumeInfo data from VolumeMetadata.
 * @param {VolumeMetadata} volumeMetadata Metadata instance for the volume.
 * @param {function(VolumeInfo)} callback Called on completion.
 */
volumeManagerUtil.createVolumeInfo = function(volumeMetadata, callback) {
  var localizedLabel;
  switch (volumeMetadata.volumeType) {
    case VolumeManagerCommon.VolumeType.DOWNLOADS:
      localizedLabel = str('DOWNLOADS_DIRECTORY_LABEL');
      break;
    case VolumeManagerCommon.VolumeType.DRIVE:
      localizedLabel = str('DRIVE_DIRECTORY_LABEL');
      break;
    default:
      // TODO(mtomasz): Calculate volumeLabel for all types of volumes in the
      // C++ layer.
      localizedLabel = volumeMetadata.volumeLabel ||
          volumeMetadata.volumeId.split(':', 2)[1];
      break;
  }

  chrome.fileManagerPrivate.requestFileSystem(
      volumeMetadata.volumeId,
      function(fileSystem) {
        // TODO(mtomasz): chrome.runtime.lastError should have error reason.
        if (!fileSystem) {
          console.error('File system not found: ' + volumeMetadata.volumeId);
          callback(new VolumeInfo(
              /** @type {VolumeManagerCommon.VolumeType} */
              (volumeMetadata.volumeType),
              volumeMetadata.volumeId,
              null,  // File system is not found.
              volumeMetadata.mountCondition,
              volumeMetadata.deviceType,
              volumeMetadata.devicePath,
              volumeMetadata.isReadOnly,
              volumeMetadata.profile,
              localizedLabel,
              volumeMetadata.extensionId));
          return;
        }
        if (volumeMetadata.volumeType ==
            VolumeManagerCommon.VolumeType.DRIVE) {
          // After file system is mounted, we "read" drive grand root
          // entry at first. This triggers full feed fetch on background.
          // Note: we don't need to handle errors here, because even if
          // it fails, accessing to some path later will just become
          // a fast-fetch and it re-triggers full-feed fetch.
          fileSystem.root.createReader().readEntries(
              function() { /* do nothing */ },
              function(error) {
                console.error(
                    'Triggering full feed fetch is failed: ' + error.name);
              });
        }
        callback(new VolumeInfo(
            /** @type {VolumeManagerCommon.VolumeType} */
            (volumeMetadata.volumeType),
            volumeMetadata.volumeId,
            fileSystem,
            volumeMetadata.mountCondition,
            volumeMetadata.deviceType,
            volumeMetadata.devicePath,
            volumeMetadata.isReadOnly,
            volumeMetadata.profile,
            localizedLabel,
            volumeMetadata.extensionId));
      });
};

/**
 * The order of the volume list based on root type.
 * @type {Array.<VolumeManagerCommon.VolumeType>}
 * @const
 * @private
 */
volumeManagerUtil.volumeListOrder_ = [
  VolumeManagerCommon.VolumeType.DRIVE,
  VolumeManagerCommon.VolumeType.DOWNLOADS,
  VolumeManagerCommon.VolumeType.ARCHIVE,
  VolumeManagerCommon.VolumeType.REMOVABLE,
  VolumeManagerCommon.VolumeType.MTP,
  VolumeManagerCommon.VolumeType.PROVIDED,
  VolumeManagerCommon.VolumeType.CLOUD_DEVICE
];

/**
 * Orders two volumes by volumeType and volumeId.
 *
 * The volumes at first are compared by volume type in the order of
 * volumeListOrder_.  Then they are compared by volume ID.
 *
 * @param {!VolumeInfo} volumeInfo1 Volume info to be compared.
 * @param {!VolumeInfo} volumeInfo2 Volume info to be compared.
 * @return {number} Returns -1 if volume1 < volume2, returns 1 if volume2 >
 *     volume1, returns 0 if volume1 === volume2.
 * @private
 */
volumeManagerUtil.compareVolumeInfo_ = function(volumeInfo1, volumeInfo2) {
  var typeIndex1 =
      volumeManagerUtil.volumeListOrder_.indexOf(volumeInfo1.volumeType);
  var typeIndex2 =
      volumeManagerUtil.volumeListOrder_.indexOf(volumeInfo2.volumeType);
  if (typeIndex1 !== typeIndex2)
    return typeIndex1 < typeIndex2 ? -1 : 1;
  if (volumeInfo1.volumeId !== volumeInfo2.volumeId)
    return volumeInfo1.volumeId < volumeInfo2.volumeId ? -1 : 1;
  return 0;
};

/**
 * The container of the VolumeInfo for each mounted volume.
 * @constructor
 */
function VolumeInfoList() {
  var field = 'volumeType,volumeId';

  /**
   * Holds VolumeInfo instances.
   * @type {cr.ui.ArrayDataModel}
   * @private
   */
  this.model_ = new cr.ui.ArrayDataModel([]);
  this.model_.setCompareFunction(field,
                                 /** @type {function(*, *): number} */
                                 (volumeManagerUtil.compareVolumeInfo_));
  this.model_.sort(field, 'asc');

  Object.freeze(this);
}

VolumeInfoList.prototype = {
  get length() { return this.model_.length; }
};

/**
 * Adds the event listener to listen the change of volume info.
 * @param {string} type The name of the event.
 * @param {function(Event)} handler The handler for the event.
 */
VolumeInfoList.prototype.addEventListener = function(type, handler) {
  this.model_.addEventListener(type, handler);
};

/**
 * Removes the event listener.
 * @param {string} type The name of the event.
 * @param {function(Event)} handler The handler to be removed.
 */
VolumeInfoList.prototype.removeEventListener = function(type, handler) {
  this.model_.removeEventListener(type, handler);
};

/**
 * Adds the volumeInfo to the appropriate position. If there already exists,
 * just replaces it.
 * @param {VolumeInfo} volumeInfo The information of the new volume.
 */
VolumeInfoList.prototype.add = function(volumeInfo) {
  var index = this.findIndex(volumeInfo.volumeId);
  if (index !== -1)
    this.model_.splice(index, 1, volumeInfo);
  else
    this.model_.push(volumeInfo);
};

/**
 * Removes the VolumeInfo having the given ID.
 * @param {string} volumeId ID of the volume.
 */
VolumeInfoList.prototype.remove = function(volumeId) {
  var index = this.findIndex(volumeId);
  if (index !== -1)
    this.model_.splice(index, 1);
};

/**
 * Obtains an index from the volume ID.
 * @param {string} volumeId Volume ID.
 * @return {number} Index of the volume.
 */
VolumeInfoList.prototype.findIndex = function(volumeId) {
  for (var i = 0; i < this.model_.length; i++) {
    if (this.model_.item(i).volumeId === volumeId)
      return i;
  }
  return -1;
};

/**
 * Searches the information of the volume that contains the passed entry.
 * @param {Entry|Object} entry Entry on the volume to be found.
 * @return {VolumeInfo} The volume's information, or null if not found.
 */
VolumeInfoList.prototype.findByEntry = function(entry) {
  for (var i = 0; i < this.length; i++) {
    var volumeInfo = this.item(i);
    if (volumeInfo.fileSystem &&
        util.isSameFileSystem(volumeInfo.fileSystem, entry.filesystem)) {
      return volumeInfo;
    }
    // Additionally, check fake entries.
    for (var key in volumeInfo.fakeEntries_) {
      var fakeEntry = volumeInfo.fakeEntries_[key];
      if (util.isSameEntry(fakeEntry, entry))
        return volumeInfo;
    }
  }
  return null;
};

/**
 * @param {number} index The index of the volume in the list.
 * @return {!VolumeInfo} The VolumeInfo instance.
 */
VolumeInfoList.prototype.item = function(index) {
  return /** @type {!VolumeInfo} */ (this.model_.item(index));
};

/**
 * VolumeManager is responsible for tracking list of mounted volumes.
 *
 * @constructor
 * @extends {cr.EventTarget}
 */
function VolumeManager() {
  /**
   * The list of archives requested to mount. We will show contents once
   * archive is mounted, but only for mounts from within this filebrowser tab.
   * @type {Object.<string, Object>}
   * @private
   */
  this.requests_ = {};

  /**
   * The list of VolumeInfo instances for each mounted volume.
   * @type {VolumeInfoList}
   */
  this.volumeInfoList = new VolumeInfoList();

  /**
   * Queue for mounting.
   * @type {AsyncUtil.Queue}
   * @private
   */
  this.mountQueue_ = new AsyncUtil.Queue();

  // The status should be merged into VolumeManager.
  // TODO(hidehiko): Remove them after the migration.
  /**
   * Connection state of the Drive.
   * @type {VolumeManagerCommon.DriveConnectionState}
   * @private
   */
  this.driveConnectionState_ = {
    type: VolumeManagerCommon.DriveConnectionType.OFFLINE,
    reason: VolumeManagerCommon.DriveConnectionReason.NO_SERVICE,
    hasCellularNetworkAccess: false
  };

  chrome.fileManagerPrivate.onDriveConnectionStatusChanged.addListener(
      this.onDriveConnectionStatusChanged_.bind(this));
  this.onDriveConnectionStatusChanged_();
}

/**
 * Invoked when the drive connection status is changed.
 * @private
 */
VolumeManager.prototype.onDriveConnectionStatusChanged_ = function() {
  chrome.fileManagerPrivate.getDriveConnectionState(function(state) {
    this.driveConnectionState_ = state;
    cr.dispatchSimpleEvent(this, 'drive-connection-changed');
  }.bind(this));
};

/**
 * Returns the drive connection state.
 * @return {VolumeManagerCommon.DriveConnectionState} Connection state.
 */
VolumeManager.prototype.getDriveConnectionState = function() {
  return this.driveConnectionState_;
};

/**
 * VolumeManager extends cr.EventTarget.
 */
VolumeManager.prototype.__proto__ = cr.EventTarget.prototype;

/**
 * Time in milliseconds that we wait a response for. If no response on
 * mount/unmount received the request supposed failed.
 */
VolumeManager.TIMEOUT = 15 * 60 * 1000;

/**
 * The singleton instance of VolumeManager. Initialized by the first invocation
 * of getInstance().
 * @type {VolumeManager}
 * @private
 */
VolumeManager.instance_ = null;

/**
 * Returns instance of VolumeManager for debug purpose.
 * This method returns VolumeManager.instance_ which may not be initialized.
 *
 * @return {VolumeManager} Volume manager.
 */
VolumeManager.getInstanceForDebug = function() {
  return VolumeManager.instance_;
};

/**
 * @type {Promise}
 * @private
 */
VolumeManager.instancePromise_ = null;

/**
 * Returns the VolumeManager instance asynchronously. If it is not created or
 * under initialization, it will waits for the finish of the initialization.
 * @param {function(VolumeManager)=} opt_callback Called with the VolumeManager
 *     instance. TODO(hirono): Remove the callback and use Promise instead.
 * @return {Promise} Promise to be fulfilled with the volume manager.
 */
VolumeManager.getInstance = function(opt_callback) {
  if (!VolumeManager.instancePromise_) {
    VolumeManager.instance_ = new VolumeManager();
    VolumeManager.instancePromise_ = new Promise(function(fulfill) {
      VolumeManager.instance_.initialize_(function() {
        return fulfill(VolumeManager.instance_);
      });
    });
  }
  if (opt_callback)
    VolumeManager.instancePromise_.then(opt_callback);
  return VolumeManager.instancePromise_;
};

/**
 * Revokes the singleton instance for testing.
 */
VolumeManager.revokeInstanceForTesting = function() {
  VolumeManager.instancePromise_ = null;
  VolumeManager.instance_ = null;
}

/**
 * Initializes mount points.
 * @param {function()} callback Called upon the completion of the
 *     initialization.
 * @private
 */
VolumeManager.prototype.initialize_ = function(callback) {
  chrome.fileManagerPrivate.getVolumeMetadataList(function(volumeMetadataList) {
    // We must subscribe to the mount completed event in the callback of
    // getVolumeMetadataList. crbug.com/330061.
    // But volumes reported by onMountCompleted events must be added after the
    // 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++) {
        group.add(function(volumeMetadata, continueCallback) {
          volumeManagerUtil.createVolumeInfo(
              volumeMetadata,
              function(volumeInfo) {
                this.volumeInfoList.add(volumeInfo);
                if (volumeMetadata.volumeType ===
                    VolumeManagerCommon.VolumeType.DRIVE)
                  this.onDriveConnectionStatusChanged_();
                continueCallback();
              }.bind(this));
        }.bind(this, volumeMetadataList[i]));
      }
      group.run(function() {
        // Call the callback of the initialize function.
        callback();
        // Call the callback of AsyncQueue. Maybe it invokes callbacks
        // registered by mountCompleted events.
        inCallback();
      });
    }.bind(this));

    chrome.fileManagerPrivate.onMountCompleted.addListener(
        this.onMountCompleted_.bind(this));
  }.bind(this));
};

/**
 * Event handler called when some volume was mounted or unmounted.
 * @param {MountCompletedEvent} event Received event.
 * @private
 */
VolumeManager.prototype.onMountCompleted_ = function(event) {
  this.mountQueue_.run(function(callback) {
    switch (event.eventType) {
      case 'mount':
        var requestKey = this.makeRequestKey_(
            'mount',
            event.volumeMetadata.sourcePath);

        if (event.status === 'success' ||
            event.status ===
                VolumeManagerCommon.VolumeError.UNKNOWN_FILESYSTEM ||
            event.status ===
                VolumeManagerCommon.VolumeError.UNSUPPORTED_FILESYSTEM) {
          volumeManagerUtil.createVolumeInfo(
              event.volumeMetadata,
              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 {
          console.warn('Failed to mount a volume: ' + event.status);
          this.finishRequest_(requestKey, event.status);
          callback();
        }
        break;

      case 'unmount':
        var volumeId = event.volumeMetadata.volumeId;
        var status = event.status;
        if (status === VolumeManagerCommon.VolumeError.PATH_UNMOUNTED) {
          console.warn('Volume already unmounted: ', volumeId);
          status = 'success';
        }
        var requestKey = this.makeRequestKey_('unmount', volumeId);
        var requested = requestKey in this.requests_;
        var volumeInfoIndex =
            this.volumeInfoList.findIndex(volumeId);
        var volumeInfo = volumeInfoIndex !== -1 ?
            this.volumeInfoList.item(volumeInfoIndex) : null;
        if (event.status === 'success' && !requested && volumeInfo) {
          console.warn('Mounted volume without a request: ' + volumeId);
          var e = new Event('externally-unmounted');
          e.volumeInfo = volumeInfo;
          this.dispatchEvent(e);
        }

        this.finishRequest_(requestKey, status);
        if (event.status === 'success')
          this.volumeInfoList.remove(event.volumeMetadata.volumeId);
        callback();
        break;
    }
  }.bind(this));
};

/**
 * Creates string to match mount events with requests.
 * @param {string} requestType 'mount' | 'unmount'. TODO(hidehiko): Replace by
 *     enum.
 * @param {string} argument Argument describing the request, eg. source file
 *     path of the archive to be mounted, or a volumeId for unmounting.
 * @return {string} Key for |this.requests_|.
 * @private
 */
VolumeManager.prototype.makeRequestKey_ = function(requestType, argument) {
  return requestType + ':' + argument;
};

/**
 * @param {string} fileUrl File url to the archive file.
 * @param {function(VolumeInfo)} successCallback Success callback.
 * @param {function(VolumeManagerCommon.VolumeError)} errorCallback Error
 *     callback.
 */
VolumeManager.prototype.mountArchive = function(
    fileUrl, successCallback, errorCallback) {
  chrome.fileManagerPrivate.addMount(fileUrl, function(sourcePath) {
    console.info(
        'Mount request: url=' + fileUrl + '; sourcePath=' + sourcePath);
    var requestKey = this.makeRequestKey_('mount', sourcePath);
    this.startRequest_(requestKey, successCallback, errorCallback);
  }.bind(this));
};

/**
 * Unmounts volume.
 * @param {!VolumeInfo} volumeInfo Volume to be unmounted.
 * @param {function()} successCallback Success callback.
 * @param {function(VolumeManagerCommon.VolumeError)} errorCallback Error
 *     callback.
 */
VolumeManager.prototype.unmount = function(volumeInfo,
                                           successCallback,
                                           errorCallback) {
  chrome.fileManagerPrivate.removeMount(volumeInfo.volumeId);
  var requestKey = this.makeRequestKey_('unmount', volumeInfo.volumeId);
  this.startRequest_(requestKey, successCallback, errorCallback);
};

/**
 * Obtains a volume info containing the passed entry.
 * @param {Entry|Object} entry Entry on the volume to be returned. Can be fake.
 * @return {VolumeInfo} The VolumeInfo instance or null if not found.
 */
VolumeManager.prototype.getVolumeInfo = function(entry) {
  return this.volumeInfoList.findByEntry(entry);
};

/**
 * Obtains volume information of the current profile.
 *
 * @param {VolumeManagerCommon.VolumeType} volumeType Volume type.
 * @return {VolumeInfo} Volume info.
 */
VolumeManager.prototype.getCurrentProfileVolumeInfo = function(volumeType) {
  for (var i = 0; i < this.volumeInfoList.length; i++) {
    var volumeInfo = this.volumeInfoList.item(i);
    if (volumeInfo.profile.isCurrentProfile &&
        volumeInfo.volumeType === volumeType)
      return volumeInfo;
  }
  return null;
};

/**
 * Obtains location information from an entry.
 *
 * @param {Entry|Object} entry File or directory entry. It can be a fake entry.
 * @return {EntryLocation} Location information.
 */
VolumeManager.prototype.getLocationInfo = function(entry) {
  var volumeInfo = this.volumeInfoList.findByEntry(entry);
  if (!volumeInfo)
    return null;

  if (util.isFakeEntry(entry)) {
    return new EntryLocation(
        volumeInfo,
        entry.rootType,
        true /* the entry points a root directory. */,
        true /* fake entries are read only. */);
  }

  var rootType;
  var isReadOnly;
  var isRootEntry;
  if (volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DRIVE) {
    // For Drive, the roots are /root and /other, instead of /. Root URLs
    // contain trailing slashes.
    if (entry.fullPath == '/root' || entry.fullPath.indexOf('/root/') === 0) {
      rootType = VolumeManagerCommon.RootType.DRIVE;
      isReadOnly = volumeInfo.isReadOnly;
      isRootEntry = entry.fullPath === '/root';
    } else if (entry.fullPath == '/other' ||
               entry.fullPath.indexOf('/other/') === 0) {
      rootType = VolumeManagerCommon.RootType.DRIVE_OTHER;
      isReadOnly = true;
      isRootEntry = entry.fullPath === '/other';
    } else {
      // Accessing Drive files outside of /drive/root and /drive/other is not
      // allowed, but can happen. Therefore returning null.
      return null;
    }
  } else {
    switch (volumeInfo.volumeType) {
      case VolumeManagerCommon.VolumeType.DOWNLOADS:
        rootType = VolumeManagerCommon.RootType.DOWNLOADS;
        break;
      case VolumeManagerCommon.VolumeType.REMOVABLE:
        rootType = VolumeManagerCommon.RootType.REMOVABLE;
        break;
      case VolumeManagerCommon.VolumeType.ARCHIVE:
        rootType = VolumeManagerCommon.RootType.ARCHIVE;
        break;
      case VolumeManagerCommon.VolumeType.CLOUD_DEVICE:
        rootType = VolumeManagerCommon.RootType.CLOUD_DEVICE;
        break;
      case VolumeManagerCommon.VolumeType.MTP:
        rootType = VolumeManagerCommon.RootType.MTP;
        break;
      case VolumeManagerCommon.VolumeType.PROVIDED:
        rootType = VolumeManagerCommon.RootType.PROVIDED;
        break;
      default:
        // Programming error, throw an exception.
        throw new Error('Invalid volume type: ' + volumeInfo.volumeType);
    }
    isReadOnly = volumeInfo.isReadOnly;
    isRootEntry = util.isSameEntry(entry, volumeInfo.fileSystem.root);
  }

  return new EntryLocation(volumeInfo, rootType, isRootEntry, isReadOnly);
};

/**
 * @param {string} key Key produced by |makeRequestKey_|.
 * @param {function(VolumeInfo)} successCallback To be called when the request
 *     finishes successfully.
 * @param {function(VolumeManagerCommon.VolumeError)} errorCallback To be called
 *     when the request fails.
 * @private
 */
VolumeManager.prototype.startRequest_ = function(key,
    successCallback, errorCallback) {
  if (key in this.requests_) {
    var request = this.requests_[key];
    request.successCallbacks.push(successCallback);
    request.errorCallbacks.push(errorCallback);
  } else {
    this.requests_[key] = {
      successCallbacks: [successCallback],
      errorCallbacks: [errorCallback],

      timeout: setTimeout(this.onTimeout_.bind(this, key),
                          VolumeManager.TIMEOUT)
    };
  }
};

/**
 * Called if no response received in |TIMEOUT|.
 * @param {string} key Key produced by |makeRequestKey_|.
 * @private
 */
VolumeManager.prototype.onTimeout_ = function(key) {
  this.invokeRequestCallbacks_(this.requests_[key],
                               VolumeManagerCommon.VolumeError.TIMEOUT);
  delete this.requests_[key];
};

/**
 * @param {string} key Key produced by |makeRequestKey_|.
 * @param {VolumeManagerCommon.VolumeError|string} status Status received
 *     from the API.
 * @param {VolumeInfo=} opt_volumeInfo Volume info of the mounted volume.
 * @private
 */
VolumeManager.prototype.finishRequest_ = function(key, status, opt_volumeInfo) {
  var request = this.requests_[key];
  if (!request)
    return;

  clearTimeout(request.timeout);
  this.invokeRequestCallbacks_(request, status, opt_volumeInfo);
  delete this.requests_[key];
};

/**
 * @param {Object} request Structure created in |startRequest_|.
 * @param {VolumeManagerCommon.VolumeError|string} status If status ===
 *     'success' success callbacks are called.
 * @param {VolumeInfo=} opt_volumeInfo Volume info of the mounted volume.
 * @private
 */
VolumeManager.prototype.invokeRequestCallbacks_ = function(
    request, status, opt_volumeInfo) {
  var callEach = function(callbacks, self, args) {
    for (var i = 0; i < callbacks.length; i++) {
      callbacks[i].apply(self, args);
    }
  };
  if (status === 'success') {
    callEach(request.successCallbacks, this, [opt_volumeInfo]);
  } else {
    volumeManagerUtil.validateError(status);
    callEach(request.errorCallbacks, this, [status]);
  }
};

/**
 * Returns current state of VolumeManager.
 * @return {string} Current state of VolumeManager.
 */
VolumeManager.prototype.toString = function() {
  return 'VolumeManager\n' +
      '- MountQueue_:\n' +
      '  ' + this.mountQueue_.toString().replace(/\n/g, '\n  ');
};

/**
 * Location information which shows where the path points in FileManager's
 * file system.
 *
 * @param {!VolumeInfo} volumeInfo Volume information.
 * @param {VolumeManagerCommon.RootType} rootType Root type.
 * @param {boolean} isRootEntry Whether the entry is root entry or not.
 * @param {boolean} isReadOnly Whether the entry is read only or not.
 * @constructor
 */
function EntryLocation(volumeInfo, rootType, isRootEntry, isReadOnly) {
  /**
   * Volume information.
   * @type {!VolumeInfo}
   */
  this.volumeInfo = volumeInfo;

  /**
   * Root type.
   * @type {VolumeManagerCommon.RootType}
   */
  this.rootType = rootType;

  /**
   * Whether the entry is root entry or not.
   * @type {boolean}
   */
  this.isRootEntry = isRootEntry;

  /**
   * Whether the location obtained from the fake entry correspond to special
   * searches.
   * @type {boolean}
   */
  this.isSpecialSearchRoot =
      this.rootType === VolumeManagerCommon.RootType.DRIVE_OFFLINE ||
      this.rootType === VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME ||
      this.rootType === VolumeManagerCommon.RootType.DRIVE_RECENT;

  /**
   * Whether the location is under Google Drive or a special search root which
   * represents a special search from Google Drive.
   * @type {boolean}
   */
  this.isDriveBased =
      this.rootType === VolumeManagerCommon.RootType.DRIVE ||
      this.rootType === VolumeManagerCommon.RootType.DRIVE_OTHER ||
      this.rootType === VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME ||
      this.rootType === VolumeManagerCommon.RootType.DRIVE_RECENT ||
      this.rootType === VolumeManagerCommon.RootType.DRIVE_OFFLINE;

  /**
   * Whether the given path can be a target path of folder shortcut.
   * @type {boolean}
   */
  this.isEligibleForFolderShortcut =
      !this.isSpecialSearchRoot &&
      !this.isRootEntry &&
      this.isDriveBased;

  /**
   * Whether the entry is read only or not.
   * @type {boolean}
   */
  this.isReadOnly = isReadOnly;

  Object.freeze(this);
}
