Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / remoting / webapp / base / js / console_wrapper.js
blob6ceb659c8d89e7aba3d8066c2047ad5fb5038b64
1 // Copyright 2015 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  * @fileoverview
7  * Intercept and record various classes of log messages. By default, such
8  * messages will be reported by Chrome Developer Tools as coming from this
9  * file, making source-line hyperlinks useless. To fix this click the "gear"
10  * icon in Developer Tools, click "Manage framework blocking..." under
11  * "Sources" and add console_wrapper.js as a "Blackbox" component.
12  */
15 /** @suppress {duplicate} */
16 var remoting = remoting || {};
18 (function() {
20 /**
21  * @constructor
22  * @private
23  */
24 remoting.ConsoleWrapper = function() {
25   console.assert(instance_ == null,
26                  'Duplicate remoting.ConsoleWrapper constructor.');
27   /** @private {number} The number of log entries to save. */
28   this.historyMaxSize_ = 0;
29   /** @private {Array<remoting.ConsoleWrapper.LogEntry>} */
30   this.history_ = [];
31   /** @private {Object<function(*)>} */
32   this.savedMethods_ = {};
35 /**
36  * Activate the console wrapper for the specified log types.
37  *
38  * @param {number} historyMaxSize The number of log entries to keep.
39  * @param {...remoting.ConsoleWrapper.LogType} var_logTypes The log types to
40  *     intercept.
41  * @suppress {reportUnknownTypes}
42  */
43 remoting.ConsoleWrapper.prototype.activate =
44     function(historyMaxSize, var_logTypes) {
45   this.historyMaxSize_ = historyMaxSize;
46   this.history_ = [];
47   // Restore previous wrappers.
48   for (var key in remoting.ConsoleWrapper.LogType) {
49     var type = remoting.ConsoleWrapper.LogType[key];
50     if (this.savedMethods_[type]) {
51       console[type] = this.savedMethods_[type];
52       delete this.savedMethods_[type];
53     }
54   }
55   // Activate new wrappers
56   for (var i = 1; i < arguments.length; ++i) {
57     var type = arguments[i];
58     this.savedMethods_[type] = console[type];
59     console[arguments[i]] = this.recordAndLog_.bind(this, arguments[i]);
60   }
63 /**
64  * Deactivate the console wrapper for all log types.
65  */
66 remoting.ConsoleWrapper.prototype.deactivate = function() {
67   this.activate(0);
70 /**
71  * @return {Array<remoting.ConsoleWrapper.LogEntry>} The most recent log
72  *     entries as configured by activate().
73  */
74 remoting.ConsoleWrapper.prototype.getHistory = function() {
75   return this.history_;
78 /**
79  * @param {remoting.ConsoleWrapper.LogType} type The type of log.
80  * @param {...*} var_args The items to log.
81  * @private
82  * @suppress {reportUnknownTypes}
83  */
84 remoting.ConsoleWrapper.prototype.recordAndLog_ =
85     function(type, var_args) {
86   // Construct a new arguments array by removing the first argument.
87   var args = Array.prototype.slice.call(arguments, 1);
88   // Find the caller, ignoring the top-most stack frame.
89   var caller = new base.Callstack().callstack[1];
90   var location = 'unknown';
91   if (caller) {
92     location = caller.file + ':' + caller.line;
93   }
94   // Save to history.
95   if (this.historyMaxSize_ > 0) {
96     var log = {
97       type: type,
98       message: JSON.stringify(args),
99       caller: location,
100       timestamp: new Date()
101     };
102     // Only save assertions if they fail.
103     if (log.type != 'assert' || !args[0]) {
104       this.history_.push(log);
105       if (this.history_.length > this.historyMaxSize_) {
106         this.history_.shift();
107       }
108     }
109   }
110   // Log the message, appending the caller.
111   // TODO(jamiewalch): Make the caller gray so that it's less intrusive. This
112   // can be done using a %c formatter in the first argument, but care needs to
113   // be taken to support the multi-argument case.
114   args.push(location);
115   this.savedMethods_[type].apply(console, args);
119  * @type {remoting.ConsoleWrapper}
120  */
121 var instance_ = null;
124  * @return {remoting.ConsoleWrapper} The singleton ConsoleWrapper.
125  */
126 remoting.ConsoleWrapper.getInstance = function() {
127   if (!instance_) {
128     instance_ = new remoting.ConsoleWrapper();
129   }
130   return instance_;
133 })();
136  * @typedef {{type: string, message: string, caller: string, timestamp: Date}}
137  */
138 remoting.ConsoleWrapper.LogEntry;
141  * @enum {string} The log types that can be intercepted. These must match the
142  *     names of the corresponding console methods.
143  */
144 remoting.ConsoleWrapper.LogType = {
145   LOG: 'log',
146   WARN: 'warn',
147   ERROR: 'error',
148   ASSERT: 'assert'