Bug 918383 - Fix app debugging when connecting to a simulator app that isn't installed yet. r=paul a=lsblakk
authorAlexandre Poirot <poirot.alex@gmail.com>
Thu, 19 Sep 2013 10:42:00 +0200
changeset 155551 bef0f42eeadae38e1dbcdaf7c475d3a1b99807b9
parent 155550 a02ef3b1129fc75d050a4e90a992fe7ee64bef35
child 155552 e3ca1451d061df04b8aad7a077e643d8f822a604
push id4324
push userprouget@mozilla.com
push dateSat, 28 Sep 2013 16:05:55 +0000
treeherdermozilla-aurora@e3ca1451d061 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspaul, lsblakk
bugs918383
milestone26.0a2
Bug 918383 - Fix app debugging when connecting to a simulator app that isn't installed yet. r=paul a=lsblakk
browser/devtools/app-manager/content/projects.js
--- a/browser/devtools/app-manager/content/projects.js
+++ b/browser/devtools/app-manager/content/projects.js
@@ -252,62 +252,84 @@ let UI = {
       promive.resolve(res);
     });
     return deferred.promise;
   },
 
   debug: function(button, location) {
     button.disabled = true;
     let project = AppProjects.get(location);
+
+    let onFailedToStart = (error) => {
+      // If not installed, install and open it
+      if (error == "NO_SUCH_APP") {
+        return this.install(project);
+      } else {
+        throw error;
+      }
+    };
+    let onStarted = () => {
+      // Once we asked the app to launch, the app isn't necessary completely loaded.
+      // launch request only ask the app to launch and immediatly returns.
+      // We have to keep trying to get app tab actors required to create its target.
+      let deferred = promise.defer();
+      let loop = (count) => {
+        // Ensure not looping for ever
+        if (count >= 100) {
+          deferred.reject("Unable to connect to the app");
+          return;
+        }
+        // Also, in case the app wasn't installed yet, we also have to keep asking the
+        // app to launch, as launch request made right after install may race.
+        this.start(project);
+        getTargetForApp(
+          this.connection.client,
+          this.listTabsResponse.webappsActor,
+          this._getProjectManifestURL(project)).
+            then(deferred.resolve,
+                 (err) => {
+                   if (err == "appNotFound")
+                     setTimeout(loop, 500, count + 1);
+                   else
+                     deferred.reject(err);
+                 });
+      };
+      loop(0);
+      return deferred.promise;
+    };
+    let onTargetReady = (target) => {
+      // Finally, when it's finally opened, display the toolbox
+      let deferred = promise.defer();
+      gDevTools.showToolbox(target,
+                            null,
+                            devtools.Toolbox.HostType.WINDOW).then(toolbox => {
+        this.connection.once(Connection.Events.DISCONNECTED, () => {
+          toolbox.destroy();
+        });
+        deferred.resolve(toolbox);
+      });
+      return deferred.promise;
+    };
+
     // First try to open the app
     this.start(project)
-        .then(
-         null,
-         (error) => {
-           // If not installed, install and open it
-           if (error == "NO_SUCH_APP") {
-             return this.install(project)
-                        .then(() => this.start(project));
-           } else {
-             throw error;
-           }
-         })
-        .then(() => {
-           // Finally, when it's finally opened, display the toolbox
-           return this.openToolbox(project)
-        })
+        .then(null, onFailedToStart)
+        .then(onStarted)
+        .then(onTargetReady)
         .then(() => {
            // And only when the toolbox is opened, release the button
            button.disabled = false;
          },
          (msg) => {
            button.disabled = false;
            alert(msg);
            this.connection.log(msg);
          });
   },
 
-  openToolbox: function(project) {
-    let deferred = promise.defer();
-    let manifest = this._getProjectManifestURL(project);
-    getTargetForApp(this.connection.client,
-                    this.listTabsResponse.webappsActor,
-                    manifest).then((target) => {
-      gDevTools.showToolbox(target,
-                            null,
-                            devtools.Toolbox.HostType.WINDOW).then(toolbox => {
-        this.connection.once(Connection.Events.DISCONNECTED, () => {
-          toolbox.destroy();
-        });
-        deferred.resolve();
-      });
-    }, deferred.reject);
-    return deferred.promise;
-  },
-
   reveal: function(location) {
     let project = AppProjects.get(location);
     if (project.type == "packaged") {
       let projectFolder = FileUtils.File(project.location);
       projectFolder.reveal();
     } else {
       // TODO: eventually open hosted apps in firefox
       // when permissions are correctly supported by firefox