Chromium Code Reviews| Index: chrome/browser/resources/feedback/js/event_handler.js |
| diff --git a/chrome/browser/resources/feedback/js/event_handler.js b/chrome/browser/resources/feedback/js/event_handler.js |
| index 4ca6d128807197b2b7c69c726da565aa3a5e513c..4013bd8f85aa413b279fded12722556cc6936212 100644 |
| --- a/chrome/browser/resources/feedback/js/event_handler.js |
| +++ b/chrome/browser/resources/feedback/js/event_handler.js |
| @@ -19,38 +19,6 @@ var FEEDBACK_HEIGHT = 585; |
| */ |
| var FEEDBACK_DEFAULT_WINDOW_ID = 'default_window'; |
| -/** |
| - * The feedback info received initially when the feedback UI was first requested |
| - * to start. |
| - * @type {Object} |
| - */ |
| -var initialFeedbackInfo = null; |
| - |
| -/** |
| - * The feedbak info that is ready to be sent later when the system information |
| - * becomes available. |
| - * @type {Object} |
| - */ |
| -var finalFeedbackInfo = null; |
| - |
| -/** |
| - * The system information received from the C++ side. |
| - * @type {Object} |
| - */ |
| -var systemInfo = null; |
| - |
| -/** |
| - * True if the system information has been received, false otherwise. |
| - * @type {boolean} |
| - */ |
| -var isSystemInfoReady = false; |
| - |
| -/** |
| - * A callback to be invoked when the system information is ready. |
| - * @type {function(sysInfo)} |
| - */ |
| -var onSystemInfoReadyCallback = null; |
| - |
| // To generate a hashed extension ID, use a sha-256 hash, all in lower case. |
| // Example: |
| // echo -n 'abcdefghijklmnopqrstuvwxyzabcdef' | sha1sum | \ |
| @@ -111,6 +79,101 @@ var whitelistedExtensionIds = [ |
| '3BC3740BFC58F06088B300274B4CFBEA20136342', // http://crbug.com/541769 |
| ]; |
| +/** |
| + * A FeedbackRequest object represents a unique feedback report, requested by an |
| + * instance of the feedback window. It contains the system information specific |
| + * to this report, the full feedbackInfo, and callbacks to send the report upon |
| + * request. |
| + */ |
| +class FeedbackRequest { |
|
xiyuan
2016/03/14 23:47:28
Are we allowed to use this ES6 feature? This seems
afakhry
2016/03/15 19:25:38
I asked sky@ who referred me to estade@ who referr
xiyuan
2016/03/15 19:54:06
Thank you for digging into this. I am fine as long
|
| + constructor(requestId, feedbackInfo) { |
| + this.id_ = requestId; |
| + this.feedbackInfo_ = feedbackInfo; |
| + this.onSystemInfoReadyCallback_ = null; |
| + this.isSystemInfoReady_ = false; |
| + } |
| + |
| + /** |
| + * Called when the system information is sent from the C++ side. |
| + * @param {Object} sysInfo The received system information. |
| + */ |
| + getSystemInformationCallback(sysInfo) { |
| + this.isSystemInfoReady_ = true; |
| + |
| + // Combine the newly received system information with whatever system |
| + // information we have in the feedback info (if any). |
| + if (this.feedbackInfo_.systemInformation) { |
| + this.feedbackInfo_.systemInformation = |
| + this.feedbackInfo_.systemInformation.concat(sysInfo); |
| + } else { |
| + this.feedbackInfo_.systemInformation = sysInfo; |
| + } |
|
xiyuan
2016/03/14 23:47:28
Just to double check with you that changes here on
afakhry
2016/03/15 19:25:38
Yes I made sure they refer to the same thing, and
|
| + |
| + if (this.onSystemInfoReadyCallback_ != null) { |
| + this.onSystemInfoReadyCallback_(); |
| + this.onSystemInfoReadyCallback_ = null; |
| + } |
| + } |
| + |
| + /** |
| + * Retrieves the system information for this request object. |
| + * @param {function()} callback Invoked to notify the listener that the system |
| + * information has been received. |
| + */ |
| + getSystemInformation(callback) { |
| + if (this.isSystemInfoReady_) { |
| + callback(); |
| + return; |
| + } |
| + |
| + this.onSystemInfoReadyCallback_ = callback; |
| + // The C++ side must reply to the callback specific to this object. |
| + var boundCallback = this.getSystemInformationCallback.bind(this); |
| + chrome.feedbackPrivate.getSystemInformation(boundCallback); |
| + } |
| + |
| + /** |
| + * Sends the feedback report represented by the object, either now if system |
| + * information is ready, or later once it is. |
| + * @param {boolean} useSystemInfo True if the user would like the system |
| + * information to be sent with the report. |
| + */ |
| + sendReport(useSystemInfo) { |
| + if (useSystemInfo && !this.isSystemInfoReady_) { |
| + this.onSystemInfoReadyCallback_ = this.sendReportNow; |
|
xiyuan
2016/03/14 23:47:28
Think we need to bind here, i.e. this.sendReportNo
afakhry
2016/03/15 19:25:38
It works without this bind, since it will be calle
xiyuan
2016/03/15 19:54:06
Interesting. Just tried it and it works as you des
|
| + return; |
| + } |
| + |
| + this.sendReportNow(); |
| + } |
| + |
| + /** |
| + * Sends the report immediately and removes this object once the report is |
| + * sent. |
| + */ |
| + sendReportNow() { |
| + /** @const */ var ID = this.id_; |
| + chrome.feedbackPrivate.sendFeedback(this.feedbackInfo_, |
| + function(result) { |
| + console.log('Feedback: Report sent for request with ID ' + ID); |
| + |
| + // The following deletes this FeedbackRequest object. |
| + feedbackRequestsMap.delete(ID); |
| + }); |
| + } |
| +}; |
| + |
| +/** |
| + * Maps each FeedbackRequest object by its unique ID. |
| + * @type {Map} |
| + */ |
| +var feedbackRequestsMap = new Map(); |
| + |
| +/** |
| + * Used to generate unique IDs for FeedbackRequest objects. |
| + * @type {number} |
| + */ |
| +var lastUsedId = 0; |
| /** |
| * Function to determine whether or not a given extension id is whitelisted to |
| @@ -145,13 +208,10 @@ function senderWhitelisted(id, startFeedbackCallback, feedbackInfo) { |
| * @param {function(Object)} sendResponse Callback for sending a response. |
| */ |
| function feedbackReadyHandler(request, sender, sendResponse) { |
| - if (request.ready) { |
| - chrome.runtime.sendMessage( |
| - {sentFromEventPage: true, data: initialFeedbackInfo}); |
| - } |
| + if (request.ready) |
| + chrome.runtime.sendMessage({sentFromEventPage: true}); |
| } |
| - |
| /** |
| * Callback which gets notified if another extension is requesting feedback. |
| * @param {Object} request The message request object. |
| @@ -164,38 +224,6 @@ function requestFeedbackHandler(request, sender, sendResponse) { |
| } |
| /** |
| - * Called when the system information is sent from the C++ side. |
| - * @param {Object} sysInfo The received system information. |
| - */ |
| - |
| -function getSystemInformationCallback(sysInfo) { |
| - systemInfo = sysInfo; |
| - isSystemInfoReady = true; |
| - if (onSystemInfoReadyCallback != null) |
| - onSystemInfoReadyCallback(sysInfo); |
| -} |
| - |
| -/** |
| - * If the user requested to send the report before the system information was |
| - * received, this callback will be invoked once the system information is ready |
| - * to send the report then. |
| - * @param {Object} sysInfo The received system information. |
| - */ |
| - |
| -function onSysInfoReadyForSend(sysInfo) { |
| - // Combine the newly received system information with whatever system |
| - // information we have in the final feedback info (if any). |
| - if (finalFeedbackInfo.systemInformation) { |
| - finalFeedbackInfo.systemInformation = |
| - finalFeedbackInfo.systemInformation.concat(sysInfo); |
| - } else { |
| - finalFeedbackInfo.systemInformation = sysInfo; |
| - } |
| - |
| - chrome.feedbackPrivate.sendFeedback(finalFeedbackInfo, function(result) {}); |
| -} |
| - |
| -/** |
| * Callback which starts up the feedback UI. |
| * @param {Object} feedbackInfo Object containing any initial feedback info. |
| */ |
| @@ -213,46 +241,55 @@ function startFeedbackUI(feedbackInfo) { |
| hidden: true, |
| resizable: false }, |
| function(appWindow) { |
| - // Initialize the state of the app only once upon the creation of the |
| - // feedback UI window. |
| - initialFeedbackInfo = feedbackInfo; |
| - finalFeedbackInfo = null; |
| - systemInfo = null; |
| - isSystemInfoReady = false; |
| - onSystemInfoReadyCallback = null; |
| + // Generate a unique feedback request ID for this feedback window. |
| + // A FeedbackRequest object is used to represent this instance of the |
| + // feedback window. |
| + /** @const */ var ID = ++lastUsedId; |
| + feedbackRequestsMap.set(ID, new FeedbackRequest(ID, feedbackInfo)); |
|
xiyuan
2016/03/14 23:47:28
It seems |feedbackRequestsMap| could be optimized
afakhry
2016/03/15 19:25:38
Yes, thanks for the suggestion. Done.
However, we
xiyuan
2016/03/15 19:54:06
I don't think we need to manage this explicitly. I
afakhry
2016/03/16 00:45:34
Right. I removed the map, and it works. My brain n
|
| + // The feedbackInfo member of the new window should refer to the one in |
| + // its corresponding FeedbackRequest object to avoid copying and |
| + // duplicatations. |
| + appWindow.contentWindow.feedbackInfo = |
| + feedbackRequestsMap.get(ID).feedbackInfo_; |
| + |
| + // When this instance of the feedback window is closed, the |
| + // corresponding FeedbackRequest object must be deleted unless it needs |
| + // to be kept alive until the report is sent later. |
| + var deferRequestdeleteUntilSent = false; |
| // Define some functions for the new window so that it can call back |
| // into here. |
| // Define a function for the new window to get the system information. |
| appWindow.contentWindow.getSystemInformation = function(callback) { |
| - if (!isSystemInfoReady) { |
| - onSystemInfoReadyCallback = callback; |
| - chrome.feedbackPrivate.getSystemInformation( |
| - getSystemInformationCallback); |
| + var request = feedbackRequestsMap.get(ID); |
| + if (request == undefined) { |
| + console.log('Feedback Error: Invalid request ID ' + ID); |
| return; |
| } |
| - callback(systemInfo); |
| + request.getSystemInformation(callback); |
| }; |
| - // Define a function to be called by the new window when the report is |
| - // not ready yet, and has to be sent later when the system information |
| - // is received. |
| - appWindow.contentWindow.sendReportLater = function(feedbackInfo) { |
| - finalFeedbackInfo = feedbackInfo; |
| - if (!isSystemInfoReady) { |
| - onSystemInfoReadyCallback = onSysInfoReadyForSend; |
| + // Define a function to request sending the feedback report. |
| + appWindow.contentWindow.sendFeedbackReport = function(useSystemInfo) { |
| + var request = feedbackRequestsMap.get(ID); |
| + if (request == undefined) { |
| + console.log('Feedback Error: Invalid request ID ' + ID); |
| return; |
| } |
| - onSysInfoReadyForSend(systemInfo); |
| + // The report will be sent by the request object. Keep it alive until |
| + // the report is sent. |
| + deferRequestdeleteUntilSent = true; |
| + request.sendReport(useSystemInfo); |
| }; |
| - // Returns whether the system information has been received or not. |
| - appWindow.contentWindow.isSystemInfoReady = function() { |
| - return isSystemInfoReady; |
| - }; |
| + // Observe when the window is closed. |
| + appWindow.onClosed.addListener(function() { |
| + if (!deferRequestdeleteUntilSent) |
| + feedbackRequestsMap.delete(appWindow.contentWindow.REQUEST_ID); |
| + }); |
| }); |
| } |