text: // 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.
  
  /**
   * This view displays options for importing data from a log file.
   */
  var ImportView = (function() {
    'use strict';
  
    // This is defined in index.html, but for all intents and purposes is part
    // of this view.
    var LOAD_LOG_FILE_DROP_TARGET_ID = 'import-view-drop-target';
  
    // We inherit from DivView.
    var superClass = DivView;
  
    /**
     * @constructor
     */
    function ImportView() {
      assertFirstConstructorCall(ImportView);
  
      // Call superclass's constructor.
      superClass.call(this, ImportView.MAIN_BOX_ID);
  
      this.loadedDiv_ = $(ImportView.LOADED_DIV_ID);
  
      this.loadFileElement_ = $(ImportView.LOAD_LOG_FILE_ID);
      this.loadFileElement_.onchange = this.logFileChanged.bind(this);
      this.loadStatusText_ = $(ImportView.LOAD_STATUS_TEXT_ID);
  
      var dropTarget = $(LOAD_LOG_FILE_DROP_TARGET_ID);
      dropTarget.ondragenter = this.onDrag.bind(this);
      dropTarget.ondragover = this.onDrag.bind(this);
      dropTarget.ondrop = this.onDrop.bind(this);
  
      this.loadedInfoBuildName_ = $(ImportView.LOADED_INFO_BUILD_NAME_ID);
      this.loadedInfoExportDate_ = $(ImportView.LOADED_INFO_EXPORT_DATE_ID);
      this.loadedInfoOsType_ = $(ImportView.LOADED_INFO_OS_TYPE_ID);
      this.loadedInfoCommandLine_ = $(ImportView.LOADED_INFO_COMMAND_LINE_ID);
      this.loadedInfoUserComments_ = $(ImportView.LOADED_INFO_USER_COMMENTS_ID);
    }
  
    ImportView.TAB_HANDLE_ID = 'tab-handle-import';
  
    // IDs for special HTML elements in import_view.html
    ImportView.MAIN_BOX_ID = 'import-view-tab-content';
    ImportView.LOADED_DIV_ID = 'import-view-loaded-div';
    ImportView.LOAD_LOG_FILE_ID = 'import-view-load-log-file';
    ImportView.LOAD_STATUS_TEXT_ID = 'import-view-load-status-text';
    ImportView.LOADED_INFO_EXPORT_DATE_ID = 'import-view-export-date';
    ImportView.LOADED_INFO_BUILD_NAME_ID = 'import-view-build-name';
    ImportView.LOADED_INFO_OS_TYPE_ID = 'import-view-os-type';
    ImportView.LOADED_INFO_COMMAND_LINE_ID = 'import-view-command-line';
    ImportView.LOADED_INFO_USER_COMMENTS_ID = 'import-view-user-comments';
  
    cr.addSingletonGetter(ImportView);
  
    ImportView.prototype = {
      // Inherit the superclass's methods.
      __proto__: superClass.prototype,
  
      /**
       * Called when a log file is loaded, after clearing the old log entries and
       * loading the new ones.  Returns true to indicate the view should
       * still be visible.
       */
      onLoadLogFinish: function(data, unused, logDump) {
        setNodeDisplay(this.loadedDiv_, true);
        this.updateLoadedClientInfo(logDump.userComments);
        return true;
      },
  
      /**
       * Called when something is dragged over the drop target.
       *
       * Returns false to cancel default browser behavior when a single file is
       * being dragged.  When this happens, we may not receive a list of files for
       * security reasons, which is why we allow the |files| array to be empty.
       */
      onDrag: function(event) {
        // NOTE: Use Array.prototype.indexOf here is necessary while WebKit
        // decides which type of data structure dataTransfer.types will be
        // (currently between DOMStringList and Array). These have different APIs
        // so assuming one type or the other was breaking things. See
        // http://crbug.com/115433. TODO(dbeam): Remove when standardized more.
        var indexOf = Array.prototype.indexOf;
        return indexOf.call(event.dataTransfer.types, 'Files') == -1 ||
               event.dataTransfer.files.length > 1;
      },
  
      /**
       * Called when something is dropped onto the drop target.  If it's a single
       * file, tries to load it as a log file.
       */
      onDrop: function(event) {
        var indexOf = Array.prototype.indexOf;
        if (indexOf.call(event.dataTransfer.types, 'Files') == -1 ||
            event.dataTransfer.files.length != 1) {
          return;
        }
        event.preventDefault();
  
        // Loading a log file may hide the currently active tab.  Switch to the
        // import tab to prevent this.
        document.location.hash = 'import';
  
        this.loadLogFile(event.dataTransfer.files[0]);
      },
  
      /**
       * Called when a log file is selected.
       *
       * Gets the log file from the input element and tries to read from it.
       */
      logFileChanged: function() {
        this.loadLogFile(this.loadFileElement_.files[0]);
      },
  
      /**
       * Attempts to read from the File |logFile|.
       */
      loadLogFile: function(logFile) {
        if (logFile) {
          this.setLoadFileStatus('Loading log...', true);
          var fileReader = new FileReader();
  
          fileReader.onload = this.onLoadLogFile.bind(this, logFile);
          fileReader.onerror = this.onLoadLogFileError.bind(this);
  
          fileReader.readAsText(logFile);
        }
      },
  
      /**
       * Displays an error message when unable to read the selected log file.
       * Also clears the file input control, so the same file can be reloaded.
       */
      onLoadLogFileError: function(event) {
        this.loadFileElement_.value = null;
        this.setLoadFileStatus(
            'Error ' + getKeyWithValue(FileError, event.target.error.code) +
                '.  Unable to read file.',
            false);
      },
  
      onLoadLogFile: function(logFile, event) {
        var result = log_util.loadLogFile(event.target.result, logFile.name);
        this.setLoadFileStatus(result, false);
      },
  
      /**
       * Sets the load from file status text, displayed below the load file
       * button, to |text|.  Also enables or disables the load buttons based on
       * the value of |isLoading|, which must be true if the load process is still
       * ongoing, and false when the operation has stopped, regardless of success
       * of failure.  Also, when loading is done, replaces the load button so the
       * same file can be loaded again.
       */
      setLoadFileStatus: function(text, isLoading) {
        this.enableLoadFileElement_(!isLoading);
        this.loadStatusText_.textContent = text;
  
        if (!isLoading) {
          // Clear the button, so the same file can be reloaded.  Recreating the
          // element seems to be the only way to do this.
          var loadFileElementId = this.loadFileElement_.id;
          var loadFileElementOnChange = this.loadFileElement_.onchange;
          this.loadFileElement_.outerHTML = this.loadFileElement_.outerHTML;
          this.loadFileElement_ = $(loadFileElementId);
          this.loadFileElement_.onchange = loadFileElementOnChange;
        }
  
        // Style the log output differently depending on what just happened.
        var pos = text.indexOf('Log loaded.');
        if (isLoading) {
          this.loadStatusText_.className = 'import-view-pending-log';
        } else if (pos == 0) {
          this.loadStatusText_.className = 'import-view-success-log';
        } else if (pos != -1) {
          this.loadStatusText_.className = 'import-view-warning-log';
        } else {
          this.loadStatusText_.className = 'import-view-error-log';
        }
      },
  
      enableLoadFileElement_: function(enabled) {
        this.loadFileElement_.disabled = !enabled;
      },
  
      /**
       * Prints some basic information about the environment when the log was
       * made.
       */
      updateLoadedClientInfo: function(userComments) {
        // Reset all the fields (in case we early-return).
        this.loadedInfoExportDate_.innerText = '';
        this.loadedInfoBuildName_.innerText = '';
        this.loadedInfoOsType_.innerText = '';
        this.loadedInfoCommandLine_.innerText = '';
        this.loadedInfoUserComments_.innerText = '';
  
        if (typeof(ClientInfo) != 'object')
          return;
  
        timeutil.addNodeWithDate(this.loadedInfoExportDate_,
                                 new Date(ClientInfo.numericDate));
  
        var buildName =
            ClientInfo.name +
            ' ' + ClientInfo.version +
            ' (' + ClientInfo.official +
            ' ' + ClientInfo.cl +
            ') ' + ClientInfo.version_mod;
  
        this.loadedInfoBuildName_.innerText = buildName;
  
        this.loadedInfoOsType_.innerText = ClientInfo.os_type;
        this.loadedInfoCommandLine_.innerText = ClientInfo.command_line;
  
        // User comments will not be available when dumped from command line.
        this.loadedInfoUserComments_.innerText = userComments || '';
      }
    };
  
    return ImportView;
  })();
  