OLD | NEW |
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 Loading... |
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 Loading... |
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); |
OLD | NEW |