Index: netlog_viewer/import_view.js |
diff --git a/netlog_viewer/import_view.js b/netlog_viewer/import_view.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..642079cc31b80f485ffcb992e613c0e09d4baa5c |
--- /dev/null |
+++ b/netlog_viewer/import_view.js |
@@ -0,0 +1,224 @@ |
+// 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); |
+ } |
+ |
+ ImportView.TAB_ID = 'tab-handle-import'; |
+ ImportView.TAB_NAME = 'Import'; |
+ ImportView.TAB_HASH = '#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'; |
+ |
+ // IDs for HTML elements pertaining to log dump information. |
+ ImportView.LOADED_INFO_NUMERIC_DATE_ID = 'import-view-numericDate'; |
+ ImportView.LOADED_INFO_NAME_ID = 'import-view-name'; |
+ ImportView.LOADED_INFO_VERSION_ID = 'import-view-version'; |
+ ImportView.LOADED_INFO_OFFICIAL_ID = 'import-view-official'; |
+ ImportView.LOADED_INFO_CL_ID = 'import-view-cl'; |
+ ImportView.LOADED_INFO_VERSION_MOD_ID = 'import-view-version-mod'; |
+ ImportView.LOADED_INFO_OS_TYPE_ID = 'import-view-os-type'; |
+ ImportView.LOADED_INFO_COMMAND_LINE_ID = 'import-view-command-line'; |
+ ImportView.LOADED_INFO_ACTIVE_FIELD_TRIAL_GROUPS_ID = |
+ 'import-view-activeFieldTrialGroups'; |
+ 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(polledData, unused, logDump) { |
+ $(ImportView.LOADED_INFO_NUMERIC_DATE_ID).textContent = |
+ timeutil.dateToString(new Date(Constants.clientInfo.numericDate)); |
+ $(ImportView.LOADED_INFO_NAME_ID).textContent = |
+ Constants.clientInfo.name; |
+ $(ImportView.LOADED_INFO_VERSION_ID).textContent = |
+ Constants.clientInfo.version; |
+ $(ImportView.LOADED_INFO_OFFICIAL_ID).textContent = |
+ Constants.clientInfo.official; |
+ $(ImportView.LOADED_INFO_CL_ID).textContent = |
+ Constants.clientInfo.cl; |
+ $(ImportView.LOADED_INFO_VERSION_MOD_ID).textContent = |
+ Constants.clientInfo.version_mod; |
+ $(ImportView.LOADED_INFO_OS_TYPE_ID).textContent = |
+ Constants.clientInfo.os_type; |
+ $(ImportView.LOADED_INFO_COMMAND_LINE_ID).textContent = |
+ Constants.clientInfo.command_line; |
+ $(ImportView.LOADED_INFO_ACTIVE_FIELD_TRIAL_GROUPS_ID).textContent = |
+ Constants.activeFieldTrialGroups; |
+ |
+ if (logDump.userComments != undefined) { |
+ $(ImportView.LOADED_INFO_USER_COMMENTS_ID).textContent = |
+ logDump.userComments; |
+ } else { |
+ $(ImportView.LOADED_INFO_USER_COMMENTS_ID).textContent = ''; |
+ } |
+ |
+ setNodeDisplay(this.loadedDiv_, true); |
+ 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; |
+ }, |
+ }; |
+ |
+ return ImportView; |
+})(); |
+ |