Bug 918383 - Fix app debugging when connecting to a simulator app that isn't installed yet. r=paul
authorAlexandre Poirot <poirot.alex@gmail.com>
Thu, 19 Sep 2013 10:42:00 +0200
changeset 161892 4ea055ede55144d3058be0d51a3fa2dc72a72ad6
parent 161731 debb2fa19aece84058d418a24bc7bacd7ca55f8d
child 161893 3ca60aa3a003f64c9b73b0db4d2851a6bfa7a21f
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspaul
bugs918383
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 918383 - Fix app debugging when connecting to a simulator app that isn't installed yet. r=paul
browser/devtools/app-manager/content/projects.js
--- a/browser/devtools/app-manager/content/projects.js
+++ b/browser/devtools/app-manager/content/projects.js
@@ -254,62 +254,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