Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / remoting / webapp / server_log_entry.js
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.
4
5 /**
6  * @fileoverview
7  * A class of server log entries.
8  */
9
10 'use strict';
11
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
14
15 /**
16  * @private
17  * @constructor
18  */
19 remoting.ServerLogEntry = function() {
20   /** @type Object.<string, string> */ this.dict = {};
21 };
22
23 /** @private */
24 remoting.ServerLogEntry.KEY_EVENT_NAME_ = 'event-name';
25 /** @private */
26 remoting.ServerLogEntry.VALUE_EVENT_NAME_SESSION_STATE_ =
27     'session-state';
28
29 /** @private */
30 remoting.ServerLogEntry.KEY_SESSION_ID_ = 'session-id';
31
32 /** @private */
33 remoting.ServerLogEntry.KEY_ROLE_ = 'role';
34 /** @private */
35 remoting.ServerLogEntry.VALUE_ROLE_CLIENT_ = 'client';
36
37 /** @private */
38 remoting.ServerLogEntry.KEY_SESSION_STATE_ = 'session-state';
39
40 /**
41  * @private
42  * @param {remoting.ClientSession.State} state
43  * @return {string}
44  */
45 remoting.ServerLogEntry.getValueForSessionState = function(state) {
46   switch(state) {
47     case remoting.ClientSession.State.UNKNOWN:
48       return 'unknown';
49     case remoting.ClientSession.State.CREATED:
50       return 'created';
51     case remoting.ClientSession.State.CONNECTING:
52       return 'connecting';
53     case remoting.ClientSession.State.INITIALIZING:
54       return 'initializing';
55     case remoting.ClientSession.State.CONNECTED:
56       return 'connected';
57     case remoting.ClientSession.State.CLOSED:
58       return 'closed';
59     case remoting.ClientSession.State.FAILED:
60       return 'connection-failed';
61     case remoting.ClientSession.State.CONNECTION_DROPPED:
62       return 'connection-dropped';
63     case remoting.ClientSession.State.CONNECTION_CANCELED:
64       return 'connection-canceled';
65     default:
66       return 'undefined-' + state;
67   }
68 };
69
70 /** @private */
71 remoting.ServerLogEntry.KEY_CONNECTION_ERROR_ = 'connection-error';
72
73 /**
74  * @private
75  * @param {remoting.Error} connectionError
76  * @return {string}
77  */
78 remoting.ServerLogEntry.getValueForError =
79     function(connectionError) {
80   switch(connectionError) {
81     case remoting.Error.NONE:
82       return 'none';
83     case remoting.Error.INVALID_ACCESS_CODE:
84       return 'invalid-access-code';
85     case remoting.Error.MISSING_PLUGIN:
86       return 'missing_plugin';
87     case remoting.Error.AUTHENTICATION_FAILED:
88       return 'authentication-failed';
89     case remoting.Error.HOST_IS_OFFLINE:
90       return 'host-is-offline';
91     case remoting.Error.INCOMPATIBLE_PROTOCOL:
92       return 'incompatible-protocol';
93     case remoting.Error.BAD_PLUGIN_VERSION:
94       return 'bad-plugin-version';
95     case remoting.Error.NETWORK_FAILURE:
96       return 'network-failure';
97     case remoting.Error.HOST_OVERLOAD:
98       return 'host-overload';
99     case remoting.Error.P2P_FAILURE:
100       return 'p2p-failure';
101     case remoting.Error.UNEXPECTED:
102       return 'unexpected';
103     default:
104       return 'unknown-' + connectionError;
105   }
106 };
107
108 /** @private */
109 remoting.ServerLogEntry.KEY_SESSION_DURATION_ = 'session-duration';
110
111 /** @private */
112 remoting.ServerLogEntry.VALUE_EVENT_NAME_CONNECTION_STATISTICS_ =
113     "connection-statistics";
114 /** @private */
115 remoting.ServerLogEntry.KEY_VIDEO_BANDWIDTH_ = "video-bandwidth";
116 /** @private */
117 remoting.ServerLogEntry.KEY_CAPTURE_LATENCY_ = "capture-latency";
118 /** @private */
119 remoting.ServerLogEntry.KEY_ENCODE_LATENCY_ = "encode-latency";
120 /** @private */
121 remoting.ServerLogEntry.KEY_DECODE_LATENCY_ = "decode-latency";
122 /** @private */
123 remoting.ServerLogEntry.KEY_RENDER_LATENCY_ = "render-latency";
124 /** @private */
125 remoting.ServerLogEntry.KEY_ROUNDTRIP_LATENCY_ = "roundtrip-latency";
126
127 /** @private */
128 remoting.ServerLogEntry.KEY_OS_NAME_ = 'os-name';
129 /** @private */
130 remoting.ServerLogEntry.VALUE_OS_NAME_WINDOWS_ = 'Windows';
131 /** @private */
132 remoting.ServerLogEntry.VALUE_OS_NAME_LINUX_ = 'Linux';
133 /** @private */
134 remoting.ServerLogEntry.VALUE_OS_NAME_MAC_ = 'Mac';
135 /** @private */
136 remoting.ServerLogEntry.VALUE_OS_NAME_CHROMEOS_ = 'ChromeOS';
137
138 /** @private */
139 remoting.ServerLogEntry.KEY_OS_VERSION_ = 'os-version';
140
141 /** @private */
142 remoting.ServerLogEntry.KEY_CPU_ = 'cpu';
143
144 /** @private */
145 remoting.ServerLogEntry.KEY_BROWSER_VERSION_ = 'browser-version';
146
147 /** @private */
148 remoting.ServerLogEntry.KEY_WEBAPP_VERSION_ = 'webapp-version';
149
150 /** @private */
151 remoting.ServerLogEntry.VALUE_EVENT_NAME_SESSION_ID_OLD_ = 'session-id-old';
152
153 /** @private */
154 remoting.ServerLogEntry.VALUE_EVENT_NAME_SESSION_ID_NEW_ = 'session-id-new';
155
156 /** @private */
157 remoting.ServerLogEntry.KEY_MODE_ = 'mode';
158 /** @private */
159 remoting.ServerLogEntry.VALUE_MODE_IT2ME_ = 'it2me';
160 /** @private */
161 remoting.ServerLogEntry.VALUE_MODE_ME2ME_ = 'me2me';
162 /** @private */
163 remoting.ServerLogEntry.VALUE_MODE_UNKNOWN_ = 'unknown';
164
165 /**
166  * Sets one field in this log entry.
167  *
168  * @private
169  * @param {string} key
170  * @param {string} value
171  */
172 remoting.ServerLogEntry.prototype.set = function(key, value) {
173   this.dict[key] = value;
174 };
175
176 /**
177  * Converts this object into an XML stanza.
178  *
179  * @return {string}
180  */
181 remoting.ServerLogEntry.prototype.toStanza = function() {
182   var stanza = '<gr:entry ';
183   for (var key in this.dict) {
184     stanza += escape(key) + '="' + escape(this.dict[key]) + '" ';
185   }
186   stanza += '/>';
187   return stanza;
188 };
189
190 /**
191  * Prints this object on the debug log.
192  *
193  * @param {number} indentLevel the indentation level
194  */
195 remoting.ServerLogEntry.prototype.toDebugLog = function(indentLevel) {
196   /** @type Array.<string> */ var fields = [];
197   for (var key in this.dict) {
198     fields.push(key + ': ' + this.dict[key]);
199   }
200   console.log(Array(indentLevel+1).join("  ") + fields.join(', '));
201 };
202
203 /**
204  * Makes a log entry for a change of client session state.
205  *
206  * @param {remoting.ClientSession.State} state
207  * @param {remoting.Error} connectionError
208  * @param {remoting.ClientSession.Mode} mode
209  * @return {remoting.ServerLogEntry}
210  */
211 remoting.ServerLogEntry.makeClientSessionStateChange = function(state,
212     connectionError, mode) {
213   var entry = new remoting.ServerLogEntry();
214   entry.set(remoting.ServerLogEntry.KEY_ROLE_,
215             remoting.ServerLogEntry.VALUE_ROLE_CLIENT_);
216   entry.set(remoting.ServerLogEntry.KEY_EVENT_NAME_,
217             remoting.ServerLogEntry.VALUE_EVENT_NAME_SESSION_STATE_);
218   entry.set(remoting.ServerLogEntry.KEY_SESSION_STATE_,
219             remoting.ServerLogEntry.getValueForSessionState(state));
220   if (connectionError != remoting.Error.NONE) {
221     entry.set(remoting.ServerLogEntry.KEY_CONNECTION_ERROR_,
222               remoting.ServerLogEntry.getValueForError(connectionError));
223   }
224   entry.addModeField(mode);
225   return entry;
226 };
227
228 /**
229  * Adds a session duration to a log entry.
230  *
231  * @param {number} sessionDuration
232  */
233 remoting.ServerLogEntry.prototype.addSessionDurationField = function(
234     sessionDuration) {
235   this.set(remoting.ServerLogEntry.KEY_SESSION_DURATION_,
236       sessionDuration.toString());
237 };
238
239 /**
240  * Makes a log entry for a set of connection statistics.
241  * Returns null if all the statistics were zero.
242  *
243  * @param {remoting.StatsAccumulator} statsAccumulator
244  * @param {remoting.ClientSession.Mode} mode
245  * @return {?remoting.ServerLogEntry}
246  */
247 remoting.ServerLogEntry.makeStats = function(statsAccumulator, mode) {
248   var entry = new remoting.ServerLogEntry();
249   entry.set(remoting.ServerLogEntry.KEY_ROLE_,
250             remoting.ServerLogEntry.VALUE_ROLE_CLIENT_);
251   entry.set(remoting.ServerLogEntry.KEY_EVENT_NAME_,
252             remoting.ServerLogEntry.VALUE_EVENT_NAME_CONNECTION_STATISTICS_);
253   entry.addModeField(mode);
254   var nonZero = false;
255   nonZero |= entry.addStatsField(
256       remoting.ServerLogEntry.KEY_VIDEO_BANDWIDTH_,
257       remoting.ClientSession.STATS_KEY_VIDEO_BANDWIDTH, statsAccumulator);
258   nonZero |= entry.addStatsField(
259       remoting.ServerLogEntry.KEY_CAPTURE_LATENCY_,
260       remoting.ClientSession.STATS_KEY_CAPTURE_LATENCY, statsAccumulator);
261   nonZero |= entry.addStatsField(
262       remoting.ServerLogEntry.KEY_ENCODE_LATENCY_,
263       remoting.ClientSession.STATS_KEY_ENCODE_LATENCY, statsAccumulator);
264   nonZero |= entry.addStatsField(
265       remoting.ServerLogEntry.KEY_DECODE_LATENCY_,
266       remoting.ClientSession.STATS_KEY_DECODE_LATENCY, statsAccumulator);
267   nonZero |= entry.addStatsField(
268       remoting.ServerLogEntry.KEY_RENDER_LATENCY_,
269       remoting.ClientSession.STATS_KEY_RENDER_LATENCY, statsAccumulator);
270   nonZero |= entry.addStatsField(
271       remoting.ServerLogEntry.KEY_ROUNDTRIP_LATENCY_,
272       remoting.ClientSession.STATS_KEY_ROUNDTRIP_LATENCY, statsAccumulator);
273   if (nonZero) {
274     return entry;
275   }
276   return null;
277 };
278
279 /**
280  * Adds one connection statistic to a log entry.
281  *
282  * @private
283  * @param {string} entryKey
284  * @param {string} statsKey
285  * @param {remoting.StatsAccumulator} statsAccumulator
286  * @return {boolean} whether the statistic is non-zero
287  */
288 remoting.ServerLogEntry.prototype.addStatsField = function(
289     entryKey, statsKey, statsAccumulator) {
290   var val = statsAccumulator.calcMean(statsKey);
291   this.set(entryKey, val.toFixed(2));
292   return (val != 0);
293 };
294
295 /**
296  * Makes a log entry for a "this session ID is old" event.
297  *
298  * @param {string} sessionId
299  * @param {remoting.ClientSession.Mode} mode
300  * @return {remoting.ServerLogEntry}
301  */
302 remoting.ServerLogEntry.makeSessionIdOld = function(sessionId, mode) {
303   var entry = new remoting.ServerLogEntry();
304   entry.set(remoting.ServerLogEntry.KEY_ROLE_,
305             remoting.ServerLogEntry.VALUE_ROLE_CLIENT_);
306   entry.set(remoting.ServerLogEntry.KEY_EVENT_NAME_,
307             remoting.ServerLogEntry.VALUE_EVENT_NAME_SESSION_ID_OLD_);
308   entry.addSessionIdField(sessionId);
309   entry.addModeField(mode);
310   return entry;
311 };
312
313 /**
314  * Makes a log entry for a "this session ID is new" event.
315  *
316  * @param {string} sessionId
317  * @param {remoting.ClientSession.Mode} mode
318  * @return {remoting.ServerLogEntry}
319  */
320 remoting.ServerLogEntry.makeSessionIdNew = function(sessionId, mode) {
321   var entry = new remoting.ServerLogEntry();
322   entry.set(remoting.ServerLogEntry.KEY_ROLE_,
323             remoting.ServerLogEntry.VALUE_ROLE_CLIENT_);
324   entry.set(remoting.ServerLogEntry.KEY_EVENT_NAME_,
325             remoting.ServerLogEntry.VALUE_EVENT_NAME_SESSION_ID_NEW_);
326   entry.addSessionIdField(sessionId);
327   entry.addModeField(mode);
328   return entry;
329 };
330
331 /**
332  * Adds a session ID field to this log entry.
333  *
334  * @param {string} sessionId
335  */
336 remoting.ServerLogEntry.prototype.addSessionIdField = function(sessionId) {
337   this.set(remoting.ServerLogEntry.KEY_SESSION_ID_, sessionId);
338 }
339
340 /**
341  * Adds fields describing the host to this log entry.
342  */
343 remoting.ServerLogEntry.prototype.addHostFields = function() {
344   var host = remoting.ServerLogEntry.getHostData();
345   if (host) {
346     if (host.os_name.length > 0) {
347       this.set(remoting.ServerLogEntry.KEY_OS_NAME_, host.os_name);
348     }
349     if (host.os_version.length > 0) {
350       this.set(remoting.ServerLogEntry.KEY_OS_VERSION_, host.os_version);
351     }
352     if (host.cpu.length > 0) {
353       this.set(remoting.ServerLogEntry.KEY_CPU_, host.cpu);
354     }
355   }
356 };
357
358 /**
359  * Extracts host data from the userAgent string.
360  *
361  * @private
362  * @return {{os_name:string, os_version:string, cpu:string} | null}
363  */
364 remoting.ServerLogEntry.getHostData = function() {
365   return remoting.ServerLogEntry.extractHostDataFrom(navigator.userAgent);
366 };
367
368 /**
369  * Extracts host data from the given userAgent string.
370  *
371  * @private
372  * @param {string} s
373  * @return {{os_name:string, os_version:string, cpu:string} | null}
374  */
375 remoting.ServerLogEntry.extractHostDataFrom = function(s) {
376   // Sample userAgent strings:
377   // 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 ' +
378   //   '(KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2'
379   // 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.8 ' +
380   //   '(KHTML, like Gecko) Chrome/17.0.933.0 Safari/535.8'
381   // 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.1 ' +
382   //   '(KHTML, like Gecko) Chrome/14.0.835.202 Safari/535.1'
383   // 'Mozilla/5.0 (X11; CrOS i686 14.811.154) AppleWebKit/535.1 ' +
384   //   '(KHTML, like Gecko) Chrome/14.0.835.204 Safari/535.1'
385   var match = new RegExp('Windows NT ([0-9\\.]*)').exec(s);
386   if (match && (match.length >= 2)) {
387     return {
388         'os_name': remoting.ServerLogEntry.VALUE_OS_NAME_WINDOWS_,
389         'os_version': match[1],
390         'cpu': ''
391     };
392   }
393   match = new RegExp('Linux ([a-zA-Z0-9_]*)').exec(s);
394   if (match && (match.length >= 2)) {
395     return {
396         'os_name': remoting.ServerLogEntry.VALUE_OS_NAME_LINUX_,
397         'os_version' : '',
398         'cpu': match[1]
399     };
400   }
401   match = new RegExp('([a-zA-Z]*) Mac OS X ([0-9_]*)').exec(s);
402   if (match && (match.length >= 3)) {
403     return {
404         'os_name': remoting.ServerLogEntry.VALUE_OS_NAME_MAC_,
405         'os_version': match[2].replace(/_/g, '.'),
406         'cpu': match[1]
407     };
408   }
409   match = new RegExp('CrOS ([a-zA-Z0-9]*) ([0-9.]*)').exec(s);
410   if (match && (match.length >= 3)) {
411     return {
412         'os_name': remoting.ServerLogEntry.VALUE_OS_NAME_CHROMEOS_,
413         'os_version': match[2],
414         'cpu': match[1]
415     };
416   }
417   return null;
418 };
419
420 /**
421  * Adds a field specifying the browser version to this log entry.
422  */
423 remoting.ServerLogEntry.prototype.addChromeVersionField = function() {
424   var version = remoting.getChromeVersion();
425   if (version != null) {
426     this.set(remoting.ServerLogEntry.KEY_BROWSER_VERSION_, version);
427   }
428 };
429
430 /**
431  * Adds a field specifying the webapp version to this log entry.
432  */
433 remoting.ServerLogEntry.prototype.addWebappVersionField = function() {
434   var manifest = chrome.runtime.getManifest();
435   if (manifest && manifest.version) {
436     this.set(remoting.ServerLogEntry.KEY_WEBAPP_VERSION_, manifest.version);
437   }
438 };
439
440 /**
441  * Adds a field specifying the mode to this log entry.
442  *
443  * @param {remoting.ClientSession.Mode} mode
444  */
445 remoting.ServerLogEntry.prototype.addModeField = function(mode) {
446   this.set(remoting.ServerLogEntry.KEY_MODE_,
447       remoting.ServerLogEntry.getModeField(mode));
448 };
449
450 /**
451  * Gets the value of the mode field to be put in a log entry.
452  *
453  * @private
454  * @param {remoting.ClientSession.Mode} mode
455  * @return {string}
456  */
457 remoting.ServerLogEntry.getModeField = function(mode) {
458   switch(mode) {
459     case remoting.ClientSession.Mode.IT2ME:
460       return remoting.ServerLogEntry.VALUE_MODE_IT2ME_;
461     case remoting.ClientSession.Mode.ME2ME:
462       return remoting.ServerLogEntry.VALUE_MODE_ME2ME_;
463     default:
464       return remoting.ServerLogEntry.VALUE_MODE_UNKNOWN_;
465   }
466 };