// 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. */));
    cr.ui.decorate(this.gearButton_, cr.ui.MenuButton);
    this.dialogDom_.querySelector('#gear-menu').menuItemSelector =
      'menuitem, hr';

    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.navigationList_, this);

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

    CommandUtil.registerCommand(this.dialogContainer_, 'format',
        Commands.formatCommand, this.navigationList_, 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();
  };
})();
