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