Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / remoting / webapp / base / js / telemetry_event_writer.js
blob87531574b723aee2005bec2b42784ccd9a89b822
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 /** @suppress {duplicate} */
6 var remoting = remoting || {};
8 (function() {
10 'use strict';
12 remoting.TelemetryEventWriter = function() {};
14 /** @enum {string} */
15 var IpcNames = {
16 WRITE: 'remoting.TelemetryEventWriter.write'
19 /**
20 * @param {base.Ipc} ipc
21 * @param {remoting.XhrEventWriter} eventWriter
22 * @constructor
23 * @implements {base.Disposable}
25 remoting.TelemetryEventWriter.Service = function(ipc, eventWriter) {
26 /** @private */
27 this.eventWriter_ = eventWriter;
28 /** @private */
29 this.ipc_ = ipc;
30 /** @private {base.Disposables} */
31 this.eventHooks_ = new base.Disposables();
33 /** @private */
34 this.sessionMonitor_ = new SessionMonitor(this.eventWriter_);
37 /** @return {Promise} */
38 remoting.TelemetryEventWriter.Service.prototype.init = function() {
39 /** @this {remoting.TelemetryEventWriter.Service} */
40 function init() {
41 this.eventHooks_.add(
42 new base.DomEventHook(window, 'online',
43 this.eventWriter_.flush.bind(this.eventWriter_),
44 false),
45 new base.ChromeEventHook(chrome.runtime.onSuspend,
46 this.onSuspend_.bind(this)));
48 this.ipc_.register(IpcNames.WRITE, this.write.bind(this));
49 this.eventWriter_.flush();
51 // Only listen for new incoming requests after we have loaded the pending
52 // ones. This will ensure that we always process the requests in order.
53 return this.eventWriter_.loadPendingRequests().then(init.bind(this));
56 remoting.TelemetryEventWriter.Service.prototype.dispose = function() {
57 this.ipc_.unregister(IpcNames.WRITE);
58 base.dispose(this.eventHooks_);
59 this.eventHooks_ = null;
62 /**
63 * Unbind any sessions that are associated with |windowId|.
64 * @param {string} windowId
66 remoting.TelemetryEventWriter.Service.prototype.unbindSession =
67 function(windowId) {
68 this.sessionMonitor_.unbindSession(windowId);
71 /**
72 * @param {string} windowId The source window id of the IPC.
73 * @param {!Object} event The event to be written to the server.
75 remoting.TelemetryEventWriter.Service.prototype.write =
76 function(windowId, event) {
77 this.sessionMonitor_.trackSessionStateChanges(windowId, event);
78 this.eventWriter_.write(event);
81 /**
82 * @private
84 remoting.TelemetryEventWriter.Service.prototype.onSuspend_ = function() {
85 this.eventWriter_.writeToStorage();
88 /** @return {remoting.TelemetryEventWriter.Service} */
89 remoting.TelemetryEventWriter.Service.create = function() {
90 return new remoting.TelemetryEventWriter.Service(
91 base.Ipc.getInstance(),
92 new remoting.XhrEventWriter(
93 remoting.settings.TELEMETRY_API_BASE_URL,
94 chrome.storage.local,
95 'pending-log-requests'));
98 remoting.TelemetryEventWriter.Client = function() {};
101 * @param {!Object} event
102 * @return {Promise} A promise that resolves when the log message is sent to the
103 * logging service.
105 remoting.TelemetryEventWriter.Client.write = function(event) {
106 return base.Ipc.invoke(IpcNames.WRITE, chrome.app.window.current().id, event);
111 * @struct
112 * @constructor
113 * @param {remoting.ChromotingEvent} event
115 function SessionInfo(event) {
116 this.event = event;
117 this.timestamp = Date.now();
121 * When a window is closed using the context menu, the foreground page doesn't
122 * have a chance to intercept the close event.
123 * This class keeps track of all foreground windows with ongoing sessions, so
124 * that we can report session termination when they are closed.
126 * @param {remoting.XhrEventWriter} eventWriter
127 * @constructor
129 var SessionMonitor = function(eventWriter) {
130 /** @private */
131 this.eventWriter_ = eventWriter;
132 /** @private {Map<string, SessionInfo>} */
133 this.sessionMap_ = new Map();
137 * @param {string} windowId
138 * @param {Object} entry
140 SessionMonitor.prototype.trackSessionStateChanges = function(windowId, entry) {
141 var event = /** @type {remoting.ChromotingEvent} */ (base.deepCopy(entry));
143 if (event.type !== remoting.ChromotingEvent.Type.SESSION_STATE) {
144 return;
147 if (remoting.ChromotingEvent.isEndOfSession(event)) {
148 this.sessionMap_.delete(windowId);
149 } else {
150 this.sessionMap_.set(windowId, new SessionInfo(event));
155 * Unbinds a session with |windowId| and log any close events if necessary.
156 * @param {string} windowId
158 SessionMonitor.prototype.unbindSession = function(windowId) {
159 if (this.sessionMap_.has(windowId)) {
160 var sessionInfo = this.sessionMap_.get(windowId);
161 console.assert(sessionInfo !== undefined);
162 inferSessionEndEvent(/** @type {SessionInfo} */ (sessionInfo));
163 this.eventWriter_.write(/** @type {Object} */ (sessionInfo.event));
164 this.sessionMap_.delete(windowId);
169 * @param {SessionInfo} sessionInfo
171 function inferSessionEndEvent(sessionInfo) {
172 var event = sessionInfo.event;
173 var SessionState = remoting.ChromotingEvent.SessionState;
175 switch (event.session_state) {
176 case SessionState.INITIALIZING:
177 case SessionState.CONNECTING:
178 case SessionState.AUTHENTICATED:
179 event.session_state = SessionState.CONNECTION_CANCELED;
180 break;
181 default:
182 event.session_state = SessionState.CLOSED;
184 var elapsed = (Date.now() - sessionInfo.timestamp) / 1000.0;
185 event.session_duration += elapsed;
188 })();