// 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.

'use strict';

/**
 * This variable is checked in SelectFileDialogExtensionBrowserTest.
 * @type {number}
 */
window.JSErrorCount = 0;

/**
 * Count uncaught exceptions.
 */
window.onerror = function() { window.JSErrorCount++; };

/**
 * FileManager constructor.
 *
 * FileManager objects encapsulate the functionality of the file selector
 * dialogs, as well as the full screen file manager application (though the
 * latter is not yet implemented).
 *
 * @constructor
 */
function FileManager() {
  this.initializeQueue_ = new AsyncUtil.Group();
}

/**
 * Maximum delay in milliseconds for updating thumbnails in the bottom panel
 * to mitigate flickering. If images load faster then the delay they replace
 * old images smoothly. On the other hand we don't want to keep old images
 * too long.
 *
 * @type {number}
 * @const
 */
FileManager.THUMBNAIL_SHOW_DELAY = 100;

FileManager.prototype = {
  __proto__: cr.EventTarget.prototype
};

/**
 * Unload the file manager.
 * Used by background.js (when running in the packaged mode).
 */
function unload() {
  fileManager.onBeforeUnload_();
  fileManager.onUnload_();
}

/**
 * List of dialog types.
 *
 * Keep this in sync with FileManagerDialog::GetDialogTypeAsString, except
 * FULL_PAGE which is specific to this code.
 *
 * @enum {string}
 */
var DialogType = {
  SELECT_FOLDER: 'folder',
  SELECT_UPLOAD_FOLDER: 'upload-folder',
  SELECT_SAVEAS_FILE: 'saveas-file',
  SELECT_OPEN_FILE: 'open-file',
  SELECT_OPEN_MULTI_FILE: 'open-multi-file',
  FULL_PAGE: 'full-page'
};

/**
 * TextMeasure constructor.
 *
 * TextMeasure is a measure for text that returns the width of text.  This
 * class has a dummy span element. When measuring the width of text, it sets
 * the text to the element and obtains the element's size by
 * getBoundingClientRect.
 *
 * @constructor
 * @param {HTMLElement} element Element that has styles of measured text. The
 *     width of text is mesures like as it is rendered in this element.
 */
var TextMeasure = function(element) {
  var doc = element.ownerDocument;
  this.dummySpan_ = doc.createElement('span');
  this.dummySpan_ = doc.getElementsByTagName('body')[0].
                        appendChild(this.dummySpan_);
  this.dummySpan_.style.position = 'absolute';
  this.dummySpan_.style.visibility = 'hidden';
  var styles = window.getComputedStyle(element, '');
  var stylesToBeCopied = [
    'fontSize',
    'fontStyle',
    'fontWeight',
    'fontFamily',
    'letterSpacing'
  ];
  for (var i = 0; i < stylesToBeCopied.length; i++) {
    this.dummySpan_.style[stylesToBeCopied[i]] = styles[stylesToBeCopied[i]];
  }
};

/**
 * Measures the widht of text.
 *
 * @param {string} text Text that is measured the width.
 * @return {number} Width of the specified text.
 */
TextMeasure.prototype.getWidth = function(text) {
  this.dummySpan_.innerText = text;
  var rect = this.dummySpan_.getBoundingClientRect();
  return rect ? rect.width : 0;
};

/**
 * @param {string} type Dialog type.
 * @return {boolean} Whether the type is modal.
 */
DialogType.isModal = function(type) {
  return type == DialogType.SELECT_FOLDER ||
      type == DialogType.SELECT_UPLOAD_FOLDER ||
      type == DialogType.SELECT_SAVEAS_FILE ||
      type == DialogType.SELECT_OPEN_FILE ||
      type == DialogType.SELECT_OPEN_MULTI_FILE;
};

/**
 * Bottom magrin of the list and tree for transparent preview panel.
 * @const
 */
var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52;

