Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / resources / net_internals / main.js
blob7c5d6551b5fc2a26851f2c8256a69d09aba32c9e
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  * Dictionary of constants (Initialized soon after loading by data from browser,
7  * updated on load log).  The *Types dictionaries map strings to numeric IDs,
8  * while the *TypeNames are the other way around.
9  */
10 var EventType = null;
11 var EventTypeNames = null;
12 var EventPhase = null;
13 var EventSourceType = null;
14 var EventSourceTypeNames = null;
15 var ClientInfo = null;
16 var NetError = null;
17 var QuicError = null;
18 var QuicRstStreamError = null;
19 var LoadFlag = null;
20 var CertStatusFlag = null;
21 var LoadState = null;
22 var AddressFamily = null;
23 var SdchProblemCode = null;
24 var DataReductionProxyBypassEventType = null;
26 /**
27  * Dictionary of all constants, used for saving log files.
28  */
29 var Constants = null;
31 /**
32  * Object to communicate between the renderer and the browser.
33  * @type {!BrowserBridge}
34  */
35 var g_browser = null;
37 /**
38  * This class is the root view object of the page.  It owns all the other
39  * views, and manages switching between them.  It is also responsible for
40  * initializing the views and the BrowserBridge.
41  */
42 var MainView = (function() {
43   'use strict';
45   // We inherit from WindowView
46   var superClass = WindowView;
48   /**
49    * Main entry point. Called once the page has loaded.
50    *  @constructor
51    */
52   function MainView() {
53     assertFirstConstructorCall(MainView);
55     if (hasTouchScreen())
56       document.body.classList.add('touch');
58     // This must be initialized before the tabs, so they can register as
59     // observers.
60     g_browser = BrowserBridge.getInstance();
62     // This must be the first constants observer, so other constants observers
63     // can safely use the globals, rather than depending on walking through
64     // the constants themselves.
65     g_browser.addConstantsObserver(new ConstantsObserver());
67     // Create the tab switcher.
68     this.initTabs_();
70     // Cut out a small vertical strip at the top of the window, to display
71     // a high level status (i.e. if we are capturing events, or displaying a
72     // log file). Below it we will position the main tabs and their content
73     // area.
74     this.topBarView_ = TopBarView.getInstance(this);
75     var verticalSplitView = new VerticalSplitView(
76         this.topBarView_, this.tabSwitcher_);
78     superClass.call(this, verticalSplitView);
80     // Trigger initial layout.
81     this.resetGeometry();
83     window.onhashchange = this.onUrlHashChange_.bind(this);
85     // Select the initial view based on the current URL.
86     window.onhashchange();
88     // Tell the browser that we are ready to start receiving log events.
89     this.topBarView_.switchToSubView('capture');
90     g_browser.sendReady();
91   }
93   cr.addSingletonGetter(MainView);
95   // Tracks if we're viewing a loaded log file, so views can behave
96   // appropriately.  Global so safe to call during construction.
97   var isViewingLoadedLog = false;
99   MainView.isViewingLoadedLog = function() {
100     return isViewingLoadedLog;
101   };
103   MainView.prototype = {
104     // Inherit the superclass's methods.
105     __proto__: superClass.prototype,
107     // This is exposed both so the log import/export code can enumerate all the
108     // tabs, and for testing.
109     tabSwitcher: function() {
110       return this.tabSwitcher_;
111     },
113     /**
114      * Prevents receiving/sending events to/from the browser, so loaded data
115      * will not be mixed with current Chrome state.  Also hides any interactive
116      * HTML elements that send messages to the browser.  Cannot be undone
117      * without reloading the page.  Must be called before passing loaded data
118      * to the individual views.
119      *
120      * @param {string} opt_fileName The name of the log file that has been
121      *     loaded, if we're loading a log file.
122      */
123     onLoadLog: function(opt_fileName) {
124       isViewingLoadedLog = true;
126       this.stopCapturing();
127       if (opt_fileName != undefined) {
128         // If there's a file name, a log file was loaded, so swap out the status
129         // bar to indicate we're no longer capturing events.  Also disable
130         // hiding cookies, so if the log dump has them, they'll be displayed.
131         this.topBarView_.switchToSubView('loaded').setFileName(opt_fileName);
132         $(ExportView.PRIVACY_STRIPPING_CHECKBOX_ID).checked = false;
133         SourceTracker.getInstance().setPrivacyStripping(false);
134       } else {
135         // Otherwise, the "Stop Capturing" button was presumably pressed.
136         // Don't disable hiding cookies, so created log dumps won't have them,
137         // unless the user toggles the option.
138         this.topBarView_.switchToSubView('halted');
139       }
140     },
142     switchToViewOnlyMode: function() {
143       // Since this won't be dumped to a file, we don't want to remove
144       // cookies and credentials.
145       log_util.createLogDumpAsync('', log_util.loadLogFile, false);
146     },
148     stopCapturing: function() {
149       g_browser.disable();
150       document.styleSheets[0].insertRule(
151           '.hide-when-not-capturing { display: none; }', 0);
152     },
154     initTabs_: function() {
155       this.tabIdToHash_ = {};
156       this.hashToTabId_ = {};
158       this.tabSwitcher_ = new TabSwitcherView(
159           $(TopBarView.TAB_DROPDOWN_MENU_ID),
160           this.onTabSwitched_.bind(this));
162       // Helper function to add a tab given the class for a view singleton.
163       var addTab = function(viewClass) {
164         var tabId = viewClass.TAB_ID;
165         var tabHash = viewClass.TAB_HASH;
166         var tabName = viewClass.TAB_NAME;
167         var view = viewClass.getInstance();
169         if (!tabId || !view || !tabHash || !tabName) {
170           throw Error('Invalid view class for tab');
171         }
173         if (tabHash.charAt(0) != '#') {
174           throw Error('Tab hashes must start with a #');
175         }
177         this.tabSwitcher_.addTab(tabId, view, tabName);
178         this.tabIdToHash_[tabId] = tabHash;
179         this.hashToTabId_[tabHash] = tabId;
180       }.bind(this);
182       // Populate the main tabs.  Even tabs that don't contain information for
183       // the running OS should be created, so they can load log dumps from other
184       // OSes.
185       addTab(CaptureView);
186       addTab(ExportView);
187       addTab(ImportView);
188       addTab(ProxyView);
189       addTab(EventsView);
190       addTab(WaterfallView);
191       addTab(TimelineView);
192       addTab(DnsView);
193       addTab(SocketsView);
194       addTab(SpdyView);
195       addTab(QuicView);
196       addTab(SdchView);
197       addTab(HttpCacheView);
198       addTab(ModulesView);
199       addTab(HSTSView);
200       addTab(BandwidthView);
201       addTab(PrerenderView);
202       addTab(CrosView);
204       this.tabSwitcher_.showMenuItem(CrosView.TAB_ID, cr.isChromeOS);
205     },
207     /**
208      * This function is called by the tab switcher when the current tab has been
209      * changed. It will update the current URL to reflect the new active tab,
210      * so the back can be used to return to previous view.
211      */
212     onTabSwitched_: function(oldTabId, newTabId) {
213       // Update data needed by newly active tab, as it may be
214       // significantly out of date.
215       if (g_browser)
216         g_browser.checkForUpdatedInfo();
218       // Change the URL to match the new tab.
220       var newTabHash = this.tabIdToHash_[newTabId];
221       var parsed = parseUrlHash_(window.location.hash);
222       if (parsed.tabHash != newTabHash) {
223         window.location.hash = newTabHash;
224       }
225     },
227     onUrlHashChange_: function() {
228       var parsed = parseUrlHash_(window.location.hash);
230       if (!parsed)
231         return;
233       if (!parsed.tabHash) {
234         // Default to the export tab.
235         parsed.tabHash = ExportView.TAB_HASH;
236       }
238       var tabId = this.hashToTabId_[parsed.tabHash];
240       if (tabId) {
241         this.tabSwitcher_.switchToTab(tabId);
242         if (parsed.parameters) {
243           var view = this.tabSwitcher_.getTabView(tabId);
244           view.setParameters(parsed.parameters);
245         }
246       }
247     },
249   };
251   /**
252    * Takes the current hash in form of "#tab&param1=value1&param2=value2&..."
253    * and parses it into a dictionary.
254    *
255    * Parameters and values are decoded with decodeURIComponent().
256    */
257   function parseUrlHash_(hash) {
258     var parameters = hash.split('&');
260     var tabHash = parameters[0];
261     if (tabHash == '' || tabHash == '#') {
262       tabHash = undefined;
263     }
265     // Split each string except the first around the '='.
266     var paramDict = null;
267     for (var i = 1; i < parameters.length; i++) {
268       var paramStrings = parameters[i].split('=');
269       if (paramStrings.length != 2)
270         continue;
271       if (paramDict == null)
272         paramDict = {};
273       var key = decodeURIComponent(paramStrings[0]);
274       var value = decodeURIComponent(paramStrings[1]);
275       paramDict[key] = value;
276     }
278     return {tabHash: tabHash, parameters: paramDict};
279   }
281   return MainView;
282 })();
284 function ConstantsObserver() {}
287  * Loads all constants from |constants|.  On failure, global dictionaries are
288  * not modifed.
289  * @param {Object} receivedConstants The map of received constants.
290  */
291 ConstantsObserver.prototype.onReceivedConstants = function(receivedConstants) {
292   if (!areValidConstants(receivedConstants))
293     return;
295   Constants = receivedConstants;
297   EventType = Constants.logEventTypes;
298   EventTypeNames = makeInverseMap(EventType);
299   EventPhase = Constants.logEventPhase;
300   EventSourceType = Constants.logSourceType;
301   EventSourceTypeNames = makeInverseMap(EventSourceType);
302   ClientInfo = Constants.clientInfo;
303   LoadFlag = Constants.loadFlag;
304   NetError = Constants.netError;
305   QuicError = Constants.quicError;
306   QuicRstStreamError = Constants.quicRstStreamError;
307   AddressFamily = Constants.addressFamily;
308   LoadState = Constants.loadState;
309   SdchProblemCode = Constants.sdchProblemCode;
310   DataReductionProxyBypassEventType =
311       Constants.dataReductionProxyBypassEventType;
312   DataReductionProxyBypassActionType =
313       Constants.dataReductionProxyBypassActionType;
314   // certStatusFlag may not be present when loading old log Files
315   if (typeof(Constants.certStatusFlag) == 'object')
316     CertStatusFlag = Constants.certStatusFlag;
317   else
318     CertStatusFlag = {};
320   timeutil.setTimeTickOffset(Constants.timeTickOffset);
324  * Returns true if it's given a valid-looking constants object.
325  * @param {Object} receivedConstants The received map of constants.
326  * @return {boolean} True if the |receivedConstants| object appears valid.
327  */
328 function areValidConstants(receivedConstants) {
329   return typeof(receivedConstants) == 'object' &&
330          typeof(receivedConstants.logEventTypes) == 'object' &&
331          typeof(receivedConstants.clientInfo) == 'object' &&
332          typeof(receivedConstants.logEventPhase) == 'object' &&
333          typeof(receivedConstants.logSourceType) == 'object' &&
334          typeof(receivedConstants.loadFlag) == 'object' &&
335          typeof(receivedConstants.netError) == 'object' &&
336          typeof(receivedConstants.addressFamily) == 'object' &&
337          typeof(receivedConstants.timeTickOffset) == 'string' &&
338          typeof(receivedConstants.logFormatVersion) == 'number';
342  * Returns the name for netError.
344  * Example: netErrorToString(-105) should return
345  * "ERR_NAME_NOT_RESOLVED".
346  * @param {number} netError The net error code.
347  * @return {string} The name of the given error.
348  */
349 function netErrorToString(netError) {
350   return getKeyWithValue(NetError, netError);
354  * Returns the name for quicError.
356  * Example: quicErrorToString(25) should return
357  * "TIMED_OUT".
358  * @param {number} quicError The QUIC error code.
359  * @return {string} The name of the given error.
360  */
361 function quicErrorToString(quicError) {
362   return getKeyWithValue(QuicError, quicError);
366  * Returns the name for quicRstStreamError.
368  * Example: quicRstStreamErrorToString(3) should return
369  * "BAD_APPLICATION_PAYLOAD".
370  * @param {number} quicRstStreamError The QUIC RST_STREAM error code.
371  * @return {string} The name of the given error.
372  */
373 function quicRstStreamErrorToString(quicRstStreamError) {
374   return getKeyWithValue(QuicRstStreamError, quicRstStreamError);
378  * Returns a string representation of |family|.
379  * @param {number} family An AddressFamily
380  * @return {string} A representation of the given family.
381  */
382 function addressFamilyToString(family) {
383   var str = getKeyWithValue(AddressFamily, family);
384   // All the address family start with ADDRESS_FAMILY_*.
385   // Strip that prefix since it is redundant and only clutters the output.
386   return str.replace(/^ADDRESS_FAMILY_/, '');
390  * Returns the name for sdchProblemCode.
392  * Example: sdchProblemCodeToString(5) should return
393  * "DECODE_BODY_ERROR".
394  * @param {number} sdchProblemCode The SDCH problem code.
395  * @return {string} The name of the given problem code.
396  */
397 function sdchProblemCodeToString(sdchProblemCode) {
398   return getKeyWithValue(SdchProblemCode, sdchProblemCode);