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

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: self revision 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 * Used to generate unique IDs for FeedbackRequest objects.
84 * @type {number}
85 */
86 var lastUsedId = 0;
87
88 /**
89 * A FeedbackRequest object represents a unique feedback report, requested by an
90 * instance of the feedback window. It contains the system information specific
91 * to this report, the full feedbackInfo, and callbacks to send the report upon
92 * request.
93 */
94 class FeedbackRequest {
95 constructor(feedbackInfo) {
96 this.id_ = ++lastUsedId;
97 this.feedbackInfo_ = feedbackInfo;
98 this.onSystemInfoReadyCallback_ = null;
99 this.isSystemInfoReady_ = false;
100 this.reportIsBeingSent_ = false;
101 this.isRequestCanceled_ = false;
102 this.useSystemInfo_ = false;
103 }
104
105 /**
106 * Called when the system information is sent from the C++ side.
107 * @param {Object} sysInfo The received system information.
108 */
109 getSystemInformationCallback(sysInfo) {
110 if (this.isRequestCanceled_) {
111 // If the window had been closed before the system information was
112 // received, we skip the rest of the operations and return immediately.
113 return;
114 }
115
116 this.isSystemInfoReady_ = true;
117
118 // Combine the newly received system information with whatever system
119 // information we have in the feedback info (if any).
120 if (this.feedbackInfo_.systemInformation) {
121 this.feedbackInfo_.systemInformation =
122 this.feedbackInfo_.systemInformation.concat(sysInfo);
123 } else {
124 this.feedbackInfo_.systemInformation = sysInfo;
125 }
126
127 if (this.onSystemInfoReadyCallback_ != null) {
128 this.onSystemInfoReadyCallback_();
129 this.onSystemInfoReadyCallback_ = null;
130 }
131 }
132
133 /**
134 * Retrieves the system information for this request object.
135 * @param {function()} callback Invoked to notify the listener that the system
136 * information has been received.
137 */
138 getSystemInformation(callback) {
139 if (this.isSystemInfoReady_) {
140 callback();
141 return;
142 }
143
144 this.onSystemInfoReadyCallback_ = callback;
145 // The C++ side must reply to the callback specific to this object.
146 var boundCallback = this.getSystemInformationCallback.bind(this);
147 chrome.feedbackPrivate.getSystemInformation(boundCallback);
148 }
149
150 /**
151 * Sends the feedback report represented by the object, either now if system
152 * information is ready, or later once it is.
153 * @param {boolean} useSystemInfo True if the user would like the system
154 * information to be sent with the report.
155 */
156 sendReport(useSystemInfo) {
157 this.reportIsBeingSent_ = true;
158 this.useSystemInfo_ = useSystemInfo;
159 if (useSystemInfo && !this.isSystemInfoReady_) {
160 this.onSystemInfoReadyCallback_ = this.sendReportNow;
161 return;
162 }
163
164 this.sendReportNow();
165 }
166
167 /**
168 * Sends the report immediately and removes this object once the report is
169 * sent.
170 */
171 sendReportNow() {
172 if (!this.useSystemInfo_) {
173 // Clear the system information if the user doesn't want it to be sent.
174 this.feedbackInfo_.systemInformation = null;
175 }
176
177 /** @const */ var ID = this.id_;
178 chrome.feedbackPrivate.sendFeedback(this.feedbackInfo_,
179 function(result) {
180 console.log('Feedback: Report sent for request with ID ' + ID);
181 });
182 }
183
184 /**
185 * Handles the event when the feedback UI window corresponding to this
186 * FeedbackRequest instance is closed.
187 */
188 onWindowClosed() {
189 if (!this.reportIsBeingSent_)
190 this.isRequestCanceled_ = true;
191 }
192 };
114 193
115 /** 194 /**
116 * Function to determine whether or not a given extension id is whitelisted to 195 * 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 196 * invoke the feedback UI. If the extension is whitelisted, the callback to
118 * start the Feedback UI will be called. 197 * start the Feedback UI will be called.
119 * @param {string} id the id of the sender extension. 198 * @param {string} id the id of the sender extension.
120 * @param {Function} startFeedbackCallback The callback function that will 199 * @param {Function} startFeedbackCallback The callback function that will
121 * will start the feedback UI. 200 * will start the feedback UI.
122 * @param {Object} feedbackInfo The feedback info object to pass to the 201 * @param {Object} feedbackInfo The feedback info object to pass to the
123 * start feedback UI callback. 202 * start feedback UI callback.
(...skipping 14 matching lines...) Expand all
138 } 217 }
139 218
140 /** 219 /**
141 * Callback which gets notified once our feedback UI has loaded and is ready to 220 * Callback which gets notified once our feedback UI has loaded and is ready to
142 * receive its initial feedback info object. 221 * receive its initial feedback info object.
143 * @param {Object} request The message request object. 222 * @param {Object} request The message request object.
144 * @param {Object} sender The sender of the message. 223 * @param {Object} sender The sender of the message.
145 * @param {function(Object)} sendResponse Callback for sending a response. 224 * @param {function(Object)} sendResponse Callback for sending a response.
146 */ 225 */
147 function feedbackReadyHandler(request, sender, sendResponse) { 226 function feedbackReadyHandler(request, sender, sendResponse) {
148 if (request.ready) { 227 if (request.ready)
149 chrome.runtime.sendMessage( 228 chrome.runtime.sendMessage({sentFromEventPage: true});
150 {sentFromEventPage: true, data: initialFeedbackInfo});
151 }
152 } 229 }
153 230
154
155 /** 231 /**
156 * Callback which gets notified if another extension is requesting feedback. 232 * Callback which gets notified if another extension is requesting feedback.
157 * @param {Object} request The message request object. 233 * @param {Object} request The message request object.
158 * @param {Object} sender The sender of the message. 234 * @param {Object} sender The sender of the message.
159 * @param {function(Object)} sendResponse Callback for sending a response. 235 * @param {function(Object)} sendResponse Callback for sending a response.
160 */ 236 */
161 function requestFeedbackHandler(request, sender, sendResponse) { 237 function requestFeedbackHandler(request, sender, sendResponse) {
162 if (request.requestFeedback) 238 if (request.requestFeedback)
163 senderWhitelisted(sender.id, startFeedbackUI, request.feedbackInfo); 239 senderWhitelisted(sender.id, startFeedbackUI, request.feedbackInfo);
164 } 240 }
165 241
166 /** 242 /**
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. 243 * Callback which starts up the feedback UI.
200 * @param {Object} feedbackInfo Object containing any initial feedback info. 244 * @param {Object} feedbackInfo Object containing any initial feedback info.
201 */ 245 */
202 function startFeedbackUI(feedbackInfo) { 246 function startFeedbackUI(feedbackInfo) {
203 var win = chrome.app.window.get(FEEDBACK_DEFAULT_WINDOW_ID); 247 var win = chrome.app.window.get(FEEDBACK_DEFAULT_WINDOW_ID);
204 if (win) { 248 if (win) {
205 win.show(); 249 win.show();
206 return; 250 return;
207 } 251 }
208 chrome.app.window.create('html/default.html', { 252 chrome.app.window.create('html/default.html', {
209 frame: 'none', 253 frame: 'none',
210 id: FEEDBACK_DEFAULT_WINDOW_ID, 254 id: FEEDBACK_DEFAULT_WINDOW_ID,
211 width: FEEDBACK_WIDTH, 255 width: FEEDBACK_WIDTH,
212 height: FEEDBACK_HEIGHT, 256 height: FEEDBACK_HEIGHT,
213 hidden: true, 257 hidden: true,
214 resizable: false }, 258 resizable: false },
215 function(appWindow) { 259 function(appWindow) {
216 // Initialize the state of the app only once upon the creation of the 260 var request = new FeedbackRequest(feedbackInfo);
217 // feedback UI window. 261
218 initialFeedbackInfo = feedbackInfo; 262 // The feedbackInfo member of the new window should refer to the one in
219 finalFeedbackInfo = null; 263 // its corresponding FeedbackRequest object to avoid copying and
220 systemInfo = null; 264 // duplicatations.
221 isSystemInfoReady = false; 265 appWindow.contentWindow.feedbackInfo = request.feedbackInfo_;
222 onSystemInfoReadyCallback = null;
223 266
224 // Define some functions for the new window so that it can call back 267 // Define some functions for the new window so that it can call back
225 // into here. 268 // into here.
226 269
227 // Define a function for the new window to get the system information. 270 // Define a function for the new window to get the system information.
228 appWindow.contentWindow.getSystemInformation = function(callback) { 271 appWindow.contentWindow.getSystemInformation = function(callback) {
229 if (!isSystemInfoReady) { 272 request.getSystemInformation(callback);
230 onSystemInfoReadyCallback = callback;
231 chrome.feedbackPrivate.getSystemInformation(
232 getSystemInformationCallback);
233 return;
234 }
235
236 callback(systemInfo);
237 }; 273 };
238 274
239 // Define a function to be called by the new window when the report is 275 // Define a function to request sending the feedback report.
240 // not ready yet, and has to be sent later when the system information 276 appWindow.contentWindow.sendFeedbackReport = function(useSystemInfo) {
241 // is received. 277 request.sendReport(useSystemInfo);
242 appWindow.contentWindow.sendReportLater = function(feedbackInfo) {
243 finalFeedbackInfo = feedbackInfo;
244 if (!isSystemInfoReady) {
245 onSystemInfoReadyCallback = onSysInfoReadyForSend;
246 return;
247 }
248
249 onSysInfoReadyForSend(systemInfo);
250 }; 278 };
251 279
252 // Returns whether the system information has been received or not. 280 // Observe when the window is closed.
253 appWindow.contentWindow.isSystemInfoReady = function() { 281 appWindow.onClosed.addListener(function() {
254 return isSystemInfoReady; 282 request.onWindowClosed();
255 }; 283 });
256 }); 284 });
257 } 285 }
258 286
259 chrome.runtime.onMessage.addListener(feedbackReadyHandler); 287 chrome.runtime.onMessage.addListener(feedbackReadyHandler);
260 chrome.runtime.onMessageExternal.addListener(requestFeedbackHandler); 288 chrome.runtime.onMessageExternal.addListener(requestFeedbackHandler);
261 chrome.feedbackPrivate.onFeedbackRequested.addListener(startFeedbackUI); 289 chrome.feedbackPrivate.onFeedbackRequested.addListener(startFeedbackUI);
OLDNEW
« no previous file with comments | « chrome/browser/extensions/api/feedback_private/feedback_service.cc ('k') | chrome/browser/resources/feedback/js/feedback.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698