Bug 1322383 - Ignore GFX sanity check window during startup of Firefox. r=ato+446296
☠☠ backed out by af67c447c17b ☠ ☠
authorHenrik Skupin <mail@hskupin.info>
Tue, 28 Feb 2017 17:39:54 +0100
changeset 374390 d080b72ec241db12e79f1da4b08e2ed6870ab7c4
parent 374389 20f6edaec61ee22350354dbed3f684802fdcee3b
child 374391 df1c149b427f2665057681358d9126c9cafa7668
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersato
bugs1322383, 446296
milestone54.0a1
Bug 1322383 - Ignore GFX sanity check window during startup of Firefox. r=ato+446296 On Windows systems an additional chrome window will be opened during startup. It's used for testing specific GFX related features. It's located off-screen and will usually be closed immediately. But in some situations it can take longer. To avoid an inconsistent list of start window handles Marionette should wait with starting the test until this window has actually been closed. MozReview-Commit-ID: 3k1hoSYm0Af
testing/marionette/components/marionette.js
testing/marionette/driver.js
--- a/testing/marionette/components/marionette.js
+++ b/testing/marionette/components/marionette.js
@@ -50,16 +50,17 @@ MarionetteComponent.prototype = {
   contractID: MARIONETTE_CONTRACTID,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler, Ci.nsIObserver]),
   _xpcom_categories: [
     {category: "command-line-handler", entry: "b-marionette"},
     {category: "profile-after-change", service: true}
   ],
   enabled: false,
   finalUiStartup: false,
+  gfxWindow: null,
   server: null,
 };
 
 MarionetteComponent.prototype.setupLogger_ = function (level) {
   let log = Log.repository.getLogger("Marionette");
   log.level = level;
   log.addAppender(new Log.DumpAppender());
   return log;
@@ -108,49 +109,78 @@ MarionetteComponent.prototype.handle = f
   // if the CLI is there then lets do work otherwise nothing to see
   if (cmdLine.handleFlag("marionette", false)) {
     this.enabled = true;
     this.logger.debug("Marionette enabled via command-line flag");
     this.init();
   }
 };
 
