Backed out 2 changesets (bug 1176712) for gip f5 permafail CLOSED TREE a=bustage
authorWes Kocher <wkocher@mozilla.com>
Thu, 02 Jul 2015 09:21:23 -0700
changeset 251173 a92c364a6d2e0e8f808909fbc0a197f322467b79
parent 251172 e2a194964fa2ca4e44a6903511f69b4dbe3e3eb8
child 251174 f66705bc0fd5d9cdfad62539f38be9d3c91c21d3
child 251205 206bbf2e268c90e3c117ab75413bab6e7ea3daf5
push id13833
push userryanvm@gmail.com
push dateThu, 02 Jul 2015 20:00:55 +0000
treeherderfx-team@98101796b275 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbustage
bugs1176712
milestone42.0a1
backs out52fd1c8b0fcb409205f98e48d32ee0d8d44d8daf
6baeaddb32cc5ed8271773317a0049c19b49016b
Backed out 2 changesets (bug 1176712) for gip f5 permafail CLOSED TREE a=bustage Backed out changeset 52fd1c8b0fcb (bug 1176712) Backed out changeset 6baeaddb32cc (bug 1176712)
dom/activities/ActivitiesService.jsm
dom/activities/tests/mochi/common.js
dom/activities/tests/mochi/manifest.webapp
dom/activities/tests/mochi/mochitest.ini
dom/activities/tests/mochi/test_dev_mode_activity.html
dom/activities/tests/mochi/test_same_name_multiple_filters.html
dom/apps/Webapps.jsm
--- a/dom/activities/ActivitiesService.jsm
+++ b/dom/activities/ActivitiesService.jsm
@@ -29,17 +29,17 @@ XPCOMUtils.defineLazyServiceGetter(this,
 
 this.EXPORTED_SYMBOLS = [];
 
 function debug(aMsg) {
   //dump("-- ActivitiesService.jsm " + Date.now() + " " + aMsg + "\n");
 }
 
 const DB_NAME    = "activities";
-const DB_VERSION = 2;
+const DB_VERSION = 1;
 const STORE_NAME = "activities";
 
 function ActivitiesDb() {
 
 }
 
 ActivitiesDb.prototype = {
   __proto__: IndexedDBHelper.prototype,
@@ -58,109 +58,38 @@ ActivitiesDb.prototype = {
    *  manifest:            String
    *  name:                String
    *  icon:                String
    *  description:         jsval
    * }
    */
   upgradeSchema: function actdb_upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
     debug("Upgrade schema " + aOldVersion + " -> " + aNewVersion);
-
-    let self = this;
-
-    function upgrade(currentVersion) {
-      let next = upgrade.bind(self, currentVersion + 1);
-      switch (currentVersion) {
-        case 0:
-          self.createSchema(aDb, next);
-          break;
-        case 1:
-          self.upgradeSchemaVersion2(aDb, aTransaction, next);
-          break;
-      }
-    }
-
-    upgrade(aOldVersion);
-  },
-
-  createSchema: function(aDb, aNext) {
     let objectStore = aDb.createObjectStore(STORE_NAME, { keyPath: "id" });
 
     // indexes
     objectStore.createIndex("name", "name", { unique: false });
     objectStore.createIndex("manifest", "manifest", { unique: false });
 
     debug("Created object stores and indexes");
-
-    aNext();
-  },
-
-  upgradeSchemaVersion2: function(aDb, aTransaction, aNext) {
-    debug("Upgrading DB to version 2");
-
-    // In order to be able to have multiple activities with same name
-    // but different descriptions, we need to update the keypath from
-    // a hash made from {manifest, name} to a hash made from {manifest,
-    // name, description}.
-    //
-    // Unfortunately, updating the keypath is not allowed by IDB, so we
-    // need to remove and recreate the activities object store.
-
-    let activities = [];
-    let objectStore = aTransaction.objectStore(STORE_NAME);
-    objectStore.openCursor().onsuccess = (event) => {
-      let cursor = event.target.result;
-      if (!cursor) {
-        aDb.deleteObjectStore(STORE_NAME);
-
-        let objectStore = aDb.createObjectStore(STORE_NAME, { keyPath: "id" });
-
-        // indexes
-        objectStore.createIndex("name", "name", { unique: false });
-        objectStore.createIndex("manifest", "manifest", { unique: false });
-
-        this.add(activities, () => {
-          debug("DB upgraded to version 2");
-          aNext();
-        }, () => {
-          dump("Error upgrading DB to version 2 " + error + "\n");
-        });
-        return;
-      }
-
-      let activity = cursor.value;
-      debug("Upgrading activity " + JSON.stringify(activity));
-      activity.id = this.createId(activity);
-      activities.push(activity);
-      cursor.continue();
-    };
   },
 
   // unique ids made of (uri, action)
   createId: function actdb_createId(aObject) {
     let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
                       .createInstance(Ci.nsIScriptableUnicodeConverter);
     converter.charset = "UTF-8";
 
     let hasher = Cc["@mozilla.org/security/hash;1"]
                    .createInstance(Ci.nsICryptoHash);
     hasher.init(hasher.SHA1);
 
     // add uri and action to the hash
-    ["manifest", "name", "description"].forEach(function(aProp) {
-      if (!aObject[aProp]) {
-        return;
-      }
-
-      let property = aObject[aProp];
-      if (aProp == "description") {
-        property = JSON.stringify(aObject[aProp]);
-      }
-
-      let data = converter.convertToByteArray(property, {});
+    ["manifest", "name"].forEach(function(aProp) {
+      let data = converter.convertToByteArray(aObject[aProp], {});
       hasher.update(data, data.length);
     });
 
     return hasher.finish(true);
   },
 
   // Add all the activities carried in the |aObjects| array.
   add: function actdb_add(aObjects, aSuccess, aError) {
@@ -176,27 +105,26 @@ ActivitiesDb.prototype = {
         debug("Going to add " + JSON.stringify(object));
         store.put(object);
       }, this);
     }.bind(this), aSuccess, aError);
   },
 
   // Remove all the activities carried in the |aObjects| array.
   remove: function actdb_remove(aObjects) {
-    this.newTxn("readwrite", STORE_NAME, (txn, store) => {
-      aObjects.forEach((aObject) => {
+    this.newTxn("readwrite", STORE_NAME, function (txn, store) {
+      aObjects.forEach(function (aObject) {
         let object = {
           manifest: aObject.manifest,
-          name: aObject.name,
-          description: aObject.description
+          name: aObject.name
         };
         debug("Going to remove " + JSON.stringify(object));
         store.delete(this.createId(object));
-      });
-    }, function() {}, function() {});
+      }, this);
+    }.bind(this), function() {}, function() {});
   },
 
   // Remove all activities associated with the given |aManifest| URL.
   removeAll: function actdb_removeAll(aManifest) {
     this.newTxn("readwrite", STORE_NAME, function (txn, store) {
       let index = store.index("manifest");
       let request = index.mozGetAll(aManifest);
       request.onsuccess = function manifestActivities(aEvent) {
@@ -314,18 +242,18 @@ let Activities = {
               "result": aResult
             });
             break;
           }
           case Ci.nsIActivityUIGlueCallback.WEBAPPS_ACTIVITY: {
             debug("Activity choice: " + aResult);
 
             // We have no matching activity registered, let's fire an error.
-            // Don't do this check until we have passed to UIGlue so the glue
-            // can choose to launch its own activity if needed.
+            // Don't do this check until we have passed to UIGlue so the glue can choose to launch
+            // its own activity if needed.
             if (aResults.options.length === 0) {
               self.trySendAndCleanup(aMsg.id, "Activity:FireError", {
                 "id": aMsg.id,
                 "error": "NO_PROVIDER"
               });
               return;
             }
 
deleted file mode 100644
--- a/dom/activities/tests/mochi/common.js
+++ /dev/null
@@ -1,37 +0,0 @@
-const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
-
-const ACTIVITY_GLUE_CID = Components.ID("{f4cfbe10-a106-4cd1-b04e-0d2a6aac138b}");
-const SYS_MSG_GLUE_CID = Components.ID("{b0b6b9af-bc4e-4200-bffe-fb7691065ec9}");
-
-const gRootUrl = "http://test/chrome/dom/activities/tests/mochi/";
-
-function registerComponent(aObject, aDescription, aContract, aCid) {
-  info("Registering " + aCid);
-
-  var componentManager =
-    Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
-  componentManager.registerFactory(aCid, aDescription, aContract, aObject);
-
-  // Keep the id on the object so we can unregister later.
-  aObject.cid = aCid;
-}
-
-function unregisterComponent(aObject) {
-  info("Unregistering " + aObject.cid);
-  var componentManager =
-    Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
-  componentManager.unregisterFactory(aObject.cid, aObject);
-}
-
-function cbError(aEvent) {
-  ok(false, "Error callback invoked " +
-            aEvent.target.error.name + " " + aEvent.target.error.message);
-  finish();
-}
-
-function unexpectedSuccess(aMsg) {
-  return function() {
-    ok(false, "Should not have succeeded: " + aMsg);
-    finish();
-  }
-}
--- a/dom/activities/tests/mochi/manifest.webapp
+++ b/dom/activities/tests/mochi/manifest.webapp
@@ -1,17 +1,6 @@
 {
   "name": "Random app",
   "activities": {
-    "import-app": { "blob": { "required": true } },
-    "bug1176712": [{
-      "filters": {
-        "type": "type1"
-      },
-      "href": "href1"
-    }, {
-      "filters": {
-        "type": "type2"
-      },
-      "href": "href2"
-    }]
+    "import-app": { "blob": { "required": true } }
   }
 }
--- a/dom/activities/tests/mochi/mochitest.ini
+++ b/dom/activities/tests/mochi/mochitest.ini
@@ -1,11 +1,9 @@
 [DEFAULT]
 skip-if = e10s
 support-files =
-  common.js
   system.webapp
   system.webapp^headers^
   manifest.webapp
   manifest.webapp^headers^
 
 [test_dev_mode_activity.html]
-[test_same_name_multiple_filters.html]
--- a/dom/activities/tests/mochi/test_dev_mode_activity.html
+++ b/dom/activities/tests/mochi/test_dev_mode_activity.html
@@ -4,18 +4,16 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id={1123846}
 -->
 <head>
   <title>Test for Bug {1123846}</title>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/chrome-harness.js"></script>
-  <script type="application/javascript"
-          src="http://test/chrome/dom/activities/tests/mochi/common.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
 </head>
 <body>
 
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={1123846}">Mozilla Bug {1123846}</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 
@@ -30,32 +28,48 @@ https://bugzilla.mozilla.org/show_bug.cg
   *
   * We test the following:
   * 1) No dev mode, no system app installed (failure).
   * 2) No dev mode, system app installed (failure).
   * 3) No dev mode, system app and other app installed (failure).
   * 4) Dev mode, system app and other app installed (success, only system app returned).
   */
 
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
+var gRootUrl = "http://test/chrome/dom/activities/tests/mochi/";
 var gGenerator = runTest();
 
 function go() {
   SpecialPowers.pushPermissions(
     [{ "type": "webapps-manage", "allow": 1, "context": document },
      { "type": "browser", "allow": 1, "context": document },
      { "type": "embed-apps", "allow": 1, "context": document }],
     function() {
       SpecialPowers.pushPrefEnv(
         {'set': [["dom.mozBrowserFramesEnabled", true],
                  ["dom.sysmsg.enabled", true],
                  ["dom.apps.developer_mode", false],
                  ["dom.activities.developer_mode_only", "import-app"]]},
         continueTest) });
 }
 