// Anonymous "namespace".
(function() {

  // Private variables and helper functions.

  /**
   * Location of the page to buy more storage for Google Drive.
   */
  FileManager.GOOGLE_DRIVE_BUY_STORAGE =
      'https://www.google.com/settings/storage';

  /**
   * Location of Google Drive specific help.
   */
  FileManager.GOOGLE_DRIVE_HELP =
      'https://support.google.com/chromeos/?p=filemanager_drivehelp';

  /**
   * Location of Google Drive specific help.
   */
  FileManager.GOOGLE_DRIVE_ROOT = 'https://drive.google.com';

  /**
   * Location of Files App specific help.
   */
  FileManager.FILES_APP_HELP =
      'https://support.google.com/chromeos/?p=gsg_files_app';

  /**
   * Number of milliseconds in a day.
   */
  var MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000;

  /**
   * Some UI elements react on a single click and standard double click handling
   * leads to confusing results. We ignore a second click if it comes soon
   * after the first.
   */
  var DOUBLE_CLICK_TIMEOUT = 200;

  var removeChildren = function(element) {
    element.textContent = '';
  };

  /**
   * Update the elemenst to display the information about remainig space for
   * the storage.
   * @param {!Element} spaceInnerBar Block element for a percentage bar
   *                                 representing the remaining space.
   * @param {!Element} spaceInfoLabel Inline element to contain the message.
   * @param {!Element} spaceOuterBar Block element around the percentage bar.
   */
   var updateSpaceInfo = function(
      sizeStatsResult, spaceInnerBar, spaceInfoLabel, spaceOuterBar) {
    spaceInnerBar.removeAttribute('pending');
    if (sizeStatsResult) {
      var sizeStr = util.bytesToString(sizeStatsResult.remainingSize);
      spaceInfoLabel.textContent = strf('SPACE_AVAILABLE', sizeStr);

      var usedSpace =
          sizeStatsResult.totalSize - sizeStatsResult.remainingSize;
      spaceInnerBar.style.width =
          (100 * usedSpace / sizeStatsResult.totalSize) + '%';

      spaceOuterBar.hidden = false;
    } else {
      spaceOuterBar.hidden = true;
      spaceInfoLabel.textContent = str('FAILED_SPACE_INFO');
    }
  };

  // Public statics.

  FileManager.ListType = {
    DETAIL: 'detail',
    THUMBNAIL: 'thumb'
  };

  FileManager.prototype.initPreferences_ = function(callback) {
    var group = new AsyncUtil.Group();

    // DRIVE preferences should be initialized before creating DirectoryModel
    // to rebuild the roots list.
    group.add(this.getPreferences_.bind(this));

    // Get startup preferences.
    this.viewOptions_ = {};
    group.add(function(done) {
      this.dialogType = this.params_.type || DialogType.FULL_PAGE;
      this.startupPrefName_ = 'file-manager-' + this.dialogType;
      util.platform.getPreference(this.startupPrefName_, function(value) {
        // Load the global default options.
        try {
          this.viewOptions_ = JSON.parse(value);
        } catch (ignore) {}
        // Override with window-specific options.
        if (window.appState && window.appState.viewOptions) {
          for (var key in window.appState.viewOptions) {
            if (window.appState.viewOptions.hasOwnProperty(key))
              this.viewOptions_[key] = window.appState.viewOptions[key];
          }
        }
        done();
      }.bind(this));
    }.bind(this));

    // Get the command line option.
    group.add(function(done) {
      chrome.commandLinePrivate.hasSwitch(
          'file-manager-show-checkboxes', function(flag) {
        this.showCheckboxes_ = flag;
        done();
      }.bind(this));
    }.bind(this));

    // Removes the user data which is no longer used.
    // TODO(yoshiki): Remove this in M31 http://crbug.com/268784/
    chrome.storage.local.remove('folder-shortcuts-list');

    group.run(callback);
  };

  /**
   * Request local file system, resolve roots and init_ after that.
   * Warning, you can't use DOM nor any external scripts here, since it may not
   * be loaded yet. Functions in util.* and metrics.* are available and can
   * be used.
   *
   * @param {function()} callback Completion callback.
   * @private
   */
  FileManager.prototype.initFileSystem_ = function(callback) {
    util.installFileErrorToString();

    metrics.startInterval('Load.FileSystem');
    chrome.fileBrowserPrivate.requestFileSystem(function(filesystem) {
      metrics.recordInterval('Load.FileSystem');
      this.filesystem_ = filesystem;
      callback();
    }.bind(this));

    // Mount Drive if enabled.
    if (this.isDriveEnabled())
      this.volumeManager_.mountDrive(function() {}, function() {});
  };

  /**
   * One time initialization for the file system and related things.
   *
   * @param {function()} callback Completion callback.
   * @private
   */
  FileManager.prototype.initFileSystemUI_ = function(callback) {
    this.table_.startBatchUpdates();
    this.grid_.startBatchUpdates();

    this.initFileList_();
    this.setupCurrentDirectory_(true /* page loading */);

    // PyAuto tests monitor this state by polling this variable
    this.__defineGetter__('workerInitialized_', function() {
       return this.metadataCache_.isInitialized();
    }.bind(this));

    this.initDateTimeFormatters_();

    var self = this;

    // Get the 'allowRedeemOffers' preference before launching
    // FileListBannerController.
    this.getPreferences_(function(pref) {
      /** @type {boolean} */
      var showOffers = pref['allowRedeemOffers'];
      self.bannersController_ = new FileListBannerController(
          self.directoryModel_, self.volumeManager_, self.document_,
          showOffers);
      self.bannersController_.addEventListener('relayout',
                                               self.onResize_.bind(self));
    });

    var dm = this.directoryModel_;
    dm.addEventListener('directory-changed',
                        this.onDirectoryChanged_.bind(this));
    dm.addEventListener('begin-update-files', function() {
      self.currentList_.startBatchUpdates();
    });
    dm.addEventListener('end-update-files', function() {
      self.restoreItemBeingRenamed_();
      self.currentList_.endBatchUpdates();
    });
    dm.addEventListener('scan-started', this.onScanStarted_.bind(this));
    dm.addEventListener('scan-completed', this.onScanCompleted_.bind(this));
    dm.addEventListener('scan-failed', this.onScanCancelled_.bind(this));
    dm.addEventListener('scan-cancelled', this.onScanCancelled_.bind(this));
    dm.addEventListener('scan-updated', this.onScanUpdated_.bind(this));
    dm.addEventListener('rescan-completed',
                        this.refreshCurrentDirectoryMetadata_.bind(this));

    /**
     * If |item| in |parentView| is behind the preview panel, scrolls up the
     * parent view and make the item visible.
     *
     * @param {HTMLElement} item Item to be visible in the parent.
     * @param {HTMLElement} parentView View contains |selectedItem|.
     */
    var ensureItemNotBehindPreviewPanel = function(item, parentView) {
      var itemRect = item.getBoundingClientRect();
      if (!itemRect)
        return;
      var itemBottom = itemRect.bottom;

      var previewPanel = this.dialogDom_.querySelector('.preview-panel');
      var previewPanelRects = previewPanel.getBoundingClientRect();
      var panelHeight = previewPanelRects ? previewPanelRects.height : 0;

      var listRect = parentView.getBoundingClientRect();
      if (!listRect)
        return;
      var listBottom = listRect.bottom - panelHeight;

      if (itemBottom > listBottom) {
        var scrollOffset = itemBottom - listBottom;
        parentView.scrollTop += scrollOffset;
      }
    }.bind(this);

    var sm = this.directoryModel_.getFileListSelection();
    sm.addEventListener('change', function() {
      if (sm.selectedIndexes.length != 1)
        return;
      var view = (this.listType_ == FileManager.ListType.DETAIL) ?
          this.table_.list : this.grid_;
      var selectedItem = view.getListItemByIndex(sm.selectedIndex);
      if (!selectedItem)
        return;
      ensureItemNotBehindPreviewPanel(selectedItem, view);
    }.bind(this));

    this.directoryTree_.addEventListener('change', function() {
      var selectedSubTree = this.directoryTree_.selectedItem;
      if (!selectedSubTree)
        return;
      var selectedItem = selectedSubTree.rowElement;
      ensureItemNotBehindPreviewPanel(selectedItem, this.directoryTree_);
    }.bind(this));

    var stateChangeHandler =
        this.onPreferencesChanged_.bind(this);
    chrome.fileBrowserPrivate.onPreferencesChanged.addListener(
        stateChangeHandler);
    stateChangeHandler();

    var driveConnectionChangedHandler =
        this.onDriveConnectionChanged_.bind(this);
    this.volumeManager_.addEventListener('drive-connection-changed',
        driveConnectionChangedHandler);
    driveConnectionChangedHandler();

    // Set the initial focus and set it as a fallback.
    this.document_.addEventListener('focusout', function(e) {
      if (!e.relatedTarget)
        setTimeout(this.refocus.bind(this), 0);
    }.bind(this));
    this.refocus();

    this.initDataTransferOperations_();

    this.initContextMenus_();
    this.initCommands_();

    this.updateFileTypeFilter_();

    this.selectionHandler_.onFileSelectionChanged();

    this.table_.endBatchUpdates();
    this.grid_.endBatchUpdates();

    callback();
  };

  /**
   * @private
   */
  FileManager.prototype.initDateTimeFormatters_ = function() {
    var use12hourClock = !this.preferences_['use24hourClock'];
    this.table_.setDateTimeFormat(use12hourClock);
  };

  /**
   * @private
   */
  FileManager.prototype.initDataTransferOperations_ = function() {
    this.copyManager_ = new FileCopyManagerWrapper.getInstance();

    this.butterBar_ = new ButterBar(this.dialogDom_, this.copyManager_);

    // CopyManager and ButterBar are required for 'Delete' operation in
    // Open and Save dialogs. But drag-n-drop and copy-paste are not needed.
    if (this.dialogType != DialogType.FULL_PAGE) return;

    // TODO(hidehiko): Extract FileCopyManager related code from FileManager
    // to simplify it.
    this.onCopyProgressBound_ = this.onCopyProgress_.bind(this);
    this.copyManager_.addEventListener(
        'copy-progress', this.onCopyProgressBound_);

    this.onCopyManagerEntryChangedBound_ =
        this.onCopyManagerEntryChanged_.bind(this);
    this.copyManager_.addEventListener(
        'entry-changed', this.onCopyManagerEntryChangedBound_);

    var controller = this.fileTransferController_ =
        new FileTransferController(this.document_,
                                   this.copyManager_,
                                   this.metadataCache_,
                                   this.directoryModel_);
    controller.attachDragSource(this.table_.list);
    controller.attachFileListDropTarget(this.table_.list);
    controller.attachDragSource(this.grid_);
    controller.attachFileListDropTarget(this.grid_);
    controller.attachTreeDropTarget(this.directoryTree_);
    controller.attachNavigationListDropTarget(this.navigationList_, true);
    controller.attachCopyPasteHandlers();
    controller.addEventListener('selection-copied',
        this.blinkSelection.bind(this));
    controller.addEventListener('selection-cut',
        this.blinkSelection.bind(this));
  };

  /**
   * One-time initialization of context menus.
   * @private
   */
  FileManager.prototype.initContextMenus_ = function() {
    this.fileContextMenu_ = this.dialogDom_.querySelector('#file-context-menu');
    cr.ui.Menu.decorate(this.fileContextMenu_);

    cr.ui.contextMenuHandler.setContextMenu(this.grid_, this.fileContextMenu_);
    cr.ui.contextMenuHandler.setContextMenu(this.table_.querySelector('.list'),
        this.fileContextMenu_);
    cr.ui.contextMenuHandler.setContextMenu(
        this.document_.querySelector('.drive-welcome.page'),
        this.fileContextMenu_);

    this.rootsContextMenu_ =
        this.dialogDom_.querySelector('#roots-context-menu');
    cr.ui.Menu.decorate(this.rootsContextMenu_);
    this.navigationList_.setContextMenu(this.rootsContextMenu_);

    this.directoryTreeContextMenu_ =
        this.dialogDom_.querySelector('#directory-tree-context-menu');
    cr.ui.Menu.decorate(this.directoryTreeContextMenu_);
    this.directoryTree_.contextMenuForSubitems = this.directoryTreeContextMenu_;

    this.textContextMenu_ =
        this.dialogDom_.querySelector('#text-context-menu');
    cr.ui.Menu.decorate(this.textContextMenu_);

    this.gearButton_ = this.dialogDom_.querySelector('#gear-button');
    this.gearButton_.addEventListener('menushow',
        this.refreshRemainingSpace_.bind(this,
                                         false /* Without loading caption. */));
    this.dialogDom_.querySelector('#gear-menu').menuItemSelector =
      'menuitem, hr';
    cr.ui.decorate(this.gearButton_, cr.ui.MenuButton);

    if (this.dialogType == DialogType.FULL_PAGE) {
      var maximizeButton = this.dialogDom_.querySelector('#maximize-button');
      maximizeButton.addEventListener('click', this.onMaximize.bind(this));

      var closeButton = this.dialogDom_.querySelector('#close-button');
      closeButton.addEventListener('click', this.onClose.bind(this));
    }

    this.syncButton.checkable = true;
    this.hostedButton.checkable = true;
    this.detailViewButton_.checkable = true;
    this.thumbnailViewButton_.checkable = true;

    if (util.platform.runningInBrowser()) {
      // Supresses the default context menu.
      this.dialogDom_.addEventListener('contextmenu', function(e) {
        e.preventDefault();
        e.stopPropagation();
      });
    }
  };

  FileManager.prototype.onMaximize = function() {
    // Do not maximize when running via chrome://files in a browser.
    if (util.platform.runningInBrowser())
      return;

    var appWindow = chrome.app.window.current();
    if (appWindow.isMaximized())
      appWindow.restore();
    else
      appWindow.maximize();
  };

  FileManager.prototype.onClose = function() {
    // Do not close when running via chrome://files in a browser.
    if (util.platform.runningInBrowser())
      return;

    window.close();
  };

  /**
   * One-time initialization of commands.
   * @private
   */
  FileManager.prototype.initCommands_ = function() {
    var commandButtons = this.dialogDom_.querySelectorAll('button[command]');
    for (var j = 0; j < commandButtons.length; j++)
      CommandButton.decorate(commandButtons[j]);

    // TODO(dzvorygin): Here we use this hack, since 'hidden' is standard
    // attribute and we can't use it's setter as usual.
    cr.ui.Command.prototype.setHidden = function(value) {
      this.__lookupSetter__('hidden').call(this, value);
    };

    var commands = this.dialogDom_.querySelectorAll('command');
    for (var i = 0; i < commands.length; i++)
      cr.ui.Command.decorate(commands[i]);

    var doc = this.document_;

    CommandUtil.registerCommand(this.dialogContainer_, 'newfolder',
        Commands.newFolderCommand, this, this.directoryModel_);

    CommandUtil.registerCommand(this.dialogContainer_, 'newwindow',
        Commands.newWindowCommand, this, this.directoryModel_);

    CommandUtil.registerCommand(this.dialogContainer_, 'change-default-app',
        Commands.changeDefaultAppCommand, this);

    CommandUtil.registerCommand(this.navigationList_, 'unmount',
        Commands.unmountCommand, this);

    CommandUtil.registerCommand(this.navigationList_, 'import-photos',
        Commands.importCommand, this.navigationList_);

    CommandUtil.registerCommand(this.dialogContainer_, 'format',
        Commands.formatCommand, this,
        this.directoryModel_);

    CommandUtil.registerCommand(this.dialogContainer_, 'delete',
        Commands.deleteFileCommand, this);

    CommandUtil.registerCommand(this.dialogContainer_, 'rename',
        Commands.renameFileCommand, this);

    CommandUtil.registerCommand(this.dialogContainer_, 'volume-help',
        Commands.volumeHelpCommand, this);

    CommandUtil.registerCommand(this.dialogContainer_, 'drive-buy-more-space',
        Commands.driveBuySpaceCommand, this);

    CommandUtil.registerCommand(this.dialogContainer_,
        'drive-clear-local-cache', Commands.driveClearCacheCommand, this);

    CommandUtil.registerCommand(this.dialogContainer_, 'drive-go-to-drive',
        Commands.driveGoToDriveCommand, this);

    CommandUtil.registerCommand(this.dialogContainer_, 'paste',
        Commands.pasteFileCommand, doc, this.fileTransferController_);

    CommandUtil.registerCommand(this.dialogContainer_, 'open-with',
        Commands.openWithCommand, this);

    CommandUtil.registerCommand(this.dialogContainer_, 'toggle-pinned',
        Commands.togglePinnedCommand, this);

    CommandUtil.registerCommand(this.dialogContainer_, 'zip-selection',
        Commands.zipSelectionCommand, this, this.directoryModel_);

    CommandUtil.registerCommand(this.dialogContainer_, 'share',
        Commands.shareCommand, this);

    CommandUtil.registerCommand(this.dialogContainer_,
        'create-folder-shortcut', Commands.createFolderShortcutCommand, this);

    CommandUtil.registerCommand(this.dialogContainer_,
        'remove-folder-shortcut', Commands.removeFolderShortcutCommand, this);

    CommandUtil.registerCommand(this.dialogContainer_, 'search',
        Commands.searchCommand, this,
        this.dialogDom_.querySelector('#search-box'));

    // Register commands with CTRL-1..9 shortcuts for switching between
    // volumes.
    for (var i = 1; i <= 9; i++) {
      CommandUtil.registerCommand(this.dialogContainer_,
                                  'volume-switch-' + i,
                                  Commands.volumeSwitchCommand,
                                  this.navigationList_,
                                  i);
    }

    CommandUtil.registerCommand(doc, 'zoom-in', Commands.zoomInCommand);
    CommandUtil.registerCommand(doc, 'zoom-out', Commands.zoomOutCommand);
    CommandUtil.registerCommand(doc, 'zoom-reset', Commands.zoomResetCommand);

    CommandUtil.registerCommand(this.dialogContainer_, 'cut',
        Commands.defaultCommand, doc);
    CommandUtil.registerCommand(this.dialogContainer_, 'copy',
        Commands.defaultCommand, doc);

    var inputs = this.dialogDom_.querySelectorAll(
        'input[type=text], input[type=search], textarea');

    for (i = 0; i < inputs.length; i++) {
      cr.ui.contextMenuHandler.setContextMenu(inputs[i], this.textContextMenu_);
      this.registerInputCommands_(inputs[i]);
    }

    cr.ui.contextMenuHandler.setContextMenu(this.renameInput_,
        this.textContextMenu_);
    this.registerInputCommands_(this.renameInput_);

    doc.addEventListener('command', this.setNoHover_.bind(this, true));
  };

  /**
   * Registers cut, copy, paste and delete commands on input element.
   *
   * @param {Node} node Text input element to register on.
   * @private
   */
  FileManager.prototype.registerInputCommands_ = function(node) {
    var defaultCommand = Commands.defaultCommand;
    CommandUtil.forceDefaultHandler(node, 'cut');
    CommandUtil.forceDefaultHandler(node, 'copy');
    CommandUtil.forceDefaultHandler(node, 'paste');
    CommandUtil.forceDefaultHandler(node, 'delete');
    node.addEventListener('keydown', function(e) {
      if (util.getKeyModifiers(e) + e.keyCode == '191') {
        // If this key event is propagated, this is handled search command,
        // which calls 'preventDefault' mehtod.
        e.stopPropagation();
      }
    });
  };

  FileManager.prototype.initializeCore = function() {
    this.initializeQueue_.add(this.initGeneral_.bind(this), [], 'initGeneral');
    this.initializeQueue_.add(this.initStrings_.bind(this), [], 'initStrings');
    this.initializeQueue_.add(
        this.initPreferences_.bind(this), [], 'initPreferences');
    this.initializeQueue_.add(
        this.initFileSystem_.bind(this),
        ['initGeneral', 'initPreferences'], 'initFileSystem');

    this.initializeQueue_.run();
  };

  FileManager.prototype.initializeUI = function(dialogDom, callback) {
    this.dialogDom_ = dialogDom;

    this.initializeQueue_.add(
        this.initEssentialUI_.bind(this),
        ['initGeneral', 'initStrings'],
        'initEssentialUI');
    this.initializeQueue_.add(this.initAdditionalUI_.bind(this),
        ['initEssentialUI'], 'initAdditionalUI');
    this.initializeQueue_.add(
        this.initFileSystemUI_.bind(this),
        ['initFileSystem', 'initAdditionalUI'],
        'initFileSystemUI');

    // Run again just in case if all pending closures have completed and the
    // queue has stopped and monitor the completion.
    this.initializeQueue_.run(callback);
  };

  /**
   * Initializes general purpose basic things, which are used by other
   * initializing methods.
   *
   * @param {function()} callback Completion callback.
   * @private
   */
  FileManager.prototype.initGeneral_ = function(callback) {
    this.volumeManager_ = VolumeManager.getInstance();
    if (window.appState) {
      this.params_ = window.appState.params || {};
      this.defaultPath = window.appState.defaultPath;
    } else {
      this.params_ = location.search ?
                     JSON.parse(decodeURIComponent(location.search.substr(1))) :
                     {};
      this.defaultPath = this.params_.defaultPath;
    }
    callback();
  };

  /**
   * One time initialization of strings (mostly i18n).
   *
   * @param {function()} callback Completion callback.
   * @private
   */
  FileManager.prototype.initStrings_ = function(callback) {
    // Fetch the strings via the private api if running in the browser window.
    // Otherwise, read cached strings from the local storage.
    if (util.platform.runningInBrowser()) {
      chrome.fileBrowserPrivate.getStrings(function(strings) {
        loadTimeData.data = strings;
        callback();
      });
    } else {
      chrome.storage.local.get('strings', function(items) {
        loadTimeData.data = items['strings'];
        callback();
      });
    }
  };

  /**
   * One time initialization of the Files.app's essential UI elements. These
   * elements will be shown to the user. Only visible elements should be
   * initialized here. Any heavy operation should be avoided. Files.app's
   * window is shown at the end of this routine.
   *
   * @param {function()} callback Completion callback.
   * @private
   */
  FileManager.prototype.initEssentialUI_ = function(callback) {
    this.listType_ = null;

    this.filesystemObserverId_ = null;
    this.driveObserverId_ = null;

    this.document_ = this.dialogDom_.ownerDocument;
    this.dialogType = this.params_.type || DialogType.FULL_PAGE;
    this.startupPrefName_ = 'file-manager-' + this.dialogType;

    // Used to filter out focusing by mouse.
    this.suppressFocus_ = false;

    // Optional list of file types.
    this.fileTypes_ = this.params_.typeList || [];
    metrics.recordEnum('Create', this.dialogType,
        [DialogType.SELECT_FOLDER,
         DialogType.SELECT_UPLOAD_FOLDER,
         DialogType.SELECT_SAVEAS_FILE,
         DialogType.SELECT_OPEN_FILE,
         DialogType.SELECT_OPEN_MULTI_FILE,
         DialogType.FULL_PAGE]);

    this.selectionHandler_ = null;
    this.ctrlKeyPressed_ = false;

    this.metadataCache_ = MetadataCache.createFull();

    this.hasFooterPanel_ =
        this.dialogType == DialogType.SELECT_SAVEAS_FILE ||
        this.dialogType == DialogType.SELECT_FOLDER;

    // If the footer panel exists, the buttons are placed there. Otherwise,
    // the buttons are on the preview panel.
    var parentPanelOfButtons = this.dialogDom_.querySelector(
        !this.hasFooterPanel_ ? '.preview-panel' : '.dialog-footer');
    parentPanelOfButtons.classList.add('button-panel');
    this.fileTypeSelector_ = parentPanelOfButtons.querySelector('.file-type');
    this.okButton_ = parentPanelOfButtons.querySelector('.ok');
    this.cancelButton_ = parentPanelOfButtons.querySelector('.cancel');

    // Pre-populate the static localized strings.
    i18nTemplate.process(this.document_, loadTimeData);

    // Initialize the header.
    this.dialogDom_.querySelector('#app-name').innerText =
        chrome.runtime.getManifest().name;

    this.initDialogType_();

    // Show the window as soon as the UI pre-initialization is done.
    if (this.dialogType == DialogType.FULL_PAGE &&
        !util.platform.runningInBrowser()) {
      chrome.app.window.current().show();
      setTimeout(callback, 100);  // Wait until the animation is finished.
    } else {
      callback();
    }
  };

  /**
   * One-time initialization of dialogs.
   * @private
   */
  FileManager.prototype.initDialogs_ = function() {
    var d = cr.ui.dialogs;
    d.BaseDialog.OK_LABEL = str('OK_LABEL');
    d.BaseDialog.CANCEL_LABEL = str('CANCEL_LABEL');
    this.error = new ErrorDialog(this.dialogDom_);
    this.alert = new d.AlertDialog(this.dialogDom_);
    this.confirm = new d.ConfirmDialog(this.dialogDom_);
    this.prompt = new d.PromptDialog(this.dialogDom_);
    this.shareDialog_ = new ShareDialog(this.dialogDom_);
    this.defaultTaskPicker =
        new cr.filebrowser.DefaultActionDialog(this.dialogDom_);
  };

  /**
   * One-time initialization of various DOM nodes. Loads the additional DOM
   * elements visible to the user. Initialize here elements, which are expensive
   * or hidden in the beginning.
   *
   * @param {function()} callback Completion callback.
   * @private
   */
  FileManager.prototype.initAdditionalUI_ = function(callback) {
    this.initDialogs_();

    this.dialogDom_.addEventListener('drop', function(e) {
      // Prevent opening an URL by dropping it onto the page.
      e.preventDefault();
    });

    this.dialogDom_.addEventListener('click',
                                     this.onExternalLinkClick_.bind(this));
    // Cache nodes we'll be manipulating.
    var dom = this.dialogDom_;

    this.filenameInput_ = dom.querySelector('#filename-input-box input');
    this.taskItems_ = dom.querySelector('#tasks');

    this.table_ = dom.querySelector('.detail-table');
    this.grid_ = dom.querySelector('.thumbnail-grid');
    this.spinner_ = dom.querySelector('#spinner-with-text');
    this.showSpinner_(true);

    this.searchBreadcrumbs_ = new BreadcrumbsController(
         dom.querySelector('#search-breadcrumbs'), this.metadataCache_);
    this.searchBreadcrumbs_.addEventListener(
         'pathclick', this.onBreadcrumbClick_.bind(this));
    this.searchBreadcrumbs_.setHideLast(false);

    // Check the option to hide the selecting checkboxes.
    this.table_.showCheckboxes = this.showCheckboxes_;

    var fullPage = this.dialogType == DialogType.FULL_PAGE;
    FileTable.decorate(this.table_, this.metadataCache_, fullPage);
    FileGrid.decorate(this.grid_, this.metadataCache_);

    this.document_.addEventListener('keydown', this.onKeyDown_.bind(this));
    this.document_.addEventListener('keyup', this.onKeyUp_.bind(this));

    // This capturing event is only used to distinguish focusing using
    // keyboard from focusing using mouse.
    this.document_.addEventListener('mousedown', function() {
      this.suppressFocus_ = true;
    }.bind(this), true);

    this.renameInput_ = this.document_.createElement('input');
    this.renameInput_.className = 'rename';

    this.renameInput_.addEventListener(
        'keydown', this.onRenameInputKeyDown_.bind(this));
    this.renameInput_.addEventListener(
        'blur', this.onRenameInputBlur_.bind(this));

    this.filenameInput_.addEventListener(
        'keydown', this.onFilenameInputKeyDown_.bind(this));
    this.filenameInput_.addEventListener(
        'focus', this.onFilenameInputFocus_.bind(this));

    this.listContainer_ = this.dialogDom_.querySelector('#list-container');
    this.listContainer_.addEventListener(
        'keydown', this.onListKeyDown_.bind(this));
    this.listContainer_.addEventListener(
        'keypress', this.onListKeyPress_.bind(this));
    this.listContainer_.addEventListener(
        'mousemove', this.onListMouseMove_.bind(this));

    this.okButton_.addEventListener('click', this.onOk_.bind(this));
    this.onCancelBound_ = this.onCancel_.bind(this);
    this.cancelButton_.addEventListener('click', this.onCancelBound_);

    this.decorateSplitter(
        this.dialogDom_.querySelector('div#sidebar-splitter'));
    this.decorateSplitter(
        this.dialogDom_.querySelector('div#middlebar-splitter'));

    this.dialogContainer_ = this.dialogDom_.querySelector('.dialog-container');

    this.syncButton = this.dialogDom_.querySelector('#drive-sync-settings');
    this.syncButton.addEventListener('activate', this.onDrivePrefClick_.bind(
        this, 'cellularDisabled', false /* not inverted */));

    this.hostedButton = this.dialogDom_.querySelector('#drive-hosted-settings');
    this.hostedButton.addEventListener('activate', this.onDrivePrefClick_.bind(
        this, 'hostedFilesDisabled', true /* inverted */));

    this.detailViewButton_ =
        this.dialogDom_.querySelector('#detail-view');
    this.detailViewButton_.addEventListener('activate',
        this.onDetailViewButtonClick_.bind(this));

    this.thumbnailViewButton_ =
        this.dialogDom_.querySelector('#thumbnail-view');
    this.thumbnailViewButton_.addEventListener('activate',
        this.onThumbnailViewButtonClick_.bind(this));

    cr.ui.ComboButton.decorate(this.taskItems_);
    this.taskItems_.addEventListener('select',
        this.onTaskItemClicked_.bind(this));

    this.dialogDom_.ownerDocument.defaultView.addEventListener(
        'resize', this.onResize_.bind(this));

    this.filePopup_ = null;

    this.searchBoxWrapper_ =
        this.dialogDom_.querySelector('.search-box-wrapper');
    this.searchBox_ = this.dialogDom_.querySelector('#search-box');
    this.searchBox_.addEventListener(
        'input', this.onSearchBoxUpdate_.bind(this));
    this.searchBox_.addEventListener(
        'keydown', this.onSearchBoxKeyDown_.bind(this));
    this.searchTextMeasure_ = new TextMeasure(this.searchBox_);
    this.searchIcon_ = this.dialogDom_.querySelector('#search-icon');
    this.searchIcon_.addEventListener(
        'click',
        function() { this.searchBox_.focus(); }.bind(this));
    this.searchClearButton_ =
        this.dialogDom_.querySelector('#search-clear-button');
    this.searchClearButton_.addEventListener(
        'click',
        function() {
          this.searchBox_.value = '';
          this.onSearchBoxUpdate_();
        }.bind(this));
    this.lastSearchQuery_ = '';

    var autocompleteList = new cr.ui.AutocompleteList();
    autocompleteList.id = 'autocomplete-list';
    autocompleteList.autoExpands = true;
    autocompleteList.requestSuggestions =
        this.requestAutocompleteSuggestions_.bind(this);
    // function(item) {}.bind(this) does not work here, as it's a constructor.
    var self = this;
    autocompleteList.itemConstructor = function(item) {
      return self.createAutocompleteListItem_(item);
    };

    // Do nothing when a suggestion is selected.
    autocompleteList.handleSelectedSuggestion = function(selectedItem) {};
    // Instead, open the suggested item when Enter key is pressed or
    // mouse-clicked.
    autocompleteList.handleEnterKeydown = function(event) {
      this.openAutocompleteSuggestion_();
      this.lastAutocompleteQuery_ = '';
      this.autocompleteList_.suggestions = [];
    }.bind(this);
    autocompleteList.addEventListener('mousedown', function(event) {
      this.openAutocompleteSuggestion_();
      this.lastAutocompleteQuery_ = '';
      this.autocompleteList_.suggestions = [];
    }.bind(this));
    autocompleteList.addEventListener('mouseover', function(event) {
      // Change the selection by a mouse over instead of just changing the
      // color of moused over element with :hover in CSS. Here's why:
      //
      // 1) The user selects an item A with up/down keys (item A is highlighted)
      // 2) Then the user moves the cursor to another item B
      //
      // If we just change the color of moused over element (item B), both
      // the item A and B are highlighted. This is bad. We should change the
      // selection so only the item B is highlighted.
      if (event.target.itemInfo)
        autocompleteList.selectedItem = event.target.itemInfo;
    }.bind(this));

    var container = this.document_.querySelector('.dialog-header');
    container.appendChild(autocompleteList);
    this.autocompleteList_ = autocompleteList;

    this.searchBox_.addEventListener('focus', function(event) {
      this.autocompleteList_.attachToInput(this.searchBox_);
    }.bind(this));
    this.searchBox_.addEventListener('blur', function(event) {
      this.autocompleteList_.detach();
    }.bind(this));

    this.defaultActionMenuItem_ =
        this.dialogDom_.querySelector('#default-action');

    this.openWithCommand_ =
        this.dialogDom_.querySelector('#open-with');

    this.driveBuyMoreStorageCommand_ =
        this.dialogDom_.querySelector('#drive-buy-more-space');

    this.defaultActionMenuItem_.addEventListener('activate',
        this.dispatchSelectionAction_.bind(this));

    this.initFileTypeFilter_();

    util.addIsFocusedMethod();

    // Populate the static localized strings.
    i18nTemplate.process(this.document_, loadTimeData);

    // Arrange the file list.
    this.table_.normalizeColumns();
    this.table_.redraw();

    callback();
  };

  /**
   * @private
   */
  FileManager.prototype.onBreadcrumbClick_ = function(event) {
    this.directoryModel_.changeDirectory(event.path);
  };

  /**
   * Constructs table and grid (heavy operation).
   * @private
   **/
  FileManager.prototype.initFileList_ = function() {
    // Always sharing the data model between the detail/thumb views confuses
    // them.  Instead we maintain this bogus data model, and hook it up to the
    // view that is not in use.
    this.emptyDataModel_ = new cr.ui.ArrayDataModel([]);
    this.emptySelectionModel_ = new cr.ui.ListSelectionModel();

    var singleSelection =
        this.dialogType == DialogType.SELECT_OPEN_FILE ||
        this.dialogType == DialogType.SELECT_FOLDER ||
        this.dialogType == DialogType.SELECT_UPLOAD_FOLDER ||
        this.dialogType == DialogType.SELECT_SAVEAS_FILE;

    var showSpecialSearchRoots =
        this.dialogType == DialogType.SELECT_OPEN_FILE ||
        this.dialogType == DialogType.SELECT_OPEN_MULTI_FILE ||
        this.dialogType == DialogType.FULL_PAGE;

    this.fileFilter_ = new FileFilter(
        this.metadataCache_,
        false  /* Don't show dot files by default. */);

    this.fileWatcher_ = new FileWatcher(this.metadataCache_);
    this.fileWatcher_.addEventListener(
        'watcher-metadata-changed',
        this.onWatcherMetadataChanged_.bind(this));

    this.directoryModel_ = new DirectoryModel(
        this.filesystem_.root,
        singleSelection,
        this.fileFilter_,
        this.fileWatcher_,
        this.metadataCache_,
        this.volumeManager_,
        this.isDriveEnabled(),
        showSpecialSearchRoots);

    this.directoryModel_.start();

    this.folderShortcutsModel_ = new FolderShortcutsDataModel();

    this.selectionHandler_ = new FileSelectionHandler(this);
    this.selectionHandler_.addEventListener('show-preview-panel',
        this.onPreviewPanelVisibilityChanged_.bind(this, true));
    this.selectionHandler_.addEventListener('hide-preview-panel',
        this.onPreviewPanelVisibilityChanged_.bind(this, false));

    var dataModel = this.directoryModel_.getFileList();

    this.table_.setupCompareFunctions(dataModel);

    dataModel.addEventListener('permuted',
                               this.updateStartupPrefs_.bind(this));

    this.directoryModel_.getFileListSelection().addEventListener('change',
        this.selectionHandler_.onFileSelectionChanged.bind(
            this.selectionHandler_));

    this.initList_(this.grid_);
    this.initList_(this.table_.list);

    var fileListFocusBound = this.onFileListFocus_.bind(this);
    var fileListBlurBound = this.onFileListBlur_.bind(this);

    this.table_.list.addEventListener('focus', fileListFocusBound);
    this.grid_.addEventListener('focus', fileListFocusBound);

    this.table_.list.addEventListener('blur', fileListBlurBound);
    this.grid_.addEventListener('blur', fileListBlurBound);

    var dragStartBound = this.onDragStart_.bind(this);
    this.table_.list.addEventListener('dragstart', dragStartBound);
    this.grid_.addEventListener('dragstart', dragStartBound);

    var dragEndBound = this.onDragEnd_.bind(this);
    this.table_.list.addEventListener('dragend', dragEndBound);
    this.grid_.addEventListener('dragend', dragEndBound);
    // This event is published by DragSelector because drag end event is not
    // published at the end of drag selection.
    this.table_.list.addEventListener('dragselectionend', dragEndBound);

    // TODO(mtomasz, yoshiki): Create sidebar earlier, and here just attach
    // the directory model.
    this.initSidebar_();

    this.table_.addEventListener('column-resize-end',
                                 this.updateStartupPrefs_.bind(this));

    // Restore preferences.
    this.directoryModel_.sortFileList(
        this.viewOptions_.sortField || 'modificationTime',
        this.viewOptions_.sortDirection || 'desc');
    if (this.viewOptions_.columns) {
      var cm = this.table_.columnModel;
      for (var i = 0; i < cm.totalSize; i++) {
        if (this.viewOptions_.columns[i] > 0)
          cm.setWidth(i, this.viewOptions_.columns[i]);
      }
    }
    this.setListType(this.viewOptions_.listType || FileManager.ListType.DETAIL);

    this.textSearchState_ = {text: '', date: new Date()};
    this.closeOnUnmount_ = (this.params_.action == 'auto-open');

    if (this.closeOnUnmount_) {
      this.volumeManager_.addEventListener('externally-unmounted',
         this.onExternallyUnmounted_.bind(this));
    }

    // Update metadata to change 'Today' and 'Yesterday' dates.
    var today = new Date();
    today.setHours(0);
    today.setMinutes(0);
    today.setSeconds(0);
    today.setMilliseconds(0);
    setTimeout(this.dailyUpdateModificationTime_.bind(this),
               today.getTime() + MILLISECONDS_IN_DAY - Date.now() + 1000);
  };

  /**
   * @private
   */
  FileManager.prototype.initSidebar_ = function() {
    this.directoryTree_ = this.dialogDom_.querySelector('#directory-tree');
    DirectoryTree.decorate(this.directoryTree_, this.directoryModel_);
    this.directoryTree_.addEventListener('content-updated', function() {
      this.updateMiddleBarVisibility_(true);
    }.bind(this));

    this.navigationList_ = this.dialogDom_.querySelector('#volume-list');
    NavigationList.decorate(this.navigationList_,
                            this.directoryModel_,
                            this.folderShortcutsModel_);
  };

  /**
   * @param {boolean=} opt_delayed If true, updating is delayed by 500ms.
   * @private
   */
  FileManager.prototype.updateMiddleBarVisibility_ = function(opt_delayed) {
    if (this.updateMiddleBarVisibilityTimer_) {
      clearTimeout(this.updateMiddleBarVisibilityTimer_);
      this.updateMiddleBarVisibilityTimer_ = null;
    }

    if (opt_delayed) {
      this.updateMiddleBarVisibilityTimer_ =
          setTimeout(this.updateMiddleBarVisibility_.bind(this, false), 500);
      return;
    }
    var currentPath = this.directoryModel_.getCurrentDirPath();
    var visible =
        (this.directoryTree_.items.length > 0) &&
        (!DirectoryTreeUtil.shouldHideTree(currentPath));
    this.dialogDom_.
        querySelector('.dialog-middlebar-contents').hidden = !visible;
    this.dialogDom_.querySelector('#middlebar-splitter').hidden = !visible;
    this.onResize_();
  };

  /**
   * @private
   */
  FileManager.prototype.updateStartupPrefs_ = function() {
    var sortStatus = this.directoryModel_.getFileList().sortStatus;
    var prefs = {
      sortField: sortStatus.field,
      sortDirection: sortStatus.direction,
      columns: [],
      listType: this.listType_
    };
    var cm = this.table_.columnModel;
    for (var i = 0; i < cm.totalSize; i++) {
      prefs.columns.push(cm.getWidth(i));
    }
    if (DialogType.isModal(this.dialogType))
      prefs.listType = this.listType;
    // Save the global default.
    util.platform.setPreference(this.startupPrefName_, JSON.stringify(prefs));

    // Save the window-specific preference.
    if (window.appState) {
      window.appState.viewOptions = prefs;
      util.saveAppState();
    }
  };

  FileManager.prototype.refocus = function() {
    if (this.dialogType == DialogType.SELECT_SAVEAS_FILE)
      this.filenameInput_.focus();
    else
      this.currentList_.focus();
  };

  /**
   * File list focus handler. Used to select the top most element on the list
   * if nothing was selected.
   *
   * @private
   */
  FileManager.prototype.onFileListFocus_ = function() {
    // Do not select default item if focused using mouse.
    if (this.suppressFocus_)
      return;

    var selection = this.getSelection();
    if (!selection || selection.totalCount != 0)
      return;

    this.directoryModel_.selectIndex(0);
  };

  /**
   * File list blur handler.
   *
   * @private
   */
  FileManager.prototype.onFileListBlur_ = function() {
    this.suppressFocus_ = false;
  };

  /**
   * Index of selected item in the typeList of the dialog params.
   *
   * @return {number} 1-based index of selected type or 0 if no type selected.
   * @private
   */
  FileManager.prototype.getSelectedFilterIndex_ = function() {
    var index = Number(this.fileTypeSelector_.selectedIndex);
    if (index < 0)  // Nothing selected.
      return 0;
    if (this.params_.includeAllFiles)  // Already 1-based.
      return index;
    return index + 1;  // Convert to 1-based;
  };

  FileManager.prototype.setListType = function(type) {
    if (type && type == this.listType_)
      return;

    this.table_.list.startBatchUpdates();
    this.grid_.startBatchUpdates();

    // TODO(dzvorygin): style.display and dataModel setting order shouldn't
    // cause any UI bugs. Currently, the only right way is first to set display
    // style and only then set dataModel.

    if (type == FileManager.ListType.DETAIL) {
      this.table_.dataModel = this.directoryModel_.getFileList();
      this.table_.selectionModel = this.directoryModel_.getFileListSelection();
      this.table_.hidden = false;
      this.grid_.hidden = true;
      this.grid_.selectionModel = this.emptySelectionModel_;
      this.grid_.dataModel = this.emptyDataModel_;
      this.table_.hidden = false;
      /** @type {cr.ui.List} */
      this.currentList_ = this.table_.list;
      this.detailViewButton_.setAttribute('checked', '');
      this.thumbnailViewButton_.removeAttribute('checked');
      this.detailViewButton_.setAttribute('disabled', '');
      this.thumbnailViewButton_.removeAttribute('disabled');
    } else if (type == FileManager.ListType.THUMBNAIL) {
      this.grid_.dataModel = this.directoryModel_.getFileList();
      this.grid_.selectionModel = this.directoryModel_.getFileListSelection();
      this.grid_.hidden = false;
      this.table_.hidden = true;
      this.table_.selectionModel = this.emptySelectionModel_;
      this.table_.dataModel = this.emptyDataModel_;
      this.grid_.hidden = false;
      /** @type {cr.ui.List} */
      this.currentList_ = this.grid_;
      this.thumbnailViewButton_.setAttribute('checked', '');
      this.detailViewButton_.removeAttribute('checked');
      this.thumbnailViewButton_.setAttribute('disabled', '');
      this.detailViewButton_.removeAttribute('disabled');
    } else {
      throw new Error('Unknown list type: ' + type);
    }

    this.listType_ = type;
    this.updateStartupPrefs_();
    this.onResize_();

    this.table_.list.endBatchUpdates();
    this.grid_.endBatchUpdates();
  };

  /**
   * Initialize the file list table or grid.
   *
   * @param {cr.ui.List} list The list.
   * @private
   */
  FileManager.prototype.initList_ = function(list) {
    // Overriding the default role 'list' to 'listbox' for better accessibility
    // on ChromeOS.
    list.setAttribute('role', 'listbox');
    list.addEventListener('click', this.onDetailClick_.bind(this));
    list.id = 'file-list';
  };

  /**
   * @private
   */
  FileManager.prototype.onCopyProgress_ = function(event) {
    if (event.reason == 'ERROR' &&
        event.error.code == util.FileOperationErrorType.FILESYSTEM_ERROR &&
        event.error.data.toDrive &&
        event.error.data.code == FileError.QUOTA_EXCEEDED_ERR) {
      this.alert.showHtml(
          strf('DRIVE_SERVER_OUT_OF_SPACE_HEADER'),
          strf('DRIVE_SERVER_OUT_OF_SPACE_MESSAGE',
              decodeURIComponent(
                  event.error.data.sourceFileUrl.split('/').pop()),
              FileManager.GOOGLE_DRIVE_BUY_STORAGE));
    }

    // TODO(benchan): Currently, there is no FileWatcher emulation for
    // drive::FileSystem, so we need to manually trigger the directory rescan
    // after paste operations complete. Remove this once we emulate file
    // watching functionalities in drive::FileSystem.
    if (this.isOnDrive()) {
      if (event.reason == 'SUCCESS' || event.reason == 'ERROR' ||
          event.reason == 'CANCELLED') {
        this.directoryModel_.rescanLater();
      }
    }
  };

  /**
   * Handler of file manager operations. Called when an entry has been
   * changed.
   * This updates directory model to reflect operation result immediately (not
   * waiting for directory update event). Also, preloads thumbnails for the
   * images of new entries.
   * See also FileCopyManager.EventRouter.
   *
   * @param {cr.Event} event An event for the entry change.
   * @private
   */
  FileManager.prototype.onCopyManagerEntryChanged_ = function(event) {
    var type = event.type;
    var entry = event.entry;
    this.directoryModel_.onEntryChanged(type, entry);

    if (type == util.EntryChangedType.CREATE && FileType.isImage(entry)) {
      // Preload a thumbnail if the new copied entry an image.
      var metadata = entry.getMetadata(function(metadata) {
        var url = entry.toURL();
        var thumbnailLoader_ = new ThumbnailLoader(
            url,
            ThumbnailLoader.LoaderType.CANVAS,
            metadata,
            undefined,  // Media type.
            FileType.isOnDrive(url) ?
                ThumbnailLoader.UseEmbedded.USE_EMBEDDED :
                ThumbnailLoader.UseEmbedded.NO_EMBEDDED,
            10);  // Very low priority.
        thumbnailLoader_.loadDetachedImage(function(success) {});
      });
    }
  };

  /**
   * Fills the file type list or hides it.
   * @private
   */
  FileManager.prototype.initFileTypeFilter_ = function() {
    if (this.params_.includeAllFiles) {
      var option = this.document_.createElement('option');
      option.innerText = str('ALL_FILES_FILTER');
      this.fileTypeSelector_.appendChild(option);
      option.value = 0;
    }

    for (var i = 0; i < this.fileTypes_.length; i++) {
      var fileType = this.fileTypes_[i];
      var option = this.document_.createElement('option');
      var description = fileType.description;
      if (!description) {
        // See if all the extensions in the group have the same description.
        for (var j = 0; j != fileType.extensions.length; j++) {
          var currentDescription =
              FileType.getTypeString('.' + fileType.extensions[j]);
          if (!description)  // Set the first time.
            description = currentDescription;
          else if (description != currentDescription) {
            // No single description, fall through to the extension list.
            description = null;
            break;
          }
        }

        if (!description)
          // Convert ['jpg', 'png'] to '*.jpg, *.png'.
          description = fileType.extensions.map(function(s) {
           return '*.' + s;
          }).join(', ');
       }
       option.innerText = description;

       option.value = i + 1;

       if (fileType.selected)
         option.selected = true;

       this.fileTypeSelector_.appendChild(option);
    }

    var options = this.fileTypeSelector_.querySelectorAll('option');
    if (options.length < 2) {
      // There is in fact no choice, hide the selector.
      this.fileTypeSelector_.hidden = true;
      return;
    }

    this.fileTypeSelector_.addEventListener('change',
        this.updateFileTypeFilter_.bind(this));
  };

  /**
   * Filters file according to the selected file type.
   * @private
   */
  FileManager.prototype.updateFileTypeFilter_ = function() {
    this.fileFilter_.removeFilter('fileType');
    var selectedIndex = this.getSelectedFilterIndex_();
    if (selectedIndex > 0) { // Specific filter selected.
      var regexp = new RegExp('.*(' +
          this.fileTypes_[selectedIndex - 1].extensions.join('|') + ')$', 'i');
      var filter = function(entry) {
        return entry.isDirectory || regexp.test(entry.name);
      };
      this.fileFilter_.addFilter('fileType', filter);
    }
  };

  /**
   * Resize details and thumb views to fit the new window size.
   * @private
   */
  FileManager.prototype.onResize_ = function() {
    if (this.listType_ == FileManager.ListType.THUMBNAIL)
      this.grid_.relayout();
    else
      this.table_.relayout();

    // May not be available during initialization.
    if (this.directoryTree_)
      this.directoryTree_.relayout();

    // TODO(mtomasz, yoshiki): Initialize navigation list earlier, before
    // file system is available.
    if (this.navigationList_)
      this.navigationList_.redraw();

    // Hide the search box if there is not enough space.
    this.searchBoxWrapper_.classList.toggle(
        'too-short',
        this.searchBoxWrapper_.clientWidth < 100);

    this.searchBreadcrumbs_.truncate();
  };

  /**
   * Handles local metadata changes in the currect directory.
   * @param {Event} event Change event.
   * @private
   */
  FileManager.prototype.onWatcherMetadataChanged_ = function(event) {
    this.updateMetadataInUI_(event.metadataType, event.urls, event.properties);
  };

  /**
   * Resize details and thumb views to fit the new window size.
   * @private
   */
  FileManager.prototype.onPreviewPanelVisibilityChanged_ = function(visible) {
    var panelHeight = visible ? this.getPreviewPanelHeight_() : 0;
    this.grid_.setBottomMarginForPanel(panelHeight);
    this.table_.setBottomMarginForPanel(panelHeight);
    this.directoryTree_.setBottomMarginForPanel(panelHeight);
  };

  /**
   * Invoked when the drag is started on the list or the grid.
   * @private
   */
  FileManager.prototype.onDragStart_ = function() {
    this.selectionHandler_.setPreviewPanelMustBeHidden(true);
  };

  /**
   * Invoked when the drag is ended on the list or the grid.
   * @private
   */
  FileManager.prototype.onDragEnd_ = function() {
    this.selectionHandler_.setPreviewPanelMustBeHidden(false);
  };

  /**
   * Gets height of the preview panel, using cached value if available. This
   * returns the value even when the preview panel is hidden.
   *
   * @return {number} Height of the preview panel. If failure, returns 0.
   */
  FileManager.prototype.getPreviewPanelHeight_ = function() {
    if (!this.cachedPreviewPanelHeight_) {
      var previewPanel = this.dialogDom_.querySelector('.preview-panel');
      this.cachedPreviewPanelHeight_ = previewPanel.clientHeight;
    }
    return this.cachedPreviewPanelHeight_;
  };

  /**
   * Restores current directory and may be a selected item after page load (or
   * reload) or popping a state (after click on back/forward). If location.hash
   * is present it means that the user has navigated somewhere and that place
   * will be restored. defaultPath primarily is used with save/open dialogs.
   * Default path may also contain a file name. Freshly opened file manager
   * window has neither.
   *
   * @param {boolean} pageLoading True if the page is loading,
   *                              false if popping state.
   * @private
   */
  FileManager.prototype.setupCurrentDirectory_ = function(pageLoading) {
    var path = location.hash ?  // Location hash has the highest priority.
        decodeURIComponent(location.hash.substr(1)) :
        this.defaultPath;

    if (!pageLoading && path == this.directoryModel_.getCurrentDirPath())
      return;

    if (!path) {
      path = this.directoryModel_.getDefaultDirectory();
    } else if (path.indexOf('/') == -1) {
      // Path is a file name.
      path = this.directoryModel_.getDefaultDirectory() + '/' + path;
    }

    // In the FULL_PAGE mode if the hash path points to a file we might have
    // to invoke a task after selecting it.
    // If the file path is in params_ we only want to select the file.
    var invokeHandlers = pageLoading && (this.params_.action != 'select') &&
        this.dialogType == DialogType.FULL_PAGE;

    if (PathUtil.getRootType(path) === RootType.DRIVE) {
      if (!this.isDriveEnabled()) {
        var leafName = path.substr(path.indexOf('/') + 1);
        path = this.directoryModel_.getDefaultDirectory() + '/' + leafName;
        this.finishSetupCurrentDirectory_(path, invokeHandlers);
        return;
      }
      if (this.volumeManager_.isMounted(RootDirectory.DRIVE)) {
        this.finishSetupCurrentDirectory_(path, invokeHandlers);
        return;
      }

      var tracker = this.directoryModel_.createDirectoryChangeTracker();
      // Expected finish of setupPath to Drive.
      tracker.exceptInitialChange = true;
      tracker.start();
      // Waits until the Drive is mounted.
      this.volumeManager_.mountDrive(function() {
        tracker.stop();
        if (!tracker.hasChanged)
          this.finishSetupCurrentDirectory_(path, invokeHandlers);
      }.bind(this), function(error) {
        tracker.stop();
      });
    } else {
      this.finishSetupCurrentDirectory_(path, invokeHandlers);
    }
  };

  /**
   * @param {string} path Path to setup.
   * @param {boolean} invokeHandlers If thrue and |path| points to a file
   *     then default handler is triggered.
   *
   * @private
   */
  FileManager.prototype.finishSetupCurrentDirectory_ = function(
      path, invokeHandlers) {
    if (invokeHandlers) {
      var onResolve = function(baseName, leafName, exists) {
        var urls = null;
        var action = null;

        if (!exists || leafName == '') {
          // Non-existent file or a directory.
          if (this.params_.gallery) {
            // Reloading while the Gallery is open with empty or multiple
            // selection. Open the Gallery when the directory is scanned.
            urls = [];
            action = 'gallery';
          }
        } else {
          // There are 3 ways we can get here:
          // 1. Invoked from file_manager_util::ViewFile. This can only
          //    happen for 'gallery' and 'mount-archive' actions.
          // 2. Reloading a Gallery page. Must be an image or a video file.
          // 3. A user manually entered a URL pointing to a file.
          // We call the appropriate methods of FileTasks directly as we do
          // not need any of the preparations that |execute| method does.
          if (FileType.isImageOrVideo(path)) {
            urls = [util.makeFilesystemUrl(path)];
            action = 'gallery';
          }
          if (FileType.getMediaType(path) == 'archive') {
            urls = [util.makeFilesystemUrl(path)];
            action = 'archives';
          }
        }

        if (urls) {
          var listener = function() {
            this.directoryModel_.removeEventListener(
                'scan-completed', listener);
            var tasks = new FileTasks(this, this.params_);
            if (action == 'gallery') {
              tasks.openGallery(urls);
            } else if (action == 'archives') {
              tasks.mountArchives(urls);
            }
          }.bind(this);
          this.directoryModel_.addEventListener('scan-completed', listener);
        }
      }.bind(this);

      this.directoryModel_.setupPath(path, onResolve);
      return;
    }

    if (this.dialogType == DialogType.SELECT_SAVEAS_FILE) {
      this.directoryModel_.setupPath(path, function(basePath, leafName) {
        this.filenameInput_.value = leafName;
        this.selectDefaultPathInFilenameInput_();
      }.bind(this));
      return;
    }

    this.directoryModel_.setupPath(path);
  };

  /**
   * Tweak the UI to become a particular kind of dialog, as determined by the
   * dialog type parameter passed to the constructor.
   *
   * @private
   */
  FileManager.prototype.initDialogType_ = function() {
    var defaultTitle;
    var okLabel = str('OPEN_LABEL');

    switch (this.dialogType) {
      case DialogType.SELECT_FOLDER:
        defaultTitle = str('SELECT_FOLDER_TITLE');
        break;

      case DialogType.SELECT_UPLOAD_FOLDER:
        defaultTitle = str('SELECT_UPLOAD_FOLDER_TITLE');
        okLabel = str('UPLOAD_LABEL');
        break;

      case DialogType.SELECT_OPEN_FILE:
        defaultTitle = str('SELECT_OPEN_FILE_TITLE');
        break;

      case DialogType.SELECT_OPEN_MULTI_FILE:
        defaultTitle = str('SELECT_OPEN_MULTI_FILE_TITLE');
        break;

      case DialogType.SELECT_SAVEAS_FILE:
        defaultTitle = str('SELECT_SAVEAS_FILE_TITLE');
        okLabel = str('SAVE_LABEL');
        break;

      case DialogType.FULL_PAGE:
        break;

      default:
        throw new Error('Unknown dialog type: ' + this.dialogType);
    }

    this.okButton_.textContent = okLabel;
    this.dialogDom_.setAttribute('type', this.dialogType);
  };

  /**
   * Unmounts device.
   * @param {string} path Path to a volume to unmount.
   */
  FileManager.prototype.unmountVolume = function(path) {
    var onError = function(error) {
      this.alert.showHtml('', str('UNMOUNT_FAILED'));
    };
    this.volumeManager_.unmount(path, function() {}, onError.bind(this));
  };

  /**
   * @private
   */
  FileManager.prototype.refreshCurrentDirectoryMetadata_ = function() {
    var entries = this.directoryModel_.getFileList().slice();
    var directoryEntry = this.directoryModel_.getCurrentDirEntry();
    // We don't pass callback here. When new metadata arrives, we have an
    // observer registered to update the UI.

    // TODO(dgozman): refresh content metadata only when modificationTime
    // changed.
    var isFakeEntry = typeof directoryEntry.toURL !== 'function';
    var getEntries = (isFakeEntry ? [] : [directoryEntry]).concat(entries);
    this.metadataCache_.clearRecursively(directoryEntry, '*');
    this.metadataCache_.get(getEntries, 'filesystem', null);

    if (this.isOnDrive())
      this.metadataCache_.get(getEntries, 'drive', null);

    var visibleItems = this.currentList_.items;
    var visibleEntries = [];
    for (var i = 0; i < visibleItems.length; i++) {
      var index = this.currentList_.getIndexOfListItem(visibleItems[i]);
      var entry = this.directoryModel_.getFileList().item(index);
      // The following check is a workaround for the bug in list: sometimes item
      // does not have listIndex, and therefore is not found in the list.
      if (entry) visibleEntries.push(entry);
    }
    this.metadataCache_.get(visibleEntries, 'thumbnail', null);
  };

  /**
   * @private
   */
  FileManager.prototype.dailyUpdateModificationTime_ = function() {
    var fileList = this.directoryModel_.getFileList();
    var urls = [];
    for (var i = 0; i < fileList.length; i++) {
      urls.push(fileList.item(i).toURL());
    }
    this.metadataCache_.get(
        fileList.slice(), 'filesystem',
        this.updateMetadataInUI_.bind(this, 'filesystem', urls));

    setTimeout(this.dailyUpdateModificationTime_.bind(this),
               MILLISECONDS_IN_DAY);
  };

  /**
   * @param {string} type Type of metadata changed.
   * @param {Array.<string>} urls Array of urls.
   * @param {Object.<string, Object>} props Map from entry URLs to metadata
   *     props.
   * @private
   */
  FileManager.prototype.updateMetadataInUI_ = function(
      type, urls, properties) {
    var propertyByUrl = urls.reduce(function(map, url, index) {
      map[url] = properties[index];
      return map;
    }, {});

    if (this.listType_ == FileManager.ListType.DETAIL)
      this.table_.updateListItemsMetadata(type, propertyByUrl);
    else
      this.grid_.updateListItemsMetadata(type, propertyByUrl);
    // TODO: update bottom panel thumbnails.
  };

  /**
   * Restore the item which is being renamed while refreshing the file list. Do
   * nothing if no item is being renamed or such an item disappeared.
   *
   * While refreshing file list it gets repopulated with new file entries.
   * There is not a big difference whether DOM items stay the same or not.
   * Except for the item that the user is renaming.
   *
   * @private
   */
  FileManager.prototype.restoreItemBeingRenamed_ = function() {
    if (!this.isRenamingInProgress())
      return;

    var dm = this.directoryModel_;
    var leadIndex = dm.getFileListSelection().leadIndex;
    if (leadIndex < 0)
      return;

    var leadEntry = dm.getFileList().item(leadIndex);
    if (this.renameInput_.currentEntry.fullPath != leadEntry.fullPath)
      return;

    var leadListItem = this.findListItemForNode_(this.renameInput_);
    if (this.currentList_ == this.table_.list) {
      this.table_.updateFileMetadata(leadListItem, leadEntry);
    }
    this.currentList_.restoreLeadItem(leadListItem);
  };

  /**
   * @return {boolean} True if the current directory content is from Google
   *     Drive.
   */
  FileManager.prototype.isOnDrive = function() {
    var rootType = this.directoryModel_.getCurrentRootType();
    return rootType === RootType.DRIVE ||
           rootType === RootType.DRIVE_SHARED_WITH_ME ||
           rootType === RootType.DRIVE_RECENT ||
           rootType === RootType.DRIVE_OFFLINE;
  };

  /**
   * @return {boolean} True if the ctrl key is pressed now.
   */
  FileManager.prototype.isCtrlKeyPressed = function() {
    return this.ctrlKeyPressed_;
  };

  /**
   * Overrides default handling for clicks on hyperlinks.
   * In a packaged apps links with targer='_blank' open in a new tab by
   * default, other links do not open at all.
   *
   * @param {Event} event Click event.
   * @private
   */
  FileManager.prototype.onExternalLinkClick_ = function(event) {
    if (event.target.tagName != 'A' || !event.target.href)
      return;

    if (this.dialogType != DialogType.FULL_PAGE)
      this.onCancel_();
  };

  /**
   * Task combobox handler.
   *
   * @param {Object} event Event containing task which was clicked.
   * @private
   */
  FileManager.prototype.onTaskItemClicked_ = function(event) {
    var selection = this.getSelection();
    if (!selection.tasks) return;

    if (event.item.task) {
      // Task field doesn't exist on change-default dropdown item.
      selection.tasks.execute(event.item.task.taskId);
    } else {
      var extensions = [];

      for (var i = 0; i < selection.urls.length; i++) {
        var match = /\.(\w+)$/g.exec(selection.urls[i]);
        if (match) {
          var ext = match[1].toUpperCase();
          if (extensions.indexOf(ext) == -1) {
            extensions.push(ext);
          }
        }
      }

      var format = '';

      if (extensions.length == 1) {
        format = extensions[0];
      }

      // Change default was clicked. We should open "change default" dialog.
      selection.tasks.showTaskPicker(this.defaultTaskPicker,
          loadTimeData.getString('CHANGE_DEFAULT_MENU_ITEM'),
          strf('CHANGE_DEFAULT_CAPTION', format),
          this.onDefaultTaskDone_.bind(this));
    }
  };


  /**
   * Sets the given task as default, when this task is applicable.
   *
   * @param {Object} task Task to set as default.
   * @private
   */
  FileManager.prototype.onDefaultTaskDone_ = function(task) {
    // TODO(dgozman): move this method closer to tasks.
    var selection = this.getSelection();
    chrome.fileBrowserPrivate.setDefaultTask(task.taskId,
      selection.urls, selection.mimeTypes);
    selection.tasks = new FileTasks(this);
    selection.tasks.init(selection.urls, selection.mimeTypes);
    selection.tasks.display(this.taskItems_);
    this.refreshCurrentDirectoryMetadata_();
    this.selectionHandler_.onFileSelectionChanged();
  };

  /**
   * @private
   */
  FileManager.prototype.onPreferencesChanged_ = function() {
    var self = this;
    this.getPreferences_(function(prefs) {
      self.initDateTimeFormatters_();
      self.refreshCurrentDirectoryMetadata_();

      self.directoryModel_.setDriveEnabled(self.isDriveEnabled());

      if (prefs.cellularDisabled)
        self.syncButton.setAttribute('checked', '');
      else
        self.syncButton.removeAttribute('checked');

      if (self.hostedButton.hasAttribute('checked') !=
          prefs.hostedFilesDisabled && self.isOnDrive()) {
        self.directoryModel_.rescan();
      }

      if (!prefs.hostedFilesDisabled)
        self.hostedButton.setAttribute('checked', '');
      else
        self.hostedButton.removeAttribute('checked');
    },
    true /* refresh */);
  };

  FileManager.prototype.onDriveConnectionChanged_ = function() {
    var connection = this.volumeManager_.getDriveConnectionState();
    this.updateCommands();
    if (this.dialogContainer_)
      this.dialogContainer_.setAttribute('connection', connection.type);
    if (this.shareDialog_.isShowing()) {
      this.shareDialog_.hide();
      this.error.show(str('SHARE_ERROR'));
    }
  };

  /**
   * Get the metered status of Drive connection.
   *
   * @return {boolean} Returns true if drive should limit the traffic because
   * the connection is metered and the 'disable-sync-on-metered' setting is
   * enabled. Otherwise, returns false.
   */
  FileManager.prototype.isDriveOnMeteredConnection = function() {
    var connection = this.volumeManager_.getDriveConnectionState();
    return connection.type == VolumeManager.DriveConnectionType.METERED;
  };

  /**
   * Get the online/offline status of drive.
   *
   * @return {boolean} Returns true if the connection is offline. Otherwise,
   * returns false.
   */
  FileManager.prototype.isDriveOffline = function() {
    var connection = this.volumeManager_.getDriveConnectionState();
    return connection.type == VolumeManager.DriveConnectionType.OFFLINE;
  };

  FileManager.prototype.isDriveEnabled = function() {
    // Auto resolving to local path does not work for folders (e.g., dialog for
    // loading unpacked extensions) and saving.
    // TODO(kinaba): make it work for the save dialog http://crbug.com/140425
    var noLocalPathResolution =
      this.params_.type == DialogType.SELECT_SAVEAS_FILE ||
      this.params_.type == DialogType.SELECT_FOLDER ||
      this.params_.type == DialogType.SELECT_UPLOAD_FOLDER;
    if (noLocalPathResolution && this.params_.shouldReturnLocalPath)
      return false;
    return this.preferences_.driveEnabled;
  };

  FileManager.prototype.isOnReadonlyDirectory = function() {
    return this.directoryModel_.isReadOnly();
  };

  /**
   * @param {Event} Unmount event.
   * @private
   */
  FileManager.prototype.onExternallyUnmounted_ = function(event) {
    if (event.mountPath == this.directoryModel_.getCurrentRootPath()) {
      if (this.closeOnUnmount_) {
        // If the file manager opened automatically when a usb drive inserted,
        // user have never changed current volume (that implies the current
        // directory is still on the device) then close this window.
        window.close();
      }
    }
  };

  /**
   * Show a modal-like file viewer/editor on top of the File Manager UI.
   *
   * @param {HTMLElement} popup Popup element.
   * @param {function} closeCallback Function to call after the popup is closed.
   *
   * @private
   */
  FileManager.prototype.openFilePopup_ = function(popup, closeCallback) {
    this.closeFilePopup_();
    this.filePopup_ = popup;
    this.filePopupCloseCallback_ = closeCallback;
    this.dialogDom_.appendChild(this.filePopup_);
    this.filePopup_.focus();
    this.document_.body.setAttribute('overlay-visible', '');
    this.document_.querySelector('#iframe-drag-area').hidden = false;
  };

  /**
   * @private
   */
  FileManager.prototype.closeFilePopup_ = function() {
    if (this.filePopup_) {
      this.document_.body.removeAttribute('overlay-visible');
      this.document_.querySelector('#iframe-drag-area').hidden = true;
      // The window resize would not be processed properly while the relevant
      // divs had 'display:none', force resize after the layout fired.
      setTimeout(this.onResize_.bind(this), 0);
      if (this.filePopup_.contentWindow &&
          this.filePopup_.contentWindow.unload) {
        this.filePopup_.contentWindow.unload();
      }

      if (this.filePopupCloseCallback_) {
        this.filePopupCloseCallback_();
        this.filePopupCloseCallback_ = null;
      }

      // These operations have to be in the end, otherwise v8 crashes on an
      // assert. See: crbug.com/224174.
      this.dialogDom_.removeChild(this.filePopup_);
      this.filePopup_ = null;
    }
  };

  FileManager.prototype.getAllUrlsInCurrentDirectory = function() {
    var urls = [];
    var fileList = this.directoryModel_.getFileList();
    for (var i = 0; i != fileList.length; i++) {
      urls.push(fileList.item(i).toURL());
    }
    return urls;
  };

  FileManager.prototype.isRenamingInProgress = function() {
    return !!this.renameInput_.currentEntry;
  };

  /**
   * @private
   */
  FileManager.prototype.focusCurrentList_ = function() {
    if (this.listType_ == FileManager.ListType.DETAIL)
      this.table_.focus();
    else  // this.listType_ == FileManager.ListType.THUMBNAIL)
      this.grid_.focus();
  };

  /**
   * Return full path of the current directory or null.
   * @return {?string} The full path of the current directory.
   */
  FileManager.prototype.getCurrentDirectory = function() {
    return this.directoryModel_ &&
        this.directoryModel_.getCurrentDirPath();
  };

  /**
   * Return URL of the current directory or null.
   * @return {string} URL representing the current directory.
   */
  FileManager.prototype.getCurrentDirectoryURL = function() {
    return this.directoryModel_ &&
        this.directoryModel_.getCurrentDirectoryURL();
  };

  /**
   * Return DirectoryEntry of the current directory or null.
   * @return {DirectoryEntry} DirectoryEntry of the current directory. Returns
   *     null if the directory model is not ready or the current directory is
   *     not set.
   */
  FileManager.prototype.getCurrentDirectoryEntry = function() {
    return this.directoryModel_ &&
        this.directoryModel_.getCurrentDirEntry();
  };

  /**
   * Deletes the selected file and directories recursively.
   */
  FileManager.prototype.deleteSelection = function() {
    // TODO(mtomasz): Remove this temporary dialog. crbug.com/167364
    var entries = this.getSelection().entries;
    var message = entries.length == 1 ?
        strf('GALLERY_CONFIRM_DELETE_ONE', entries[0].name) :
        strf('GALLERY_CONFIRM_DELETE_SOME', entries.length);
    this.confirm.show(message, function() {
      this.copyManager_.deleteEntries(entries);
    }.bind(this));
  };

  /**
   * Shows the share dialog for the selected file or directory.
   */
  FileManager.prototype.shareSelection = function() {
    var entries = this.getSelection().entries;
    if (entries.length != 1) {
      console.warn('Unable to share multiple items at once.');
      return;
    }
    this.shareDialog_.show(entries[0], function() {
      this.error.show(str('SHARE_ERROR'));
    }.bind(this));
  };

  /**
   * Folder shared feature is under development and hidden behind flag. This
   * method returns if the feature is explicitly enabled by the flag or not.
   * TODO(yoshiki): Remove this after launching folder feature feature.
   *
   * @return {boolena} True if the flag is enabled.
   */
  FileManager.prototype.isFolderShortcutsEnabled = function() {
    // TODO(yoshiki): Remove this method in M31.
    return true;
  };

  /**
   * Creates a folder shortcut.
   * @param {string} path A shortcut which refers to |path| to be created.
   */
  FileManager.prototype.createFolderShortcut = function(path) {
    // Duplicate entry.
    if (this.folderShortcutExists(path))
      return;

    this.folderShortcutsModel_.add(path);
  };

  /**
   * Checkes if the shortcut which refers to the given folder exists or not.
   * @param {string} path Path of the folder to be checked.
   */
  FileManager.prototype.folderShortcutExists = function(path) {
    return this.folderShortcutsModel_.exists(path);
  };

  /**
   * Removes the folder shortcut.
   * @param {string} path The shortcut which refers to |path| is to be removed.
   */
  FileManager.prototype.removeFolderShortcut = function(path) {
    this.folderShortcutsModel_.remove(path);
  };

  /**
   * Blinks the selection. Used to give feedback when copying or cutting the
   * selection.
   */
  FileManager.prototype.blinkSelection = function() {
    var selection = this.getSelection();
    if (!selection || selection.totalCount == 0)
      return;

    for (var i = 0; i < selection.entries.length; i++) {
      var selectedIndex = selection.indexes[i];
      var listItem = this.currentList_.getListItemByIndex(selectedIndex);
      if (listItem)
        this.blinkListItem_(listItem);
    }
  };

  /**
   * @param {Element} listItem List item element.
   * @private
   */
  FileManager.prototype.blinkListItem_ = function(listItem) {
    listItem.classList.add('blink');
    setTimeout(function() {
      listItem.classList.remove('blink');
    }, 100);
  };

  /**
   * @private
   */
  FileManager.prototype.selectDefaultPathInFilenameInput_ = function() {
    var input = this.filenameInput_;
    input.focus();
    var selectionEnd = input.value.lastIndexOf('.');
    if (selectionEnd == -1) {
      input.select();
    } else {
      input.selectionStart = 0;
      input.selectionEnd = selectionEnd;
    }
    // Clear, so we never do this again.
    this.defaultPath = '';
  };

  /**
   * Handles mouse click or tap.
   *
   * @param {Event} event The click event.
   * @private
   */
  FileManager.prototype.onDetailClick_ = function(event) {
    if (this.isRenamingInProgress()) {
      // Don't pay attention to clicks during a rename.
      return;
    }

    var listItem = this.findListItemForEvent_(event);
    var selection = this.getSelection();
    if (!listItem || !listItem.selected || selection.totalCount != 1) {
      return;
    }

    // React on double click, but only if both clicks hit the same item.
    // TODO(mtomasz): Simplify it, and use a double click handler if possible.
    var clickNumber = (this.lastClickedItem_ == listItem) ? 2 : undefined;
    this.lastClickedItem_ = listItem;

    if (event.detail != clickNumber)
      return;

    var entry = selection.entries[0];
    if (entry.isDirectory) {
      this.onDirectoryAction(entry);
    } else {
      this.dispatchSelectionAction_();
    }
  };

  /**
   * @private
   */
  FileManager.prototype.dispatchSelectionAction_ = function() {
    if (this.dialogType == DialogType.FULL_PAGE) {
      var tasks = this.getSelection().tasks;
      if (tasks) tasks.executeDefault();
      return true;
    }
    if (!this.okButton_.disabled) {
      this.onOk_();
      return true;
    }
    return false;
  };

  /**
   * Executes directory action (i.e. changes directory).
   *
   * @param {DirectoryEntry} entry Directory entry to which directory should be
   *                               changed.
   */
  FileManager.prototype.onDirectoryAction = function(entry) {
    var mountError = this.volumeManager_.getMountError(
        PathUtil.getRootPath(entry.fullPath));
    if (mountError == VolumeManager.Error.UNKNOWN_FILESYSTEM) {
      return this.butterBar_.show(ButterBar.Mode.ERROR,
                                  str('UNKNOWN_FILESYSTEM_WARNING'));
    } else if (mountError == VolumeManager.Error.UNSUPPORTED_FILESYSTEM) {
      return this.butterBar_.show(ButterBar.Mode.ERROR,
                                  str('UNSUPPORTED_FILESYSTEM_WARNING'));
    }

    return this.directoryModel_.changeDirectory(entry.fullPath);
  };

  /**
   * Update the window title.
   * @private
   */
  FileManager.prototype.updateTitle_ = function() {
    if (this.dialogType != DialogType.FULL_PAGE)
      return;

    var path = this.getCurrentDirectory();
    var rootPath = PathUtil.getRootPath(path);
    this.document_.title = PathUtil.getRootLabel(rootPath) +
                           path.substring(rootPath.length);
  };

  /**
   * Updates search box value when directory gets changed.
   * @private
   */
  FileManager.prototype.updateSearchBoxOnDirChange_ = function() {
    if (!this.searchBox_.disabled) {
      this.searchBox_.value = '';
      this.updateSearchBoxStyles_();
    }
  };

  /**
   * Update the gear menu.
   * @private
   */
  FileManager.prototype.updateGearMenu_ = function() {
    var hideItemsForDrive = !this.isOnDrive();
    this.syncButton.hidden = hideItemsForDrive;
    this.hostedButton.hidden = hideItemsForDrive;
    this.document_.getElementById('drive-separator').hidden =
        hideItemsForDrive;

    // If volume has changed, then fetch remaining space data.
    if (this.previousRootUrl_ != this.directoryModel_.getCurrentMountPointUrl())
      this.refreshRemainingSpace_(true);  // Show loading caption.

    this.previousRootUrl_ = this.directoryModel_.getCurrentMountPointUrl();
  };

  /**
   * Refreshes space info of the current volume.
   * @param {boolean} showLoadingCaption Whether show loading caption or not.
   * @private
   */
  FileManager.prototype.refreshRemainingSpace_ = function(showLoadingCaption) {
    var volumeSpaceInfoLabel =
        this.dialogDom_.querySelector('#volume-space-info-label');
    var volumeSpaceInnerBar =
        this.dialogDom_.querySelector('#volume-space-info-bar');
    var volumeSpaceOuterBar =
        this.dialogDom_.querySelector('#volume-space-info-bar').parentNode;

    volumeSpaceInnerBar.setAttribute('pending', '');

    if (showLoadingCaption) {
      volumeSpaceInfoLabel.innerText = str('WAITING_FOR_SPACE_INFO');
      volumeSpaceInnerBar.style.width = '100%';
    }

    var currentMountPointUrl = this.directoryModel_.getCurrentMountPointUrl();
    chrome.fileBrowserPrivate.getSizeStats(
        currentMountPointUrl, function(result) {
          if (this.directoryModel_.getCurrentMountPointUrl() !=
              currentMountPointUrl)
            return;
          updateSpaceInfo(result,
                          volumeSpaceInnerBar,
                          volumeSpaceInfoLabel,
                          volumeSpaceOuterBar);
        }.bind(this));
  };

  /**
   * Update the UI when the current directory changes.
   *
   * @param {cr.Event} event The directory-changed event.
   * @private
   */
  FileManager.prototype.onDirectoryChanged_ = function(event) {
    this.selectionHandler_.onFileSelectionChanged();
    this.updateSearchBoxOnDirChange_();
    util.updateAppState(this.getCurrentDirectory());

    if (this.closeOnUnmount_ && !event.initial &&
        PathUtil.getRootPath(event.previousDirEntry.fullPath) !=
            PathUtil.getRootPath(event.newDirEntry.fullPath)) {
      this.closeOnUnmount_ = false;
    }

    this.updateCommands();
    this.updateUnformattedDriveStatus_();
    this.updateTitle_();
    this.updateGearMenu_();
  };

  /**
   * Updates commands' states by emiting canExecute events. Should be used
   * only if there is need to reevaluate states without an user action, eg.
   * external events.
   */
  FileManager.prototype.updateCommands = function() {
    var commands = this.dialogDom_.querySelectorAll('command');
    for (var i = 0; i < commands.length; i++) {
      // Commands may not have been decorated yet.
      if (commands[i].canExecuteChange)
        commands[i].canExecuteChange();
    }
  };

  // TODO(haruki): Rename this method. "Drive" here does not refer
  // "Google Drive".
  FileManager.prototype.updateUnformattedDriveStatus_ = function() {
    var volumeInfo = this.volumeManager_.getVolumeInfo_(
        PathUtil.getRootPath(this.directoryModel_.getCurrentRootPath()));

    if (volumeInfo.error) {
      this.dialogDom_.setAttribute('unformatted', '');

      var errorNode = this.dialogDom_.querySelector('#format-panel > .error');
      if (volumeInfo.error == VolumeManager.Error.UNSUPPORTED_FILESYSTEM) {
        errorNode.textContent = str('UNSUPPORTED_FILESYSTEM_WARNING');
      } else {
        errorNode.textContent = str('UNKNOWN_FILESYSTEM_WARNING');
      }

      // Update 'canExecute' for format command so the format button's disabled
      // property is properly set.
      this.updateCommands();
    } else {
      this.dialogDom_.removeAttribute('unformatted');
    }
  };

  FileManager.prototype.findListItemForEvent_ = function(event) {
    return this.findListItemForNode_(event.touchedElement || event.srcElement);
  };

  FileManager.prototype.findListItemForNode_ = function(node) {
    var item = this.currentList_.getListItemAncestor(node);
    // TODO(serya): list should check that.
    return item && this.currentList_.isItem(item) ? item : null;
  };

  /**
   * Unload handler for the page.  May be called manually for the file picker
   * dialog, because it closes by calling extension API functions that do not
   * return.
   *
   * @private
   */
  FileManager.prototype.onUnload_ = function() {
    if (this.directoryModel_)
      this.directoryModel_.dispose();
    if (this.filePopup_ &&
        this.filePopup_.contentWindow &&
        this.filePopup_.contentWindow.unload)
      this.filePopup_.contentWindow.unload(true /* exiting */);
    if (this.butterBar_)
      this.butterBar_.dispose();
    if (this.copyManager_) {
      if (this.onCopyProgressBound_) {
        this.copyManager_.removeEventListener(
            'copy-progress', this.onCopyProgressBound_);
      }
      if (this.onCopyManagerEntryChangedBound_) {
        this.copyManager_.removeEventListener(
            'entry-changed', this.onCopyManagerEntryChangedBound_);
      }
    }
  };

  FileManager.prototype.initiateRename = function() {
    var item = this.currentList_.ensureLeadItemExists();
    if (!item)
      return;
    var label = item.querySelector('.filename-label');
    var input = this.renameInput_;

    input.value = label.textContent;
    label.parentNode.setAttribute('renaming', '');
    label.parentNode.appendChild(input);
    input.focus();
    var selectionEnd = input.value.lastIndexOf('.');
    if (selectionEnd == -1) {
      input.select();
    } else {
      input.selectionStart = 0;
      input.selectionEnd = selectionEnd;
    }

    // This has to be set late in the process so we don't handle spurious
    // blur events.
    input.currentEntry = this.currentList_.dataModel.item(item.listIndex);
  };

  /**
   * @type {Event} Key event.
   * @private
   */
  FileManager.prototype.onRenameInputKeyDown_ = function(event) {
    if (!this.isRenamingInProgress())
      return;

    // Do not move selection or lead item in list during rename.
    if (event.keyIdentifier == 'Up' || event.keyIdentifier == 'Down') {
      event.stopPropagation();
    }

    switch (util.getKeyModifiers(event) + event.keyCode) {
      case '27':  // Escape
        this.cancelRename_();
        event.preventDefault();
        break;

      case '13':  // Enter
        this.commitRename_();
        event.preventDefault();
        break;
    }
  };

  /**
   * @type {Event} Blur event.
   * @private
   */
  FileManager.prototype.onRenameInputBlur_ = function(event) {
    if (this.isRenamingInProgress() && !this.renameInput_.validation_)
      this.commitRename_();
  };

  /**
   * @private
   */
  FileManager.prototype.commitRename_ = function() {
    var input = this.renameInput_;
    var entry = input.currentEntry;
    var newName = input.value;

    if (newName == entry.name) {
      this.cancelRename_();
      return;
    }

    var nameNode = this.findListItemForNode_(this.renameInput_).
                   querySelector('.filename-label');

    input.validation_ = true;
    var validationDone = function(valid) {
      input.validation_ = false;
      // Alert dialog restores focus unless the item removed from DOM.
      if (this.document_.activeElement != input)
        this.cancelRename_();
      if (!valid)
        return;

      // Validation succeeded. Do renaming.

      this.cancelRename_();
      // Optimistically apply new name immediately to avoid flickering in
      // case of success.
      nameNode.textContent = newName;

      this.directoryModel_.doesExist(entry, newName, function(exists, isFile) {
        if (!exists) {
          var onError = function(err) {
            this.alert.show(strf('ERROR_RENAMING', entry.name,
                                 util.getFileErrorString(err.code)));
          }.bind(this);
          this.directoryModel_.renameEntry(entry, newName, onError.bind(this));
        } else {
          nameNode.textContent = entry.name;
          var message = isFile ? 'FILE_ALREADY_EXISTS' :
                                 'DIRECTORY_ALREADY_EXISTS';
          this.alert.show(strf(message, newName));
        }
      }.bind(this));
    };

    // TODO(haruki): this.getCurrentDirectoryURL() might not return the actual
    // parent if the directory content is a search result. Fix it to do proper
    // validation.
    this.validateFileName_(this.getCurrentDirectoryURL(),
                           newName,
                           validationDone.bind(this));
  };

  /**
   * @private
   */
  FileManager.prototype.cancelRename_ = function() {
    this.renameInput_.currentEntry = null;

    var parent = this.renameInput_.parentNode;
    if (parent) {
      parent.removeAttribute('renaming');
      parent.removeChild(this.renameInput_);
    }
  };

  /**
   * @param {Event} Key event.
   * @private
   */
  FileManager.prototype.onFilenameInputKeyDown_ = function(event) {
    var enabled = this.selectionHandler_.updateOkButton();
    if (enabled &&
        (util.getKeyModifiers(event) + event.keyCode) == '13' /* Enter */)
      this.onOk_();
  };

  /**
   * @param {Event} Focus event.
   * @private
   */
  FileManager.prototype.onFilenameInputFocus_ = function(event) {
    var input = this.filenameInput_;

    // On focus we want to select everything but the extension, but
    // Chrome will select-all after the focus event completes.  We
    // schedule a timeout to alter the focus after that happens.
    setTimeout(function() {
        var selectionEnd = input.value.lastIndexOf('.');
        if (selectionEnd == -1) {
          input.select();
        } else {
          input.selectionStart = 0;
          input.selectionEnd = selectionEnd;
        }
    }, 0);
  };

  /**
   * @private
   */
  FileManager.prototype.onScanStarted_ = function() {
    if (this.scanInProgress_ && !this.scanUpdatedAtLeastOnceOrCompleted_) {
      this.table_.list.endBatchUpdates();
      this.grid_.endBatchUpdates();
    }

    this.updateCommands();
    this.table_.list.startBatchUpdates();
    this.grid_.startBatchUpdates();
    this.scanInProgress_ = true;

    this.scanUpdatedAtLeastOnceOrCompleted_ = false;
    if (this.scanCompletedTimer_) {
      clearTimeout(this.scanCompletedTimer_);
      this.scanCompletedTimer_ = null;
    }

    if (this.scanUpdatedTimer_) {
      clearTimeout(this.scanUpdatedTimer_);
      this.scanUpdatedTimer_ = null;
    }

    if (!this.spinner_.hidden) {
      this.cancelSpinnerTimeout_();
      this.showSpinner_(false);
      this.showSpinnerTimeout_ =
          setTimeout(this.showSpinner_.bind(this, true), 500);
    }
  };

  /**
   * @private
   */
  FileManager.prototype.onScanCompleted_ = function() {
    if (!this.scanInProgress_) {
      console.error('Scan-completed event recieved. But scan is not started.');
      return;
    }

    this.updateCommands();
    this.hideSpinnerLater_();
    this.refreshCurrentDirectoryMetadata_();

    // To avoid flickering postpone updating the ui by a small amount of time.
    // There is a high chance, that metadata will be received within 50 ms.
    this.scanCompletedTimer_ = setTimeout(function() {
      // Check if batch updates are already finished by onScanUpdated_().
      if (this.scanUpdatedAtLeastOnceOrCompleted_)
        return;
      this.scanUpdatedAtLeastOnceOrCompleted_ = true;
      this.scanInProgress_ = false;
      if (this.scanUpdatedTimer_) {
        clearTimeout(this.scanUpdatedTimer_);
        this.scanUpdatedTimer_ = null;
      }
      this.table_.list.endBatchUpdates();
      this.grid_.endBatchUpdates();
      this.updateMiddleBarVisibility_();
      this.scanCompletedTimer_ = null;
    }.bind(this), 50);
  };

  /**
   * @private
   */
  FileManager.prototype.onScanUpdated_ = function() {
    if (!this.scanInProgress_) {
      console.error('Scan-updated event recieved. But scan is not started.');
      return;
    }

    // We need to hide the spinner only once.
    if (this.scanUpdatedAtLeastOnceOrCompleted_ || this.scanUpdatedTimer_)
      return;

    // Show contents incrementally by finishing batch updated, but only after
    // 200ms elapsed, to avoid flickering when it is not necessary.
    this.scanUpdatedTimer_ = setTimeout(function() {
      // We need to hide the spinner only once.
      if (this.scanUpdatedAtLeastOnceOrCompleted_)
        return;
      if (this.scanCompletedTimer_) {
        clearTimeout(this.scanCompletedTimer_);
        this.scanCompletedTimer_ = null;
      }
      this.scanUpdatedAtLeastOnceOrCompleted_ = true;
      this.scanInProgress_ = false;
      this.hideSpinnerLater_();
      this.table_.list.endBatchUpdates();
      this.grid_.endBatchUpdates();
      this.updateMiddleBarVisibility_();
      this.scanUpdatedTimer_ = null;
    }.bind(this), 200);
  };

  /**
   * @private
   */
  FileManager.prototype.onScanCancelled_ = function() {
    if (!this.scanInProgress_) {
      console.error('Scan-cancelled event recieved. But scan is not started.');
      return;
    }

    this.updateCommands();
    this.hideSpinnerLater_();
    if (this.scanCompletedTimer_) {
      clearTimeout(this.scanCompletedTimer_);
      this.scanCompletedTimer_ = null;
    }
    if (this.scanUpdatedTimer_) {
      clearTimeout(this.scanUpdatedTimer_);
      this.scanUpdatedTimer_ = null;
    }
    // Finish unfinished batch updates.
    if (!this.scanUpdatedAtLeastOnceOrCompleted_) {
      this.scanUpdatedAtLeastOnceOrCompleted_ = true;
      this.scanInProgress_ = false;
      this.table_.list.endBatchUpdates();
      this.grid_.endBatchUpdates();
      this.updateMiddleBarVisibility_();
    }
  };

  /**
   * @private
   */
  FileManager.prototype.cancelSpinnerTimeout_ = function() {
    if (this.showSpinnerTimeout_) {
      clearTimeout(this.showSpinnerTimeout_);
      this.showSpinnerTimeout_ = null;
    }
  };

  /**
   * @private
   */
  FileManager.prototype.hideSpinnerLater_ = function() {
    this.cancelSpinnerTimeout_();
    this.showSpinner_(false);
  };

  /**
   * @param {boolean} on True to show, false to hide.
   * @private
   */
  FileManager.prototype.showSpinner_ = function(on) {
    if (on && this.directoryModel_ && this.directoryModel_.isScanning())
      this.spinner_.hidden = false;

    if (!on && (!this.directoryModel_ ||
                !this.directoryModel_.isScanning() ||
                this.directoryModel_.getFileList().length != 0)) {
      this.spinner_.hidden = true;
    }
  };

  FileManager.prototype.createNewFolder = function() {
    var defaultName = str('DEFAULT_NEW_FOLDER_NAME');

    // Find a name that doesn't exist in the data model.
    var files = this.directoryModel_.getFileList();
    var hash = {};
    for (var i = 0; i < files.length; i++) {
      var name = files.item(i).name;
      // Filtering names prevents from conflicts with prototype's names
      // and '__proto__'.
      if (name.substring(0, defaultName.length) == defaultName)
        hash[name] = 1;
    }

    var baseName = defaultName;
    var separator = '';
    var suffix = '';
    var index = '';

    var advance = function() {
      separator = ' (';
      suffix = ')';
      index++;
    };

    var current = function() {
      return baseName + separator + index + suffix;
    };

    // Accessing hasOwnProperty is safe since hash properties filtered.
    while (hash.hasOwnProperty(current())) {
      advance();
    }

    var self = this;
    var list = self.currentList_;
    var tryCreate = function() {
      self.directoryModel_.createDirectory(current(),
                                           onSuccess, onError);
    };

    var onSuccess = function(entry) {
      metrics.recordUserAction('CreateNewFolder');
      list.selectedItem = entry;
      self.initiateRename();
    };

    var onError = function(error) {
      self.alert.show(strf('ERROR_CREATING_FOLDER', current(),
                           util.getFileErrorString(error.code)));
    };

    tryCreate();
  };

  /**
   * @param {Event} event Click event.
   * @private
   */
  FileManager.prototype.onDetailViewButtonClick_ = function(event) {
    this.setListType(FileManager.ListType.DETAIL);
    this.currentList_.focus();
  };

  /**
   * @param {Event} event Click event.
   * @private
   */
  FileManager.prototype.onThumbnailViewButtonClick_ = function(event) {
    this.setListType(FileManager.ListType.THUMBNAIL);
    this.currentList_.focus();
  };

  /**
   * KeyDown event handler for the document.
   * @param {Event} event Key event.
   * @private
   */
  FileManager.prototype.onKeyDown_ = function(event) {
    if (event.srcElement === this.renameInput_) {
      // Ignore keydown handler in the rename input box.
      return;
    }

    switch (util.getKeyModifiers(event) + event.keyCode) {
      case 'Ctrl-17':  // Ctrl => Show hidden setting
        this.setCtrlKeyPressed_(true);
        return;

      case 'Ctrl-190':  // Ctrl-. => Toggle filter files.
        this.fileFilter_.setFilterHidden(
            !this.fileFilter_.isFilterHiddenOn());
        event.preventDefault();
        return;

      case '27':  // Escape => Cancel dialog.
        if (this.copyManager_ && this.copyManager_.isRunning()) {
          // If there is a copy in progress, ESC will cancel it.
          event.preventDefault();
          this.copyManager_.requestCancel();
          return;
        }

        if (this.dialogType != DialogType.FULL_PAGE) {
          // If there is nothing else for ESC to do, then cancel the dialog.
          event.preventDefault();
          this.cancelButton_.click();
        }
        break;
    }
  };

  /**
   * KeyUp event handler for the document.
   * @param {Event} event Key event.
   * @private
   */
  FileManager.prototype.onKeyUp_ = function(event) {
    if (event.srcElement === this.renameInput_) {
      // Ignore keydown handler in the rename input box.
      return;
    }

    switch (util.getKeyModifiers(event) + event.keyCode) {
      case '17':  // Ctrl => Hide hidden setting
        this.setCtrlKeyPressed_(false);
        return;
    }
  };

  /**
   * KeyDown event handler for the div#list-container element.
   * @param {Event} event Key event.
   * @private
   */
  FileManager.prototype.onListKeyDown_ = function(event) {
    if (event.srcElement.tagName == 'INPUT') {
      // Ignore keydown handler in the rename input box.
      return;
    }

    switch (util.getKeyModifiers(event) + event.keyCode) {
      case '8':  // Backspace => Up one directory.
        event.preventDefault();
        var path = this.getCurrentDirectory();
        if (path && !PathUtil.isRootPath(path)) {
          var path = path.replace(/\/[^\/]+$/, '');
          this.directoryModel_.changeDirectory(path);
        }
        break;

      case '13':  // Enter => Change directory or perform default action.
        // TODO(dgozman): move directory action to dispatchSelectionAction.
        var selection = this.getSelection();
        if (selection.totalCount == 1 &&
            selection.entries[0].isDirectory &&
            this.dialogType != DialogType.SELECT_FOLDER &&
            this.dialogType != DialogType.SELECT_UPLOAD_FOLDER) {
          event.preventDefault();
          this.onDirectoryAction(selection.entries[0]);
        } else if (this.dispatchSelectionAction_()) {
          event.preventDefault();
        }
        break;
    }

    switch (event.keyIdentifier) {
      case 'Home':
      case 'End':
      case 'Up':
      case 'Down':
      case 'Left':
      case 'Right':
        // When navigating with keyboard we hide the distracting mouse hover
        // highlighting until the user moves the mouse again.
        this.setNoHover_(true);
        break;
    }
  };

  /**
   * Suppress/restore hover highlighting in the list container.
   * @param {boolean} on True to temporarity hide hover state.
   * @private
   */
  FileManager.prototype.setNoHover_ = function(on) {
    if (on) {
      this.listContainer_.classList.add('nohover');
    } else {
      this.listContainer_.classList.remove('nohover');
    }
  };

  /**
   * KeyPress event handler for the div#list-container element.
   * @param {Event} event Key event.
   * @private
   */
  FileManager.prototype.onListKeyPress_ = function(event) {
    if (event.srcElement.tagName == 'INPUT') {
      // Ignore keypress handler in the rename input box.
      return;
    }

    if (event.ctrlKey || event.metaKey || event.altKey)
      return;

    var now = new Date();
    var char = String.fromCharCode(event.charCode).toLowerCase();
    var text = now - this.textSearchState_.date > 1000 ? '' :
        this.textSearchState_.text;
    this.textSearchState_ = {text: text + char, date: now};

    this.doTextSearch_();
  };

  /**
   * Mousemove event handler for the div#list-container element.
   * @param {Event} event Mouse event.
   * @private
   */
  FileManager.prototype.onListMouseMove_ = function(event) {
    // The user grabbed the mouse, restore the hover highlighting.
    this.setNoHover_(false);
  };

  /**
   * Performs a 'text search' - selects a first list entry with name
   * starting with entered text (case-insensitive).
   * @private
   */
  FileManager.prototype.doTextSearch_ = function() {
    var text = this.textSearchState_.text;
    if (!text)
      return;

    var dm = this.directoryModel_.getFileList();
    for (var index = 0; index < dm.length; ++index) {
      var name = dm.item(index).name;
      if (name.substring(0, text.length).toLowerCase() == text) {
        this.currentList_.selectionModel.selectedIndexes = [index];
        return;
      }
    }

    this.textSearchState_.text = '';
  };

  /**
   * Handle a click of the cancel button.  Closes the window.
   * TODO(jamescook): Make unload handler work automatically, crbug.com/104811
   *
   * @param {Event} event The click event.
   * @private
   */
  FileManager.prototype.onCancel_ = function(event) {
    chrome.fileBrowserPrivate.cancelDialog();
    this.onUnload_();
    window.close();
  };

  /**
   * Resolves selected file urls returned from an Open dialog.
   *
   * For drive files this involves some special treatment.
   * Starts getting drive files if needed.
   *
   * @param {Array.<string>} fileUrls Drive URLs.
   * @param {function(Array.<string>)} callback To be called with fixed URLs.
   * @private
   */
  FileManager.prototype.resolveSelectResults_ = function(fileUrls, callback) {
    if (this.isOnDrive()) {
      chrome.fileBrowserPrivate.getDriveFiles(
        fileUrls,
        function(localPaths) {
          callback(fileUrls);
        });
    } else {
      callback(fileUrls);
    }
  };

  /**
   * Closes this modal dialog with some files selected.
   * TODO(jamescook): Make unload handler work automatically, crbug.com/104811
   * @param {Object} selection Contains urls, filterIndex and multiple fields.
   * @private
   */
  FileManager.prototype.callSelectFilesApiAndClose_ = function(selection) {
    var self = this;
    function callback() {
      self.onUnload_();
      window.close();
    }
    if (selection.multiple) {
      chrome.fileBrowserPrivate.selectFiles(
          selection.urls, this.params_.shouldReturnLocalPath, callback);
    } else {
      var forOpening = (this.dialogType != DialogType.SELECT_SAVEAS_FILE);
      chrome.fileBrowserPrivate.selectFile(
          selection.urls[0], selection.filterIndex, forOpening,
          this.params_.shouldReturnLocalPath, callback);
    }
  };

  /**
   * Tries to close this modal dialog with some files selected.
   * Performs preprocessing if needed (e.g. for Drive).
   * @param {Object} selection Contains urls, filterIndex and multiple fields.
   * @private
   */
  FileManager.prototype.selectFilesAndClose_ = function(selection) {
    if (!this.isOnDrive() ||
        this.dialogType == DialogType.SELECT_SAVEAS_FILE) {
      setTimeout(this.callSelectFilesApiAndClose_.bind(this, selection), 0);
      return;
    }

    var shade = this.document_.createElement('div');
    shade.className = 'shade';
    var footer = this.dialogDom_.querySelector('.button-panel');
    var progress = footer.querySelector('.progress-track');
    progress.style.width = '0%';
    var cancelled = false;

    var progressMap = {};
    var filesStarted = 0;
    var filesTotal = selection.urls.length;
    for (var index = 0; index < selection.urls.length; index++) {
      progressMap[selection.urls[index]] = -1;
    }
    var lastPercent = 0;
    var bytesTotal = 0;
    var bytesDone = 0;

    var onFileTransfersUpdated = function(statusList) {
      for (var index = 0; index < statusList.length; index++) {
        var status = statusList[index];
        var escaped = encodeURI(status.fileUrl);
        if (!(escaped in progressMap)) continue;
        if (status.total == -1) continue;

        var old = progressMap[escaped];
        if (old == -1) {
          // -1 means we don't know file size yet.
          bytesTotal += status.total;
          filesStarted++;
          old = 0;
        }
        bytesDone += status.processed - old;
        progressMap[escaped] = status.processed;
      }

      var percent = bytesTotal == 0 ? 0 : bytesDone / bytesTotal;
      // For files we don't have information about, assume the progress is zero.
      percent = percent * filesStarted / filesTotal * 100;
      // Do not decrease the progress. This may happen, if first downloaded
      // file is small, and the second one is large.
      lastPercent = Math.max(lastPercent, percent);
      progress.style.width = lastPercent + '%';
    }.bind(this);

    var setup = function() {
      this.document_.querySelector('.dialog-container').appendChild(shade);
      setTimeout(function() { shade.setAttribute('fadein', 'fadein') }, 100);
      footer.setAttribute('progress', 'progress');
      this.cancelButton_.removeEventListener('click', this.onCancelBound_);
      this.cancelButton_.addEventListener('click', onCancel);
      chrome.fileBrowserPrivate.onFileTransfersUpdated.addListener(
          onFileTransfersUpdated);
    }.bind(this);

    var cleanup = function() {
      shade.parentNode.removeChild(shade);
      footer.removeAttribute('progress');
      this.cancelButton_.removeEventListener('click', onCancel);
      this.cancelButton_.addEventListener('click', this.onCancelBound_);
      chrome.fileBrowserPrivate.onFileTransfersUpdated.removeListener(
          onFileTransfersUpdated);
    }.bind(this);

    var onCancel = function() {
      cancelled = true;
      // According to API cancel may fail, but there is no proper UI to reflect
      // this. So, we just silently assume that everything is cancelled.
      chrome.fileBrowserPrivate.cancelFileTransfers(
          selection.urls, function(response) {});
      cleanup();
    }.bind(this);

    var onResolved = function(resolvedUrls) {
      if (cancelled) return;
      cleanup();
      selection.urls = resolvedUrls;
      // Call next method on a timeout, as it's unsafe to
      // close a window from a callback.
      setTimeout(this.callSelectFilesApiAndClose_.bind(this, selection), 0);
    }.bind(this);

    var onProperties = function(properties) {
      for (var i = 0; i < properties.length; i++) {
        if (!properties[i] || properties[i].present) {
          // For files already in GCache, we don't get any transfer updates.
          filesTotal--;
        }
      }
      this.resolveSelectResults_(selection.urls, onResolved);
    }.bind(this);

    setup();
    this.metadataCache_.get(selection.urls, 'drive', onProperties);
  };

  /**
   * Handle a click of the ok button.
   *
   * The ok button has different UI labels depending on the type of dialog, but
   * in code it's always referred to as 'ok'.
   *
   * @param {Event} event The click event.
   * @private
   */
  FileManager.prototype.onOk_ = function(event) {
    if (this.dialogType == DialogType.SELECT_SAVEAS_FILE) {
      // Save-as doesn't require a valid selection from the list, since
      // we're going to take the filename from the text input.
      var filename = this.filenameInput_.value;
      if (!filename)
        throw new Error('Missing filename!');

      var directory = this.getCurrentDirectoryEntry();
      var currentDirUrl = directory.toURL();
      if (currentDirUrl.charAt(currentDirUrl.length - 1) != '/')
        currentDirUrl += '/';
      this.validateFileName_(currentDirUrl, filename, function(isValid) {
        if (!isValid)
          return;

        if (util.isFakeDirectoryEntry(directory)) {
          // Can't save a file into a fake directory.
          return;
        }

        var selectFileAndClose = function() {
          this.selectFilesAndClose_({
            urls: [currentDirUrl + encodeURIComponent(filename)],
            multiple: false,
            filterIndex: this.getSelectedFilterIndex_(filename)
          });
        }.bind(this);

        directory.getFile(
            filename, {create: false},
            function(entry) {
              // An existing file is found. Show confirmation dialog to
              // overwrite it. If the user select "OK" on the dialog, save it.
              this.confirm.show(strf('CONFIRM_OVERWRITE_FILE', filename),
                                selectFileAndClose);
            }.bind(this),
            function(error) {
              if (error.code == FileError.NOT_FOUND_ERR) {
                // The file does not exist, so it should be ok to create a
                // new file.
                selectFileAndClose();
                return;
              }
              if (error.code == FileError.TYPE_MISMATCH_ERR) {
                // An directory is found.
                // Do not allow to overwrite directory.
                this.alert.show(strf('DIRECTORY_ALREADY_EXISTS', filename));
                return;
              }

              // Unexpected error.
              console.error('File save failed: ' + error.code);
            }.bind(this));
      }.bind(this));
      return;
    }

    var files = [];
    var selectedIndexes = this.currentList_.selectionModel.selectedIndexes;

    if ((this.dialogType == DialogType.SELECT_FOLDER ||
         this.dialogType == DialogType.SELECT_UPLOAD_FOLDER) &&
        selectedIndexes.length == 0) {
      var url = this.getCurrentDirectoryURL();
      var singleSelection = {
        urls: [url],
        multiple: false,
        filterIndex: this.getSelectedFilterIndex_()
      };
      this.selectFilesAndClose_(singleSelection);
      return;
    }

    // All other dialog types require at least one selected list item.
    // The logic to control whether or not the ok button is enabled should
    // prevent us from ever getting here, but we sanity check to be sure.
    if (!selectedIndexes.length)
      throw new Error('Nothing selected!');

    var dm = this.directoryModel_.getFileList();
    for (var i = 0; i < selectedIndexes.length; i++) {
      var entry = dm.item(selectedIndexes[i]);
      if (!entry) {
        console.error('Error locating selected file at index: ' + i);
        continue;
      }

      files.push(entry.toURL());
    }

    // Multi-file selection has no other restrictions.
    if (this.dialogType == DialogType.SELECT_OPEN_MULTI_FILE) {
      var multipleSelection = {
        urls: files,
        multiple: true
      };
      this.selectFilesAndClose_(multipleSelection);
      return;
    }

    // Everything else must have exactly one.
    if (files.length > 1)
      throw new Error('Too many files selected!');

    var selectedEntry = dm.item(selectedIndexes[0]);

    if (this.dialogType == DialogType.SELECT_FOLDER ||
        this.dialogType == DialogType.SELECT_UPLOAD_FOLDER) {
      if (!selectedEntry.isDirectory)
        throw new Error('Selected entry is not a folder!');
    } else if (this.dialogType == DialogType.SELECT_OPEN_FILE) {
      if (!selectedEntry.isFile)
        throw new Error('Selected entry is not a file!');
    }

    var singleSelection = {
      urls: [files[0]],
      multiple: false,
      filterIndex: this.getSelectedFilterIndex_()
    };
    this.selectFilesAndClose_(singleSelection);
  };

  /**
   * Verifies the user entered name for file or folder to be created or
   * renamed to. Name restrictions must correspond to File API restrictions
   * (see DOMFilePath::isValidPath). Curernt WebKit implementation is
   * out of date (spec is
   * http://dev.w3.org/2009/dap/file-system/file-dir-sys.html, 8.3) and going to
   * be fixed. Shows message box if the name is invalid.
   *
   * It also verifies if the name length is in the limit of the filesystem.
   *
   * @param {string} parentUrl The URL of the parent directory entry.
   * @param {string} name New file or folder name.
   * @param {function} onDone Function to invoke when user closes the
   *    warning box or immediatelly if file name is correct. If the name was
   *    valid it is passed true, and false otherwise.
   * @private
   */
  FileManager.prototype.validateFileName_ = function(parentUrl, name, onDone) {
    var msg;
    var testResult = /[\/\\\<\>\:\?\*\"\|]/.exec(name);
    if (testResult) {
      msg = strf('ERROR_INVALID_CHARACTER', testResult[0]);
    } else if (/^\s*$/i.test(name)) {
      msg = str('ERROR_WHITESPACE_NAME');
    } else if (/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$/i.test(name)) {
      msg = str('ERROR_RESERVED_NAME');
    } else if (this.fileFilter_.isFilterHiddenOn() && name[0] == '.') {
      msg = str('ERROR_HIDDEN_NAME');
    }

    if (msg) {
      this.alert.show(msg, function() {
        onDone(false);
      });
      return;
    }

    var self = this;
    chrome.fileBrowserPrivate.validatePathNameLength(
        parentUrl, name, function(valid) {
          if (!valid) {
            self.alert.show(str('ERROR_LONG_NAME'),
                            function() { onDone(false); });
          } else {
            onDone(true);
          }
        });
  };

  /**
   * Handler invoked on preference setting in drive context menu.
   *
   * @param {string} pref  The preference to alter.
   * @param {boolean} inverted Invert the value if true.
   * @param {Event}  event The click event.
   * @private
   */
  FileManager.prototype.onDrivePrefClick_ = function(pref, inverted, event) {
    var newValue = !event.target.hasAttribute('checked');
    if (newValue)
      event.target.setAttribute('checked', 'checked');
    else
      event.target.removeAttribute('checked');

    var changeInfo = {};
    changeInfo[pref] = inverted ? !newValue : newValue;
    chrome.fileBrowserPrivate.setPreferences(changeInfo);
  };

  /**
   * Invoked when the search box is changed.
   *
   * @param {Event} event The changed event.
   * @private
   */
  FileManager.prototype.onSearchBoxUpdate_ = function(event) {
    var searchString = this.searchBox_.value;

    this.updateSearchBoxStyles_();
    if (this.isOnDrive()) {
      // When the search text is changed, finishes the search and showes back
      // the last directory by passing an empty string to
      // {@code DirectoryModel.search()}.
      if (this.directoryModel_.isSearching() &&
          this.lastSearchQuery_ != searchString) {
        this.doSearch('');
      }

      // On drive, incremental search is not invoked since we have an auto-
      // complete suggestion instead.
      return;
    }

    this.search_(searchString);
  };

  /**
   * Handles special keys such as Escape on the search box.
   *
   * @param {Event} event The keydown event.
   * @private
   */
  FileManager.prototype.onSearchBoxKeyDown_ = function(event) {
    // Handle only Esc key now.
    if (event.keyCode != 27) return;
    if (this.searchBox_.value) return;
    var currentList = this.listType_ == FileManager.ListType.DETAIL ?
        this.table_.list : this.grid_;
    currentList.focus();
    if (currentList.dataModel.length != 0 &&
        currentList.selectionModel.selectedIndex == -1) {
      currentList.selectionModel.selectedIndex = 0;
    }
  };

  /**
   * Updates search box's CSS classes.
   * These classes are refered from CSS.
   *
   * @private
   */
  FileManager.prototype.updateSearchBoxStyles_ = function() {
    var TEXT_BOX_PADDING = 16; // in px.
    this.searchBoxWrapper_.classList.toggle('has-text',
                                            !!this.searchBox_.value);
    var width = this.searchTextMeasure_.getWidth(this.searchBox_.value) +
                TEXT_BOX_PADDING;
    this.searchBox_.style.width = width + 'px';
  };

  /**
   * Search files and update the list with the search result.
   *
   * @param {string} searchString String to be searched with.
   * @private
   */
  FileManager.prototype.search_ = function(searchString) {
    var noResultsDiv = this.document_.getElementById('no-search-results');

    var reportEmptySearchResults = function() {
      if (this.directoryModel_.getFileList().length === 0) {
        // The string 'SEARCH_NO_MATCHING_FILES_HTML' may contain HTML tags,
        // hence we escapes |searchString| here.
        var html = strf('SEARCH_NO_MATCHING_FILES_HTML',
                        util.htmlEscape(searchString));
        noResultsDiv.innerHTML = html;
        noResultsDiv.setAttribute('show', 'true');
      } else {
        noResultsDiv.removeAttribute('show');
      }
    };

    var hideNoResultsDiv = function() {
      noResultsDiv.removeAttribute('show');
    };

    this.doSearch(searchString,
                  reportEmptySearchResults.bind(this),
                  hideNoResultsDiv.bind(this));
  };

  /**
   * Performs search and displays results.
   *
   * @param {string} query Query that will be searched for.
   * @param {function()=} opt_onSearchRescan Function that will be called when
   *     the search directory is rescanned (i.e. search results are displayed).
   * @param {function()=} opt_onClearSearch Function to be called when search
   *     state gets cleared.
   */
  FileManager.prototype.doSearch = function(
      searchString, opt_onSearchRescan, opt_onClearSearch) {
    var onSearchRescan = opt_onSearchRescan || function() {};
    var onClearSearch = opt_onClearSearch || function() {};

    this.lastSearchQuery_ = searchString;
    this.directoryModel_.search(searchString, onSearchRescan, onClearSearch);
  };

  /**
   * Requests autocomplete suggestions for files on Drive.
   * Once the suggestions are returned, the autocomplete popup will show up.
   *
   * @param {string} query The text to autocomplete from.
   * @private
   */
  FileManager.prototype.requestAutocompleteSuggestions_ = function(query) {
    query = query.trimLeft();

    // Only Drive supports auto-compelete
    if (!this.isOnDrive())
      return;

    // Remember the most recent query. If there is an other request in progress,
    // then it's result will be discarded and it will call a new request for
    // this query.
    this.lastAutocompleteQuery_ = query;
    if (this.autocompleteSuggestionsBusy_)
      return;

    // The autocomplete list should be resized and repositioned here as the
    // search box is resized when it's focused.
    this.autocompleteList_.syncWidthAndPositionToInput();

    if (!query) {
      this.autocompleteList_.suggestions = [];
      return;
    }

    var headerItem = {isHeaderItem: true, searchQuery: query};
    if (!this.autocompleteList_.dataModel ||
        this.autocompleteList_.dataModel.length == 0)
      this.autocompleteList_.suggestions = [headerItem];
    else
      // Updates only the head item to prevent a flickering on typing.
      this.autocompleteList_.dataModel.splice(0, 1, headerItem);

    this.autocompleteSuggestionsBusy_ = true;

    var searchParams = {
      'query': query,
      'types': 'ALL',
      'maxResults': 4
    };
    chrome.fileBrowserPrivate.searchDriveMetadata(
      searchParams,
      function(suggestions) {
        this.autocompleteSuggestionsBusy_ = false;

        // Discard results for previous requests and fire a new search
        // for the most recent query.
        if (query != this.lastAutocompleteQuery_) {
          this.requestAutocompleteSuggestions_(this.lastAutocompleteQuery_);
          return;
        }

        // Keeps the items in the suggestion list.
        this.autocompleteList_.suggestions = [headerItem].concat(suggestions);
      }.bind(this));
  };

  /**
   * Creates a ListItem element for autocomple.
   *
   * @param {Object} item An object representing a suggestion.
   * @return {HTMLElement} Element containing the autocomplete suggestions.
   * @private
   */
  FileManager.prototype.createAutocompleteListItem_ = function(item) {
    var li = new cr.ui.ListItem();
    li.itemInfo = item;

    var icon = this.document_.createElement('div');
    icon.className = 'detail-icon';

    var text = this.document_.createElement('div');
    text.className = 'detail-text';

    if (item.isHeaderItem) {
      icon.setAttribute('search-icon');
      text.innerHTML =
          strf('SEARCH_DRIVE_HTML', util.htmlEscape(item.searchQuery));
    } else {
      var iconType = FileType.getIcon(item.entry);
      icon.setAttribute('file-type-icon', iconType);
      // highlightedBaseName is a piece of HTML with meta characters properly
      // escaped. See the comment at fileBrowserPrivate.searchDriveMetadata().
      text.innerHTML = item.highlightedBaseName;
    }
    li.appendChild(icon);
    li.appendChild(text);
    return li;
  };

  /**
   * Opens the currently selected suggestion item.
   * @private
   */
  FileManager.prototype.openAutocompleteSuggestion_ = function() {
    var selectedItem = this.autocompleteList_.selectedItem;

    // If the entry is the search item or no entry is selected, just change to
    // the search result.
    if (!selectedItem || selectedItem.isHeaderItem) {
      var query = selectedItem ?
          selectedItem.searchQuery : this.searchBox_.value;
      this.search_(query);
      return;
    }

    var entry = selectedItem.entry;
    // If the entry is a directory, just change the directory.
    if (entry.isDirectory) {
      this.onDirectoryAction(entry);
      return;
    }

    var urls = [entry.toURL()];
    var self = this;

    // To open a file, first get the mime type.
    this.metadataCache_.get(urls, 'drive', function(props) {
      var mimeType = props[0].contentMimeType || '';
      var mimeTypes = [mimeType];
      var openIt = function() {
        if (self.dialogType == DialogType.FULL_PAGE) {
          var tasks = new FileTasks(self);
          tasks.init(urls, mimeTypes);
          tasks.executeDefault();
        } else {
          self.onOk_();
        }
      };

      // Change the current directory to the directory that contains the
      // selected file. Note that this is necessary for an image or a video,
      // which should be opened in the gallery mode, as the gallery mode
      // requires the entry to be in the current directory model. For
      // consistency, the current directory is always changed regardless of
      // the file type.
      entry.getParent(function(parent) {
        var onDirectoryChanged = function(event) {
          self.directoryModel_.removeEventListener('scan-completed',
                                                   onDirectoryChanged);
          self.directoryModel_.selectEntry(entry.name);
          openIt();
        }
        // changeDirectory() returns immediately. We should wait until the
        // directory scan is complete.
        self.directoryModel_.addEventListener('scan-completed',
                                              onDirectoryChanged);
        self.directoryModel_.changeDirectory(
          parent.fullPath,
          function() {
            // Remove the listner if the change directory failed.
            self.directoryModel_.removeEventListener('scan-completed',
                                                     onDirectoryChanged);
          });
      });
    });
  };

  /**
   * Opens the default app change dialog.
   */
  FileManager.prototype.showChangeDefaultAppPicker = function() {
    var onActionsReady = function(actions, rememberedActionId) {
      var items = [];
      var defaultIndex = -1;
      for (var i = 0; i < actions.length; i++) {
        if (actions[i].hidden)
          continue;
        var title = actions[i].title;
        if (actions[i].id == rememberedActionId) {
          title += ' ' + loadTimeData.getString('DEFAULT_ACTION_LABEL');
          defaultIndex = i;
        }
        var item = {
          id: actions[i].id,
          label: title,
          class: actions[i].class,
          iconUrl: actions[i].icon100
        };
        items.push(item);
      }
      this.defaultTaskPicker.show(
          str('CHANGE_DEFAULT_APP_BUTTON_LABEL'),
          '',
          items,
          defaultIndex,
          function(action) {
            ActionChoiceUtil.setRememberedActionId(action.id);
          });
    }.bind(this);

    ActionChoiceUtil.getDefinedActions(loadTimeData, function(actions) {
      ActionChoiceUtil.getRememberedActionId(function(actionId) {
        onActionsReady(actions, actionId);
      });
    });
  };

  FileManager.prototype.decorateSplitter = function(splitterElement) {
    var self = this;

    var Splitter = cr.ui.Splitter;

    var customSplitter = cr.ui.define('div');

    customSplitter.prototype = {
      __proto__: Splitter.prototype,

      handleSplitterDragStart: function(e) {
        Splitter.prototype.handleSplitterDragStart.apply(this, arguments);
        this.ownerDocument.documentElement.classList.add('col-resize');
      },

      handleSplitterDragMove: function(deltaX) {
        Splitter.prototype.handleSplitterDragMove.apply(this, arguments);
        self.onResize_();
      },

      handleSplitterDragEnd: function(e) {
        Splitter.prototype.handleSplitterDragEnd.apply(this, arguments);
        this.ownerDocument.documentElement.classList.remove('col-resize');
      }
    };

    customSplitter.decorate(splitterElement);
  };

  /**
   * Updates default action menu item to match passed taskItem (icon,
   * label and action).
   *
   * @param {Object} defaultItem - taskItem to match.
   * @param {boolean} isMultiple - if multiple tasks available.
   */
  FileManager.prototype.updateContextMenuActionItems = function(defaultItem,
                                                                isMultiple) {
    if (defaultItem) {
      if (defaultItem.iconType) {
        this.defaultActionMenuItem_.style.backgroundImage = '';
        this.defaultActionMenuItem_.setAttribute('file-type-icon',
                                                 defaultItem.iconType);
      } else if (defaultItem.iconUrl) {
        this.defaultActionMenuItem_.style.backgroundImage =
            'url(' + defaultItem.iconUrl + ')';
      } else {
        this.defaultActionMenuItem_.style.backgroundImage = '';
      }

      this.defaultActionMenuItem_.label = defaultItem.title;
      this.defaultActionMenuItem_.taskId = defaultItem.taskId;
    }

    var defaultActionSeparator =
        this.dialogDom_.querySelector('#default-action-separator');

    this.openWithCommand_.canExecuteChange();
    this.openWithCommand_.setHidden(!(defaultItem && isMultiple));
    this.defaultActionMenuItem_.hidden = !defaultItem;
    defaultActionSeparator.hidden = !defaultItem;
  };


  /**
   * Window beforeunload handler.
   * @return {string} Message to show. Ignored when running as a packaged app.
   * @private
   */
  FileManager.prototype.onBeforeUnload_ = function() {
    if (this.filePopup_ &&
        this.filePopup_.contentWindow &&
        this.filePopup_.contentWindow.beforeunload) {
      // The gallery might want to prevent the unload if it is busy.
      return this.filePopup_.contentWindow.beforeunload();
    }
    return null;
  };

  /**
   * @return {FileSelection} Selection object.
   */
  FileManager.prototype.getSelection = function() {
    return this.selectionHandler_.selection;
  };

  /**
   * @return {ArrayDataModel} File list.
   */
  FileManager.prototype.getFileList = function() {
    return this.directoryModel_.getFileList();
  };

  /**
   * @return {cr.ui.List} Current list object.
   */
  FileManager.prototype.getCurrentList = function() {
    return this.currentList_;
  };

  /**
   * Retrieve the preferences of the files.app. This method caches the result
   * and returns it unless opt_update is true.
   * @param {function(Object.<string, *>)} callback Callback to get the
   *     preference.
   * @param {boolean=} opt_update If is's true, don't use the cache and
   *     retrieve latest preference. Default is false.
   * @private
   */
  FileManager.prototype.getPreferences_ = function(callback, opt_update) {
    if (!opt_update && this.preferences_ !== undefined) {
      callback(this.preferences_);
      return;
    }

    chrome.fileBrowserPrivate.getPreferences(function(prefs) {
      this.preferences_ = prefs;
      callback(prefs);
    }.bind(this));
  };

  /**
   * Set the flag expressing whether the ctrl key is pressed or not.
   * @param {boolean} flag New value of the flag
   * @private
   */
  FileManager.prototype.setCtrlKeyPressed_ = function(flag) {
    this.ctrlKeyPressed_ = flag;
    // Before the DOM is constructed, the key event can be handled.
    var cacheClearCommand =
        this.document_.querySelector('#drive-clear-local-cache');
    if (cacheClearCommand)
      cacheClearCommand.canExecuteChange();
  };
})();