-MarionetteComponent.prototype.observe = function (subj, topic, data) {
+MarionetteComponent.prototype.observe = function (subject, topic, data) {
   switch (topic) {
     case "profile-after-change":
+      // Using sessionstore-windows-restored as the xpcom category doesn't seem to work,
+      // so we wait for that by adding an observer here.
+      this.observerService.addObserver(this, "sessionstore-windows-restored", false);
+
       this.maybeReadPrefsFromEnvironment();
-      // Using final-ui-startup as the xpcom category doesn't seem to work,
-      // so we wait for that by adding an observer here.
-      this.observerService.addObserver(this, "final-ui-startup", false);
+
 #ifdef ENABLE_MARIONETTE
       this.enabled = Preferences.get(ENABLED_PREF, false);
       if (this.enabled) {
         this.logger.debug("Marionette enabled via build flag and pref");
 
         // We want to suppress the modal dialog that's shown
         // when starting up in safe-mode to enable testing.
         if (Services.appinfo.inSafeMode) {
           this.observerService.addObserver(this, "domwindowopened", false);
         }
       }
 #endif
       break;
 
-    case "final-ui-startup":
-      this.finalUiStartup = true;
-      this.observerService.removeObserver(this, topic);
-      this.observerService.addObserver(this, "xpcom-shutdown", false);
-      this.init();
+    case "domwindowclosed":
+      if (this.gfxWindow === null || subject === this.gfxWindow) {
+        this.observerService.removeObserver(this, topic);
+
+        this.observerService.addObserver(this, "xpcom-shutdown", false);
+        this.finalUiStartup = true;
+        this.init();
+      }
       break;
 
     case "domwindowopened":
       this.observerService.removeObserver(this, topic);
       this.suppressSafeModeDialog_(subj);
       break;
 
+    case "sessionstore-windows-restored":
+      this.observerService.removeObserver(this, topic);
+
+      // When Firefox starts on Windows, an additional GFX sanity test window
+      // may appear off-screen.  Marionette should wait for it to close.
+      let winEn = Services.wm.getEnumerator(null);
+      while (winEn.hasMoreElements()) {
+        let win = winEn.getNext();
+        if (win.document.documentURI == "chrome://gfxsanity/content/sanityparent.html") {
+          this.gfxWindow = win;
+          break;
+        }
+      }
+
+      if (this.gfxWindow) {
+        this.observerService.addObserver(this, "domwindowclosed", false);
+      } else {
+        this.observerService.addObserver(this, "xpcom-shutdown", false);
+        this.finalUiStartup = true;
+        this.init();
+      }
+
+      break;
+
     case "xpcom-shutdown":
       this.observerService.removeObserver(this, "xpcom-shutdown");
       this.uninit();
       break;
   }
 };
 
 MarionetteComponent.prototype.maybeReadPrefsFromEnvironment = function() {
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -36,17 +36,17 @@ Cu.import("chrome://marionette/content/m
 Cu.import("chrome://marionette/content/proxy.js");
 Cu.import("chrome://marionette/content/session.js");
 Cu.import("chrome://marionette/content/simpletest.js");
 Cu.import("chrome://marionette/content/wait.js");
 
 this.EXPORTED_SYMBOLS = ["GeckoDriver", "Context"];
 
 var FRAME_SCRIPT = "chrome://marionette/content/listener.js";
-const BROWSER_STARTUP_FINISHED = "browser-delayed-startup-finished";
+
 const CLICK_TO_START_PREF = "marionette.debugging.clicktostart";
 const CONTENT_LISTENER_PREF = "marionette.contentListener";
 
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 const SUPPORTED_STRATEGIES = new Set([
   element.Strategy.ClassName,
   element.Strategy.Selector,
@@ -65,23 +65,16 @@ const globalMessageManager = Cc["@mozill
 // API's are ready; see bug 792647.  This assumes that marionette-server.js
 // will be loaded before the 'system-message-listener-ready' message
 // is fired.  If this stops being true, this approach will have to change.
 var systemMessageListenerReady = false;
 Services.obs.addObserver(function() {
   systemMessageListenerReady = true;
 }, "system-message-listener-ready", false);
 
-// This is used on desktop to prevent newSession from returning before a page
-// load initiated by the Firefox command line has completed.
-var delayedBrowserStarted = false;
-Services.obs.addObserver(function () {
-  delayedBrowserStarted = true;
-}, BROWSER_STARTUP_FINISHED, false);
-
 this.Context = {
   CHROME: "chrome",
   CONTENT: "content",
 };
 
 this.Context.fromString = function (s) {
   s = s.toUpperCase();
   if (s in this) {
@@ -617,67 +610,58 @@ GeckoDriver.prototype.newSession = funct
   // services hanging around.
   if (this.a11yChecks && accessibility.service) {
     logger.info("Preemptively starting accessibility service in Chrome");
   }
 
   let registerBrowsers = this.registerPromise();
   let browserListening = this.listeningPromise();
 
-  let waitForWindow = function() {
+  let waitForWindow = function () {
     let win = Services.wm.getMostRecentWindow("navigator:browser");
+
     if (!win) {
-      // if the window isn't even created, just poll wait for it
+      // if no browser window exists, just poll wait for it
       let checkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
       checkTimer.initWithCallback(waitForWindow.bind(this), 100,
           Ci.nsITimer.TYPE_ONE_SHOT);
+
     } else if (win.document.readyState != "complete") {
       // otherwise, wait for it to be fully loaded before proceeding
       let listener = ev => {
         // ensure that we proceed, on the top level document load event
         // (not an iframe one...)
         if (ev.target != win.document) {
           return;
         }
         win.removeEventListener("load", listener);
         waitForWindow.call(this);
       };
       win.addEventListener("load", listener, true);
+
     } else {
       let clickToStart = Preferences.get(CLICK_TO_START_PREF);
       if (clickToStart) {
         Services.prompt.alert(win, "", "Click to start execution of marionette tests");
       }
       this.startBrowser(win, true);
     }
   };
 
-  let runSessionStart = function() {
-    if (!Preferences.get(CONTENT_LISTENER_PREF)) {
-      waitForWindow.call(this);
-    } else if (this.appName != "Firefox" && this.curBrowser === null) {
-      // if there is a content listener, then we just wake it up
-      this.addBrowser(this.getCurrentWindow());
-      this.curBrowser.startSession(this.whenBrowserStarted.bind(this));
-      this.mm.broadcastAsyncMessage("Marionette:restart", {});
-    } else {
-      throw new WebDriverError("Session already running");
-    }
-    this.switchToGlobalMessageManager();
-  };
-
-  if (!delayedBrowserStarted && this.appName != "B2G") {
-    let self = this;
-    Services.obs.addObserver(function onStart() {
-      Services.obs.removeObserver(onStart, BROWSER_STARTUP_FINISHED);
-      runSessionStart.call(self);
-    }, BROWSER_STARTUP_FINISHED, false);
+  if (!Preferences.get(CONTENT_LISTENER_PREF)) {
+    waitForWindow.call(this);
+  } else if (this.appName != "Firefox" && this.curBrowser === null) {
+    // if there is a content listener, then we just wake it up
+    this.addBrowser(this.getCurrentWindow());
+    this.curBrowser.startSession(this.whenBrowserStarted.bind(this));
+    this.mm.broadcastAsyncMessage("Marionette:restart", {});
   } else {
-    runSessionStart.call(this);
+    throw new WebDriverError("Session already running");
   }
+  this.switchToGlobalMessageManager();
 
   yield registerBrowsers;
   yield browserListening;
 
   if (this.curBrowser.tab) {
     browser.getBrowserForTab(this.curBrowser.tab).focus();
   }