+function cbError(aEvent) {
+  ok(false, "Error callback invoked " +
+            aEvent.target.error.name + " " + aEvent.target.error.message);
+  finish();
+}
+
+function unexpectedSuccess(aMsg) {
+  return function() {
+    ok(false, "Should not have succeeded: " + aMsg);
+    finish();
+  }
+}
+
 SimpleTest.waitForExplicitFinish();
 
 var systemAppUrl = gRootUrl + "system.webapp";
 var otherAppUrl = gRootUrl + "manifest.webapp";
 
 function installApp(aUrl) {
   var request = navigator.mozApps.install(aUrl, { });
   request.onerror = cbError;
@@ -73,16 +87,38 @@ function installOtherApp() {
 
 function uninstall(aApp) {
   info("Uninstalling " + (aApp ? aApp.manifestURL : "NO APP!!"));
   var request = navigator.mozApps.mgmt.uninstall(aApp);
   request.onerror = cbError;
   request.onsuccess = continueTest;
 }
 
+function registerComponent(aObject, aDescription, aContract) {
+  var uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
+                        .getService(Ci.nsIUUIDGenerator);
+  var cid = uuidGenerator.generateUUID();
+
+  info("Registering " + cid);
+
+  var componentManager =
+    Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
+  componentManager.registerFactory(cid, aDescription, aContract, aObject);
+
+  // Keep the id on the object so we can unregister later.
+  aObject.cid = cid;
+}
+
+function unregisterComponent(aObject) {
+  info("Unregistering " + aObject.cid);
+  var componentManager =
+    Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
+  componentManager.unregisterFactory(aObject.cid, aObject);
+}
+
 var ActivityGlue = {
   // nsISupports implementation.
   QueryInterface: function(iid) {
     if (iid.equals(Ci.nsISupports) ||
         iid.equals(Ci.nsIFactory) ||
         iid.equals(Ci.nsIActivityUIGlue)) {
       return this;
     }
@@ -116,37 +152,32 @@ var SystemMessageGlue = {
 
   // nsIFactory implementation.
   createInstance: function(outer, iid) {
     return this.QueryInterface(iid);
   },
 
   // nsISystemMessageGlue implementation.
   openApp(pageURL, manifestURL, type, target, showApp, onlyShowApp, extra) {
-    // We should only try to open a page in the system app.
+    // We should only try to open a page in the sytem app.
     is(manifestURL, systemAppUrl, "Opening a page in the system app.");
   }
 };
 
 registerComponent(ActivityGlue,
                   "Activity Glue",
-                  "@mozilla.org/dom/activities/ui-glue;1",
-                  ACTIVITY_GLUE_CID);
+                  "@mozilla.org/dom/activities/ui-glue;1");
 
 registerComponent(SystemMessageGlue,
                   "System Message Glue",
-                  "@mozilla.org/dom/messages/system-message-glue;1",
-                  SYS_MSG_GLUE_CID);
+                  "@mozilla.org/dom/messages/system-message-glue;1");
 
 function finish() {
   unregisterComponent(ActivityGlue);
   unregisterComponent(SystemMessageGlue);
-  obsService.removeObserver(continueTest, "new-activity-registered-success");
-  obsService.removeObserver(continueTest, "new-activity-registered-failure");
-
   SimpleTest.finish();
 }
 
 function continueTest() {
   try {
     gGenerator.next();
   } catch (e if e instanceof StopIteration) {
     finish();
deleted file mode 100644
--- a/dom/activities/tests/mochi/test_same_name_multiple_filters.html
+++ /dev/null
@@ -1,222 +0,0 @@
-<!DOCTYPE html>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id={1176712}
--->
-<head>
-  <title>Test for Bug {1176712}</title>
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript"
-          src="chrome://mochikit/content/chrome-harness.js"></script>
-  <script type="application/javascript"
-          src="http://test/chrome/dom/activities/tests/mochi/common.js"></script>
-  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
-</head>
-<body>
-
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={1176712}">Mozilla Bug {1176712}</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-
-var gGenerator = runTest();
-
-function go() {
-  SpecialPowers.pushPermissions(
-    [{ "type": "webapps-manage", "allow": 1, "context": document },
-     { "type": "browser", "allow": 1, "context": document },
-     { "type": "embed-apps", "allow": 1, "context": document }],
-    function() {
-      SpecialPowers.pushPrefEnv(
-        {'set': [["dom.mozBrowserFramesEnabled", true],
-                 ["dom.sysmsg.enabled", true]]},
-        continueTest) });
-}
-
-SimpleTest.waitForExplicitFinish();
-
-function installApp(aUrl) {
-  var request = navigator.mozApps.install(aUrl, { });
-  request.onerror = cbError;
-  request.onsuccess = continueTest;
-  return request;
-}
-
-function uninstall(aApp) {
-  info("Uninstalling " + (aApp ? aApp.manifestURL : "NO APP!!"));
-  var request = navigator.mozApps.mgmt.uninstall(aApp);
-  request.onerror = cbError;
-  request.onsuccess = continueTest;
-}
-
-var ActivityGlue = {
-  // nsISupports implementation.
-  QueryInterface: function(iid) {
-    if (iid.equals(Ci.nsISupports) ||
-        iid.equals(Ci.nsIFactory) ||
-        iid.equals(Ci.nsIActivityUIGlue)) {
-      return this;
-    }
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-  // nsIFactory implementation.
-  createInstance: function(outer, iid) {
-    return this.QueryInterface(iid);
-  },
-
-  // nsIActivityUIGlue implementation.
-  chooseActivity: function(aOptions, aActivities, aCallback) {
-    aCallback.handleEvent(Ci.nsIActivityUIGlueCallback.WEBAPPS_ACTIVITY,
-                          aActivities.length == 1 ? 0 : -1);
-  }
-};
-
-var SystemMessageGlue = {
-  // nsISupports implementation.
-  QueryInterface: function(iid) {
-    if (iid.equals(Ci.nsISupports) ||
-        iid.equals(Ci.nsIFactory) ||
-        iid.equals(Ci.nsISystemMessageGlue)) {
-      return this;
-    }
-
-    throw Cr.NS_ERROR_NO_INTERFACE;
-  },
-
-  // nsIFactory implementation.
-  createInstance: function(outer, iid) {
-    return this.QueryInterface(iid);
-  },
-
-  // nsISystemMessageGlue implementation.
-  openApp(pageURL, manifestURL, type, target, showApp, onlyShowApp, extra) {
-  }
-};
-
-registerComponent(ActivityGlue,
-                  "Activity Glue",
-                  "@mozilla.org/dom/activities/ui-glue;1",
-                  ACTIVITY_GLUE_CID);
-
-registerComponent(SystemMessageGlue,
-                  "System Message Glue",
-                  "@mozilla.org/dom/messages/system-message-glue;1",
-                  SYS_MSG_GLUE_CID);
-
-function finish() {
-  unregisterComponent(ActivityGlue);
-  unregisterComponent(SystemMessageGlue);
-  SimpleTest.finish();
-}
-
-function continueTest() {
-  try {
-    gGenerator.next();
-  } catch (e if e instanceof StopIteration) {
-    finish();
-  }
-}
-
-function runTest() {
-  SpecialPowers.setAllAppsLaunchable(true);
-
-  SpecialPowers.autoConfirmAppInstall(continueTest);
-  yield undefined;
-
-  SpecialPowers.autoConfirmAppUninstall(continueTest);
-  yield undefined;
-
-  // Check how many apps we are starting with.
-  var request = navigator.mozApps.mgmt.getAll();
-  request.onerror = cbError;
-  request.onsuccess = continueTest;
-  yield undefined;
-  var initialAppsCount = request.result.length;
-  info("Starting with " + initialAppsCount + " apps installed.");
-
-  // Before app installed
-
-  var activity = new MozActivity({
-    name: "bug1176712",
-    data: {
-      type: "type1"
-    }
-  });
-  activity.onsuccess = unexpectedSuccess("Shouldn't launch unregistered activity");
-  activity.onerror = () => {
-    ok(activity.error.name == "NO_PROVIDER", "Expected NO_PROVIDER");
-    continueTest();
-  };
-  yield undefined;
-
-  var activity = new MozActivity({
-    name: "bug1176712",
-    data: {
-      type: "type2"
-    }
-  });
-  activity.onsuccess = unexpectedSuccess("Shouldn't launch unregistered activity");
-  activity.onerror = () => {
-    ok(activity.error.name == "NO_PROVIDER", "Expected NO_PROVIDER");
-    continueTest();
-  };
-  yield undefined;
-
-  var request = installApp(gRootUrl + "manifest.webapp");
-  yield undefined;
-  var app = request.result;
-  ok(app, "App installed");
-
-  // After app installed
-
-  var activity = new MozActivity({
-    name: "bug1176712",
-    data: {
-      type: "type1"
-    }
-  });
-  activity.onsuccess = function() {
-    ok(true, "Activity launch succeed");
-    continueTest();
-  }
-  activity.onerror = cbError;
-  yield undefined;
-
-  var activity = new MozActivity({
-    name: "bug1176712",
-    data: {
-      type: "type2"
-    }
-  });
-  activity.onsuccess = function() {
-    ok(true, "Activity launch succeed");
-    continueTest();
-  }
-  activity.onerror = cbError;
-  yield undefined;
-
-  // Cleanup
-  uninstall(app);
-  yield undefined;
-
-  // Check that we restored the app registry.
-  request = navigator.mozApps.mgmt.getAll();
-  request.onerror = cbError;
-  request.onsuccess = continueTest;
-  yield undefined;
-
-  is(request.result.length, initialAppsCount, "All apps are uninstalled.");
-}
-
-addLoadEvent(go);
-
-</script>
-</pre>
-</body>
-</html>
--- a/dom/apps/Webapps.jsm
+++ b/dom/apps/Webapps.jsm
@@ -985,80 +985,69 @@ this.DOMApplicationRegistry = {
     for (let entryPoint in aManifest.entry_points) {
       this._registerInterAppConnectionsForEntryPoint(aManifest, aApp,
                                                      entryPoint);
     }
   },
 
   // |aEntryPoint| is either the entry_point name or the null in which case we
   // use the root of the manifest.
-  _createActivitiesToRegister: function(aManifest, aApp, aEntryPoint,
-                                        aRunUpdate, aUninstall) {
+  _createActivitiesToRegister: function(aManifest, aApp, aEntryPoint, aRunUpdate) {
     let activitiesToRegister = [];
     let root = aManifest;
     if (aEntryPoint && aManifest.entry_points[aEntryPoint]) {
       root = aManifest.entry_points[aEntryPoint];
     }
 
     if (!root || !root.activities) {
       return activitiesToRegister;
     }
 
     let manifest = new ManifestHelper(aManifest, aApp.origin, aApp.manifestURL);
     for (let activity in root.activities) {
-      let entry = root.activities[activity];
-      if (!Array.isArray(entry)) {
-        entry = [entry];
+      let description = root.activities[activity];
+      let href = description.href;
+      if (!href) {
+        href = manifest.launch_path;
+      }
+
+      try {
+        href = manifest.resolveURL(href);
+      } catch (e) {
+        debug("Activity href (" + href + ") is invalid, skipping. " +
+              "Error is: " + e);
+        continue;
+      }
+
+      // Make a copy of the description object since we don't want to modify
+      // the manifest itself, but need to register with a resolved URI.
+      let newDesc = {};
+      for (let prop in description) {
+        newDesc[prop] = description[prop];
       }
-      for (let i = 0; i < entry.length; i++) {
-        let description = entry[i];
-        let href = description.href;
-        if (!href) {
-          href = manifest.launch_path;
-        }
-
-        try {
-          href = manifest.resolveURL(href);
-        } catch (e) {
-          debug("Activity href (" + href + ") is invalid, skipping. " +
-                "Error is: " + e);
-          continue;
-        }
-
-        // Make a copy of the description object since we don't want to modify
-        // the manifest itself, but need to register with a resolved URI.
-        let newDesc = {};
-        for (let prop in description) {
-          newDesc[prop] = description[prop];
-        }
-        newDesc.href = href;
-
-        debug('_createActivitiesToRegister: ' + aApp.manifestURL + ', activity ' +
-            activity + ', description.href is ' + newDesc.href);
-
-        if (aRunUpdate || aUninstall) {
-          activitiesToRegister.push({ "manifest": aApp.manifestURL,
-                                      "name": activity,
-                                      "icon": manifest.iconURLForSize(128),
-                                      "description": newDesc });
-        }
-
-        if (aUninstall) {
-          continue;
-        }
-
-        let launchPathURI = Services.io.newURI(href, null, null);
-        let manifestURI = Services.io.newURI(aApp.manifestURL, null, null);
-
-        if (SystemMessagePermissionsChecker
-              .isSystemMessagePermittedToRegister("activity",
-                                                  aApp.manifestURL,
-                                                  aManifest)) {
-          msgmgr.registerPage("activity", launchPathURI, manifestURI);
-        }
+      newDesc.href = href;
+
+      debug('_createActivitiesToRegister: ' + aApp.manifestURL + ', activity ' +
+          activity + ', description.href is ' + newDesc.href);
+
+      if (aRunUpdate) {
+        activitiesToRegister.push({ "manifest": aApp.manifestURL,
+                                    "name": activity,
+                                    "icon": manifest.iconURLForSize(128),
+                                    "description": newDesc });
+      }
+
+      let launchPathURI = Services.io.newURI(href, null, null);
+      let manifestURI = Services.io.newURI(aApp.manifestURL, null, null);
+
+      if (SystemMessagePermissionsChecker
+            .isSystemMessagePermittedToRegister("activity",
+                                                aApp.manifestURL,
+                                                aManifest)) {
+        msgmgr.registerPage("activity", launchPathURI, manifestURI);
       }
     }
     return activitiesToRegister;
   },
 
   // |aAppsToRegister| contains an array of apps to be registered, where
   // each element is an object in the format of {manifest: foo, app: bar}.
   _registerActivitiesForApps: function(aAppsToRegister, aRunUpdate) {
@@ -1094,34 +1083,56 @@ this.DOMApplicationRegistry = {
   },
 
   // Better to directly use |_registerActivitiesForApps()| if we have
   // multiple apps to be registered for activities.
   _registerActivities: function(aManifest, aApp, aRunUpdate) {
     this._registerActivitiesForApps([{ manifest: aManifest, app: aApp }], aRunUpdate);
   },
 
+  // |aEntryPoint| is either the entry_point name or the null in which case we
+  // use the root of the manifest.
+  _createActivitiesToUnregister: function(aManifest, aApp, aEntryPoint) {
+    let activitiesToUnregister = [];
+    let root = aManifest;
+    if (aEntryPoint && aManifest.entry_points[aEntryPoint]) {
+      root = aManifest.entry_points[aEntryPoint];
+    }
+
+    if (!root.activities) {
+      return activitiesToUnregister;
+    }
+
+    for (let activity in root.activities) {
+      let description = root.activities[activity];
+      activitiesToUnregister.push({ "manifest": aApp.manifestURL,
+                                    "name": activity,
+                                    "description": description });
+    }
+    return activitiesToUnregister;
+  },
+
   // |aAppsToUnregister| contains an array of apps to be unregistered, where
   // each element is an object in the format of {manifest: foo, app: bar}.
   _unregisterActivitiesForApps: function(aAppsToUnregister) {
     // Collect the activities to be unregistered for root and entry_points.
     let activitiesToUnregister = [];
     aAppsToUnregister.forEach(function (aApp) {
       let manifest = aApp.manifest;
       let app = aApp.app;
       activitiesToUnregister.push.apply(activitiesToUnregister,
-        this._createActivitiesToRegister(manifest, app, null, false, true));
+        this._createActivitiesToUnregister(manifest, app, null));
 
       if (!manifest.entry_points) {
         return;
       }
 
       for (let entryPoint in manifest.entry_points) {
         activitiesToUnregister.push.apply(activitiesToUnregister,
-          this._createActivitiesToRegister(manifest, app, entryPoint, false, true));
+          this._createActivitiesToUnregister(manifest, app, entryPoint));
       }
     }, this);
 
     // Send the array carrying all the activities to be unregistered.
     cpmm.sendAsyncMessage("Activities:Unregister", activitiesToUnregister);
   },
 
   // Better to directly use |_unregisterActivitiesForApps()| if we have