Bug 1394704 - Early return ManageRecords.loadRecords during the loading process. r=lchang,scottwu draft
authorSean Lee <selee@mozilla.com>
Tue, 29 Aug 2017 14:09:18 +0800
changeset 658529 ec3a12736feb5a979d2a23d708e3890f6fc7ecc7
parent 657984 a46a5879b8781ae9ea99f37b5d34a891f0f75047
child 729692 680c07d47a469516c6aa515b847e968db825a4ca
push id77809
push userbmo:selee@mozilla.com
push dateMon, 04 Sep 2017 10:25:51 +0000
reviewerslchang, scottwu
bugs1394704
milestone57.0a1
Bug 1394704 - Early return ManageRecords.loadRecords during the loading process. r=lchang,scottwu MozReview-Commit-ID: 8yR6kDg67PL
browser/extensions/formautofill/content/manageDialog.js
--- a/browser/extensions/formautofill/content/manageDialog.js
+++ b/browser/extensions/formautofill/content/manageDialog.js
@@ -24,16 +24,18 @@ this.log = null;
 FormAutofillUtils.defineLazyLogGetter(this, "manageAddresses");
 
 class ManageRecords {
   constructor(subStorageName, elements) {
     this._storageInitPromise = profileStorage.initialize();
     this._subStorageName = subStorageName;
     this._elements = elements;
     this._records = [];
+    this._newRequest = false;
+    this._isLoadingRecords = false;
     this.prefWin = window.opener;
     this.localizeDocument();
     window.addEventListener("DOMContentLoaded", this, {once: true});
   }
 
   async init() {
     await this.loadRecords();
     this.attachEventListeners();
@@ -65,27 +67,50 @@ class ManageRecords {
    * @returns {object}
    */
   async getStorage() {
     await this._storageInitPromise;
     return profileStorage[this._subStorageName];
   }
 
   /**
-   * Load records and render them.
+   * Load records and render them. This function is a wrapper for _loadRecords
+   * to ensure any reentrant will be handled well.
    */
   async loadRecords() {
+    // This function can be early returned when there is any reentrant happends.
+    // "_newRequest" needs to be set to ensure all changes will be applied.
+    if (this._isLoadingRecords) {
+      this._newRequest = true;
+      return;
+    }
+    this._isLoadingRecords = true;
+
+    await this._loadRecords();
+
+    // _loadRecords should be invoked again if there is any multiple entrant
+    // during running _loadRecords(). This step ensures that the latest request
+    // still is applied.
+    while (this._newRequest) {
+      this._newRequest = false;
+      await this._loadRecords();
+    }
+    this._isLoadingRecords = false;
+
+    // For testing only: Notify when records are loaded
+    this._elements.records.dispatchEvent(new CustomEvent("RecordsLoaded"));
+  }
+
+  async _loadRecords() {
     let storage = await this.getStorage();
     let records = storage.getAll();
     // Sort by last modified time starting with most recent
     records.sort((a, b) => b.timeLastModified - a.timeLastModified);
     await this.renderRecordElements(records);
     this.updateButtonsStates(this._selectedOptions.length);
-    // For testing only: Notify when records are loaded
-    this._elements.records.dispatchEvent(new CustomEvent("RecordsLoaded"));
   }
 
   /**
    * Render the records onto the page while maintaining selected options if
    * they still exist.
    *
    * @param  {array<object>} records
    */