Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: chrome/browser/resources/feedback/js/event_handler.js

Issue 1794513002: Fix sending multiple feedback reports within short durations of each other (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: simplify a lot Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @type {number} 6 * @type {number}
7 * @const 7 * @const
8 */ 8 */
9 var FEEDBACK_WIDTH = 500; 9 var FEEDBACK_WIDTH = 500;
10 /** 10 /**
11 * @type {number} 11 * @type {number}
12 * @const 12 * @const
13 */ 13 */
14 var FEEDBACK_HEIGHT = 585; 14 var FEEDBACK_HEIGHT = 585;
15 15
16 /** 16 /**
17 * @type {string} 17 * @type {string}
18 * @const 18 * @const
19 */ 19 */
20 var FEEDBACK_DEFAULT_WINDOW_ID = 'default_window'; 20 var FEEDBACK_DEFAULT_WINDOW_ID = 'default_window';
21 21
22 /**
23 * The feedback info received initially when the feedback UI was first requested
24 * to start.
25 * @type {Object}
26 */
27 var initialFeedbackInfo = null;
28
29 /**
30 * The feedbak info that is ready to be sent later when the system information
31 * becomes available.
32 * @type {Object}
33 */
34 var finalFeedbackInfo = null;
35
36 /**
37 * The system information received from the C++ side.
38 * @type {Object}
39 */
40 var systemInfo = null;
41
42 /**
43 * True if the system information has been received, false otherwise.
44 * @type {boolean}
45 */
46 var isSystemInfoReady = false;
47
48 /**
49 * A callback to be invoked when the system information is ready.
50 * @type {function(sysInfo)}
51 */
52 var onSystemInfoReadyCallback = null;
53
54 // To generate a hashed extension ID, use a sha-256 hash, all in lower case. 22 // To generate a hashed extension ID, use a sha-256 hash, all in lower case.
55 // Example: 23 // Example:
56 // echo -n 'abcdefghijklmnopqrstuvwxyzabcdef' | sha1sum | \ 24 // echo -n 'abcdefghijklmnopqrstuvwxyzabcdef' | sha1sum | \
57 // awk '{print toupper($1)}' 25 // awk '{print toupper($1)}'
58 var whitelistedExtensionIds = [ 26 var whitelistedExtensionIds = [
59 '12E618C3C6E97495AAECF2AC12DEB082353241C6', // QuickOffice 27 '12E618C3C6E97495AAECF2AC12DEB082353241C6', // QuickOffice
60 '3727DD3E564B6055387425027AD74C58784ACC15', // QuickOffice 28 '3727DD3E564B6055387425027AD74C58784ACC15', // QuickOffice
61 '2FC374607C2DF285634B67C64A2E356C607091C3', // QuickOffice 29 '2FC374607C2DF285634B67C64A2E356C607091C3', // QuickOffice
62 '2843C1E82A9B6C6FB49308FDDF4E157B6B44BC2B', // G+ Photos 30 '2843C1E82A9B6C6FB49308FDDF4E157B6B44BC2B', // G+ Photos
63 '5B5DA6D054D10DB917AF7D9EAE3C56044D1B0B03', // G+ Photos 31 '5B5DA6D054D10DB917AF7D9EAE3C56044D1B0B03', // G+ Photos
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 'A8208CCC87F8261AFAEB6B85D5E8D47372DDEA6B', // http://crbug.com/478929 72 'A8208CCC87F8261AFAEB6B85D5E8D47372DDEA6B', // http://crbug.com/478929
105 'B620CF4203315F9F2E046EDED22C7571A935958D', // http://crbug.com/510270 73 'B620CF4203315F9F2E046EDED22C7571A935958D', // http://crbug.com/510270
106 'B206D8716769728278D2D300349C6CB7D7DE2EF9', // http://crbug.com/510270 74 'B206D8716769728278D2D300349C6CB7D7DE2EF9', // http://crbug.com/510270
107 'EFCF5358672FEE04789FD2EC3638A67ADEDB6C8C', // http://crbug.com/514696 75 'EFCF5358672FEE04789FD2EC3638A67ADEDB6C8C', // http://crbug.com/514696
108 'FAD85BC419FE00995D196312F53448265EFA86F1', // http://crbug.com/516527 76 'FAD85BC419FE00995D196312F53448265EFA86F1', // http://crbug.com/516527
109 'F33B037DEDA65F226B7409C2ADB0CF3F8565AB03', // http://crbug.com/541769 77 'F33B037DEDA65F226B7409C2ADB0CF3F8565AB03', // http://crbug.com/541769
110 '969C788BCBC82FBBE04A17360CA165C23A419257', // http://crbug.com/541769 78 '969C788BCBC82FBBE04A17360CA165C23A419257', // http://crbug.com/541769
111 '3BC3740BFC58F06088B300274B4CFBEA20136342', // http://crbug.com/541769 79 '3BC3740BFC58F06088B300274B4CFBEA20136342', // http://crbug.com/541769
112 ]; 80 ];
113 81
82 /**
83 * A FeedbackRequest object represents a unique feedback report, requested by an
84 * instance of the feedback window. It contains the system information specific
85 * to this report, the full feedbackInfo, and callbacks to send the report upon
86 * request.
87 */
88 class FeedbackRequest {
89 constructor(requestId, feedbackInfo) {
90 this.id_ = requestId;
xiyuan 2016/03/16 16:39:28 This is no longer needed, right? Can we get rid of
afakhry 2016/03/16 17:51:22 As discussed offline, we use it for logging that t
91 this.feedbackInfo_ = feedbackInfo;
92 this.onSystemInfoReadyCallback_ = null;
93 this.isSystemInfoReady_ = false;
94 this.isRequestCanceled_ = false;
95 }
96
97 /**
98 * Called when the system information is sent from the C++ side.
99 * @param {Object} sysInfo The received system information.
100 */
101 getSystemInformationCallback(sysInfo) {
102 if (this.isRequestCanceled_) {
103 // If the window had been closed before the system information was
104 // received, we skip the rest of the operations and return immediately.
105 return;
106 }
107
108 this.isSystemInfoReady_ = true;
109
110 // Combine the newly received system information with whatever system
111 // information we have in the feedback info (if any).
112 if (this.feedbackInfo_.systemInformation) {
113 this.feedbackInfo_.systemInformation =
114 this.feedbackInfo_.systemInformation.concat(sysInfo);
115 } else {
116 this.feedbackInfo_.systemInformation = sysInfo;
117 }
118
119 if (this.onSystemInfoReadyCallback_ != null) {
120 this.onSystemInfoReadyCallback_();
121 this.onSystemInfoReadyCallback_ = null;
122 }
123 }
124
125 /**
126 * Retrieves the system information for this request object.
127 * @param {function()} callback Invoked to notify the listener that the system
128 * information has been received.
129 */
130 getSystemInformation(callback) {
131 if (this.isSystemInfoReady_) {
132 callback();
133 return;
134 }
135
136 this.onSystemInfoReadyCallback_ = callback;
137 // The C++ side must reply to the callback specific to this object.
138 var boundCallback = this.getSystemInformationCallback.bind(this);
139 chrome.feedbackPrivate.getSystemInformation(boundCallback);
140 }
141
142 /**
143 * Sends the feedback report represented by the object, either now if system
144 * information is ready, or later once it is.
145 * @param {boolean} useSystemInfo True if the user would like the system
146 * information to be sent with the report.
147 */
148 sendReport(useSystemInfo) {
149 if (useSystemInfo && !this.isSystemInfoReady_) {
150 this.onSystemInfoReadyCallback_ = this.sendReportNow;
151 return;
152 }
153
154 this.sendReportNow();
155 }
156
157 /**
158 * Sends the report immediately and removes this object once the report is
159 * sent.
160 */
161 sendReportNow() {
162 /** @const */ var ID = this.id_;
163 var that = this;
xiyuan 2016/03/16 16:39:28 unused?
afakhry 2016/03/16 17:51:22 Oops, left overs from testing.
164 chrome.feedbackPrivate.sendFeedback(this.feedbackInfo_,
165 function(result) {
166 console.log('Feedback: Report sent for request with ID ' + ID);
167 });
168 }
169 };
170
171 /**
172 * Used to generate unique IDs for FeedbackRequest objects.
173 * @type {number}
174 */
175 var lastUsedId = 0;
114 176
115 /** 177 /**
116 * Function to determine whether or not a given extension id is whitelisted to 178 * Function to determine whether or not a given extension id is whitelisted to
117 * invoke the feedback UI. If the extension is whitelisted, the callback to 179 * invoke the feedback UI. If the extension is whitelisted, the callback to
118 * start the Feedback UI will be called. 180 * start the Feedback UI will be called.
119 * @param {string} id the id of the sender extension. 181 * @param {string} id the id of the sender extension.
120 * @param {Function} startFeedbackCallback The callback function that will 182 * @param {Function} startFeedbackCallback The callback function that will
121 * will start the feedback UI. 183 * will start the feedback UI.
122 * @param {Object} feedbackInfo The feedback info object to pass to the 184 * @param {Object} feedbackInfo The feedback info object to pass to the
123 * start feedback UI callback. 185 * start feedback UI callback.
(...skipping 14 matching lines...) Expand all
138 } 200 }
139 201
140 /** 202 /**
141 * Callback which gets notified once our feedback UI has loaded and is ready to 203 * Callback which gets notified once our feedback UI has loaded and is ready to
142 * receive its initial feedback info object. 204 * receive its initial feedback info object.
143 * @param {Object} request The message request object. 205 * @param {Object} request The message request object.
144 * @param {Object} sender The sender of the message. 206 * @param {Object} sender The sender of the message.
145 * @param {function(Object)} sendResponse Callback for sending a response. 207 * @param {function(Object)} sendResponse Callback for sending a response.
146 */ 208 */
147 function feedbackReadyHandler(request, sender, sendResponse) { 209 function feedbackReadyHandler(request, sender, sendResponse) {
148 if (request.ready) { 210 if (request.ready)
149 chrome.runtime.sendMessage( 211 chrome.runtime.sendMessage({sentFromEventPage: true});
150 {sentFromEventPage: true, data: initialFeedbackInfo});
151 }
152 } 212 }
153 213
154
155 /** 214 /**
156 * Callback which gets notified if another extension is requesting feedback. 215 * Callback which gets notified if another extension is requesting feedback.
157 * @param {Object} request The message request object. 216 * @param {Object} request The message request object.
158 * @param {Object} sender The sender of the message. 217 * @param {Object} sender The sender of the message.
159 * @param {function(Object)} sendResponse Callback for sending a response. 218 * @param {function(Object)} sendResponse Callback for sending a response.
160 */ 219 */
161 function requestFeedbackHandler(request, sender, sendResponse) { 220 function requestFeedbackHandler(request, sender, sendResponse) {
162 if (request.requestFeedback) 221 if (request.requestFeedback)
163 senderWhitelisted(sender.id, startFeedbackUI, request.feedbackInfo); 222 senderWhitelisted(sender.id, startFeedbackUI, request.feedbackInfo);
164 } 223 }
165 224
166 /** 225 /**
167 * Called when the system information is sent from the C++ side.
168 * @param {Object} sysInfo The received system information.
169 */
170
171 function getSystemInformationCallback(sysInfo) {
172 systemInfo = sysInfo;
173 isSystemInfoReady = true;
174 if (onSystemInfoReadyCallback != null)
175 onSystemInfoReadyCallback(sysInfo);
176 }
177
178 /**
179 * If the user requested to send the report before the system information was
180 * received, this callback will be invoked once the system information is ready
181 * to send the report then.
182 * @param {Object} sysInfo The received system information.
183 */
184
185 function onSysInfoReadyForSend(sysInfo) {
186 // Combine the newly received system information with whatever system
187 // information we have in the final feedback info (if any).
188 if (finalFeedbackInfo.systemInformation) {
189 finalFeedbackInfo.systemInformation =
190 finalFeedbackInfo.systemInformation.concat(sysInfo);
191 } else {
192 finalFeedbackInfo.systemInformation = sysInfo;
193 }
194
195 chrome.feedbackPrivate.sendFeedback(finalFeedbackInfo, function(result) {});
196 }
197
198 /**
199 * Callback which starts up the feedback UI. 226 * Callback which starts up the feedback UI.
200 * @param {Object} feedbackInfo Object containing any initial feedback info. 227 * @param {Object} feedbackInfo Object containing any initial feedback info.
201 */ 228 */
202 function startFeedbackUI(feedbackInfo) { 229 function startFeedbackUI(feedbackInfo) {
203 var win = chrome.app.window.get(FEEDBACK_DEFAULT_WINDOW_ID); 230 var win = chrome.app.window.get(FEEDBACK_DEFAULT_WINDOW_ID);
204 if (win) { 231 if (win) {
205 win.show(); 232 win.show();
206 return; 233 return;
207 } 234 }
208 chrome.app.window.create('html/default.html', { 235 chrome.app.window.create('html/default.html', {
209 frame: 'none', 236 frame: 'none',
210 id: FEEDBACK_DEFAULT_WINDOW_ID, 237 id: FEEDBACK_DEFAULT_WINDOW_ID,
211 width: FEEDBACK_WIDTH, 238 width: FEEDBACK_WIDTH,
212 height: FEEDBACK_HEIGHT, 239 height: FEEDBACK_HEIGHT,
213 hidden: true, 240 hidden: true,
214 resizable: false }, 241 resizable: false },
215 function(appWindow) { 242 function(appWindow) {
216 // Initialize the state of the app only once upon the creation of the 243 // Generate a unique feedback request ID for this feedback window.
217 // feedback UI window. 244 // A FeedbackRequest object is used to represent this instance of the
218 initialFeedbackInfo = feedbackInfo; 245 // feedback window.
219 finalFeedbackInfo = null; 246 /** @const */ var ID = ++lastUsedId;
220 systemInfo = null; 247 var request = new FeedbackRequest(ID, feedbackInfo);
221 isSystemInfoReady = false; 248
222 onSystemInfoReadyCallback = null; 249 // The feedbackInfo member of the new window should refer to the one in
250 // its corresponding FeedbackRequest object to avoid copying and
251 // duplicatations.
252 appWindow.contentWindow.feedbackInfo = request.feedbackInfo_;
253
254 // We mark the FeedbackRequest instance as canceled if the window was
255 // closed before the report was requested to be sent.
256 var reportIsBeingSent = false;
xiyuan 2016/03/16 16:39:28 nit: This can be part of FeedbackRequest.
afakhry 2016/03/16 17:51:22 Done.
223 257
224 // Define some functions for the new window so that it can call back 258 // Define some functions for the new window so that it can call back
225 // into here. 259 // into here.
226 260
227 // Define a function for the new window to get the system information. 261 // Define a function for the new window to get the system information.
228 appWindow.contentWindow.getSystemInformation = function(callback) { 262 appWindow.contentWindow.getSystemInformation = function(callback) {
229 if (!isSystemInfoReady) { 263 request.getSystemInformation(callback);
230 onSystemInfoReadyCallback = callback;
231 chrome.feedbackPrivate.getSystemInformation(
232 getSystemInformationCallback);
233 return;
234 }
235
236 callback(systemInfo);
237 }; 264 };
238 265
239 // Define a function to be called by the new window when the report is 266 // Define a function to request sending the feedback report.
240 // not ready yet, and has to be sent later when the system information 267 appWindow.contentWindow.sendFeedbackReport = function(useSystemInfo) {
241 // is received. 268 // The report will be sent by the request object.
242 appWindow.contentWindow.sendReportLater = function(feedbackInfo) { 269 reportIsBeingSent = true;
243 finalFeedbackInfo = feedbackInfo; 270 request.sendReport(useSystemInfo);
244 if (!isSystemInfoReady) {
245 onSystemInfoReadyCallback = onSysInfoReadyForSend;
246 return;
247 }
248
249 onSysInfoReadyForSend(systemInfo);
250 }; 271 };
251 272
252 // Returns whether the system information has been received or not. 273 // Observe when the window is closed.
253 appWindow.contentWindow.isSystemInfoReady = function() { 274 appWindow.onClosed.addListener(function() {
254 return isSystemInfoReady; 275 if (!reportIsBeingSent)
255 }; 276 request.isRequestCanceled_ = true;
277 });
256 }); 278 });
257 } 279 }
258 280
259 chrome.runtime.onMessage.addListener(feedbackReadyHandler); 281 chrome.runtime.onMessage.addListener(feedbackReadyHandler);
260 chrome.runtime.onMessageExternal.addListener(requestFeedbackHandler); 282 chrome.runtime.onMessageExternal.addListener(requestFeedbackHandler);
261 chrome.feedbackPrivate.onFeedbackRequested.addListener(startFeedbackUI); 283 chrome.feedbackPrivate.onFeedbackRequested.addListener(startFeedbackUI);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698