Bug 1477506 - In overlay loader, add window creation listener before enumerating existing windows; r=Fallen
authorGeoff Lankow <geoff@darktrojan.net>
Thu, 25 Jul 2019 16:37:38 +1200
changeset 76432 f5dc07feb56e3db11b0b335ff96e2bc2738015a4
parent 76423 e2dad5423b3ba2aa4742d4f0e74e0a06ebe92291
child 76433 94e732a2778e94d301171a13a58e84c8a56391b5
child 76434 71dbc5c422f8d52a12c8983bf0671927c2838e1a
push id8889
push usergeoff@darktrojan.net
push dateThu, 25 Jul 2019 05:41:45 +0000
treeherdertry-comm-central@94e732a2778e [default view] [failures only]
reviewersFallen
bugs1477506
Bug 1477506 - In overlay loader, add window creation listener before enumerating existing windows; r=Fallen
mail/components/extensions/parent/ext-legacy.js
--- a/mail/components/extensions/parent/ext-legacy.js
+++ b/mail/components/extensions/parent/ext-legacy.js
@@ -156,36 +156,42 @@ this.legacy = class extends ExtensionAPI
         }
 
         instance.observe(null, "profile-after-change", null);
       } catch (e) {
         console.error("Error firing profile-after-change listener for", contractid);
       }
     }
 
-    // Add overlays to all existing windows.
-    let enumerator = Services.wm.getEnumerator("mail:3pane");
-    if (enumerator.hasMoreElements() && enumerator.getNext().document.readyState == "complete") {
-      getAllWindows().forEach(w => {
-        if (["interactive", "complete"].includes(w.document.readyState)) {
-          Overlays.load(chromeManifest, w);
-        }
-      });
-    }
+    // Overlays.load must only be called once per window per extension.
+    // We use this WeakSet to remember all windows we've already seen.
+    let seenWindows = new WeakSet();
 
     // Listen for new windows to overlay.
     let documentObserver = {
-      observe(document) {
-        if (ExtensionCommon.instanceOf(document, "XULDocument")) {
-          Overlays.load(chromeManifest, document.defaultView);
+      observe(doc) {
+        let win = doc.defaultView;
+        if (ExtensionCommon.instanceOf(doc, "XULDocument") &&
+            !seenWindows.has(win)) {
+          seenWindows.add(win);
+          Overlays.load(chromeManifest, win);
         }
       },
     };
     Services.obs.addObserver(documentObserver, "chrome-document-interactive");
 
+    // Add overlays to all existing windows.
+    getAllWindows().forEach(win => {
+      if (["interactive", "complete"].includes(win.document.readyState) &&
+          !seenWindows.has(win)) {
+        seenWindows.add(win);
+        Overlays.load(chromeManifest, win);
+      }
+    });
+
     this.extension.callOnClose({
       close: () => {
         Services.obs.removeObserver(documentObserver, "chrome-document-interactive");
       },
     });
   }
 
   // The following functions are for bootstrapped add-ons.