Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / resources / net_internals / export_view.js
blob72c5bb3cb21d67be98a51e9b7ce95241ff1ad99e
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 /**
6  * This view displays options for exporting the captured data.
7  */
8 var ExportView = (function() {
9   'use strict';
11   // We inherit from DivView.
12   var superClass = DivView;
14   /**
15    * @constructor
16    */
17   function ExportView() {
18     assertFirstConstructorCall(ExportView);
20     // Call superclass's constructor.
21     superClass.call(this, ExportView.MAIN_BOX_ID);
23     var privacyStrippingCheckbox = $(ExportView.PRIVACY_STRIPPING_CHECKBOX_ID);
24     privacyStrippingCheckbox.onclick =
25         this.onSetPrivacyStripping_.bind(this, privacyStrippingCheckbox);
27     this.saveFileButton_ = $(ExportView.SAVE_FILE_BUTTON_ID);
28     this.saveFileButton_.onclick = this.onSaveFile_.bind(this);
29     this.saveStatusText_ = $(ExportView.SAVE_STATUS_TEXT_ID);
31     this.userCommentsTextArea_ = $(ExportView.USER_COMMENTS_TEXT_AREA_ID);
33     // Track blob for previous log dump so it can be revoked when a new dump is
34     // saved.
35     this.lastBlobURL_ = null;
37     // Cached copy of the last loaded log dump, for use when exporting.
38     this.loadedLogDump_ = null;
39   }
41   ExportView.TAB_ID = 'tab-handle-export';
42   ExportView.TAB_NAME = 'Export';
43   ExportView.TAB_HASH = '#export';
45   // IDs for special HTML elements in export_view.html
46   ExportView.MAIN_BOX_ID = 'export-view-tab-content';
47   ExportView.DOWNLOAD_ANCHOR_ID = 'export-view-download-anchor';
48   ExportView.SAVE_FILE_BUTTON_ID = 'export-view-save-log-file';
49   ExportView.SAVE_STATUS_TEXT_ID = 'export-view-save-status-text';
50   ExportView.PRIVACY_STRIPPING_CHECKBOX_ID =
51       'export-view-privacy-stripping-checkbox';
52   ExportView.USER_COMMENTS_TEXT_AREA_ID = 'export-view-user-comments';
53   ExportView.PRIVACY_WARNING_ID = 'export-view-privacy-warning';
55   cr.addSingletonGetter(ExportView);
57   ExportView.prototype = {
58     // Inherit the superclass's methods.
59     __proto__: superClass.prototype,
61     /**
62      * Depending on the value of the checkbox, enables or disables stripping
63      * cookies and passwords from log dumps and displayed events.
64      */
65     onSetPrivacyStripping_: function(privacyStrippingCheckbox) {
66       SourceTracker.getInstance().setPrivacyStripping(
67           privacyStrippingCheckbox.checked);
68     },
70     /**
71      * When loading a log dump, cache it for future export and continue showing
72      * the ExportView.
73      */
74     onLoadLogFinish: function(polledData, tabData, logDump) {
75       this.loadedLogDump_ = logDump;
76       this.setUserComments_(logDump.userComments);
77       return true;
78     },
80     /**
81      * Sets the save to file status text, displayed below the save to file
82      * button, to |text|.  Also enables or disables the save button based on the
83      * value of |isSaving|, which must be true if the save process is still
84      * ongoing, and false when the operation has stopped, regardless of success
85      * of failure.
86      */
87     setSaveFileStatus: function(text, isSaving) {
88       this.enableSaveFileButton_(!isSaving);
89       this.saveStatusText_.textContent = text;
90     },
92     enableSaveFileButton_: function(enabled) {
93       this.saveFileButton_.disabled = !enabled;
94     },
96     showPrivacyWarning: function() {
97       setNodeDisplay($(ExportView.PRIVACY_WARNING_ID), true);
98       $(ExportView.PRIVACY_STRIPPING_CHECKBOX_ID).checked = false;
99       $(ExportView.PRIVACY_STRIPPING_CHECKBOX_ID).disabled = true;
101       // Updating the checkbox doesn't actually disable privacy stripping, since
102       // the onclick function will not be called.
103       this.onSetPrivacyStripping_($(ExportView.PRIVACY_STRIPPING_CHECKBOX_ID));
104     },
106     /**
107      * If not already busy saving a log dump, triggers asynchronous
108      * generation of log dump and starts waiting for it to complete.
109      */
110     onSaveFile_: function() {
111       if (this.saveFileButton_.disabled)
112         return;
114       // Clean up previous blob, if any, to reduce resource usage.
115       if (this.lastBlobURL_) {
116         window.URL.revokeObjectURL(this.lastBlobURL_);
117         this.lastBlobURL_ = null;
118       }
119       this.createLogDump_(this.onLogDumpCreated_.bind(this));
120     },
122     /**
123      * Creates a log dump, and either synchronously or asynchronously calls
124      * |callback| if it succeeds.  Separate from onSaveFile_ for unit tests.
125      */
126     createLogDump_: function(callback) {
127       // Get an explanation for the dump file (this is mandatory!)
128       var userComments = this.getNonEmptyUserComments_();
129       if (userComments == undefined) {
130         return;
131       }
133       this.setSaveFileStatus('Preparing data...', true);
135       var privacyStripping = SourceTracker.getInstance().getPrivacyStripping();
137       // If we have a cached log dump, update it synchronously.
138       if (this.loadedLogDump_) {
139         var dumpText = log_util.createUpdatedLogDump(userComments,
140                                                      this.loadedLogDump_,
141                                                      privacyStripping);
142         callback(dumpText);
143         return;
144       }
146       // Otherwise, poll information from the browser before creating one.
147       log_util.createLogDumpAsync(userComments,
148                                   callback,
149                                   privacyStripping);
150     },
152     /**
153      * Sets the user comments.
154      */
155     setUserComments_: function(userComments) {
156       this.userCommentsTextArea_.value = userComments;
157     },
159     /**
160      * Fetches the user comments for this dump. If none were entered, warns the
161      * user and returns undefined. Otherwise returns the comments text.
162      */
163     getNonEmptyUserComments_: function() {
164       var value = this.userCommentsTextArea_.value;
166       // Reset the class name in case we had hilighted it earlier.
167       this.userCommentsTextArea_.className = '';
169       // We don't accept empty explanations. We don't care what is entered, as
170       // long as there is something (a single whitespace would work).
171       if (value == '') {
172         // Put a big obnoxious red border around the text area.
173         this.userCommentsTextArea_.className =
174             'export-view-explanation-warning';
175         alert('Please fill in the text field!');
176         this.userCommentsTextArea_.focus();
177         return undefined;
178       }
180       return value;
181     },
183     /**
184      * Creates a blob url and starts downloading it.
185      */
186     onLogDumpCreated_: function(dumpText) {
187       var textBlob = new Blob([dumpText], {type: 'octet/stream'});
188       this.lastBlobURL_ = window.URL.createObjectURL(textBlob);
190       // Update the anchor tag and simulate a click on it to start the
191       // download.
192       var downloadAnchor = $(ExportView.DOWNLOAD_ANCHOR_ID);
193       downloadAnchor.href = this.lastBlobURL_;
194       downloadAnchor.click();
196       this.setSaveFileStatus('Dump successful', false);
197     }
198   };
200   return ExportView;
201 })();