Backing out f085bbca2ee9 (bug 609043) since it triggered perma-orange in Android b-c tests
authorDaniel Holbert <dholbert@cs.stanford.edu>
Mon, 15 Aug 2011 20:59:13 -0700
changeset 75312 37dedb70a68adaf8d74fb2c2e58377ffb89e0449
parent 75311 51c50cf19742ffaf2c014f404739c407857f9ba2
child 75322 630e28e90986596a4855f8f67cd8072f2c1bdf6b
child 75353 e5c1fbc8df7ed2ebea6a8763b47f73eb7d776112
push id21004
push userdholbert@mozilla.com
push dateTue, 16 Aug 2011 04:03:38 +0000
treeherdermozilla-central@37dedb70a68a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs609043
milestone8.0a1
first release with
nightly linux32
37dedb70a68a / 8.0a1 / 20110816030741 / files
nightly linux64
37dedb70a68a / 8.0a1 / 20110816030741 / files
nightly mac
37dedb70a68a / 8.0a1 / 20110816030741 / files
nightly win32
37dedb70a68a / 8.0a1 / 20110816030741 / files
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
Backing out f085bbca2ee9 (bug 609043) since it triggered perma-orange in Android b-c tests
mobile/chrome/content/browser-ui.js
mobile/chrome/content/common-ui.js
mobile/chrome/content/content.js
mobile/chrome/content/injected.js
mobile/chrome/jar.mn
mobile/components/Makefile.in
mobile/components/MobileComponents.manifest
mobile/components/WebappsSupport.idl
mobile/components/WebappsSupport.js
mobile/installer/package-manifest.in
mobile/modules/Makefile.in
mobile/modules/openWebapps.jsm
--- a/mobile/chrome/content/browser-ui.js
+++ b/mobile/chrome/content/browser-ui.js
@@ -545,17 +545,16 @@ var BrowserUI = {
       // Init helpers
       BadgeHandlers.register(BrowserUI._edit.popup);
       FormHelperUI.init();
       FindHelperUI.init();
       PageActions.init();
       FullScreenVideo.init();
       NewTabPopup.init();
       CharsetMenu.init();
-      WebappsUI.init();
 
       // If some add-ons were disabled during during an application update, alert user
       let addonIDs = AddonManager.getStartupChanges("disabled");
       if (addonIDs.length > 0) {
         let disabledStrings = Strings.browser.GetStringFromName("alertAddonsDisabled");
         let label = PluralForm.get(addonIDs.length, disabledStrings).replace("#1", addonIDs.length);
         let image = "chrome://browser/skin/images/alert-addons-30.png";
 
--- a/mobile/chrome/content/common-ui.js
+++ b/mobile/chrome/content/common-ui.js
@@ -1672,168 +1672,69 @@ var CharsetMenu = {
     let history = Cc["@mozilla.org/browser/nav-history-service;1"].getService(Ci.nsINavHistoryService);
     history.setCharsetForURI(browser.documentURI, aCharset);
   }
 
 };
 
 var WebappsUI = {
   _dialog: null,
+  _manifest: null,
   _perms: [],
-  _openwebapps: null,
-  _application: null,
-
-  init: function() {
-    Cu.import("resource:///modules/openWebapps.jsm");
-    messageManager.addMessageListener("OpenWebapps:Install", this);
-    messageManager.addMessageListener("OpenWebapps:GetInstalledBy", this);
-    messageManager.addMessageListener("OpenWebapps:AmInstalled", this);
-    messageManager.addMessageListener("OpenWebapps:MgmtLaunch", this);
-    messageManager.addMessageListener("OpenWebapps:MgmtList", this);
-    messageManager.addMessageListener("OpenWebapps:MgmtUninstall", this);
-  },
-
-  // converts a manifest to an application as expected by openwebapps.install()
-  convertManifest: function(aData) {
-    let app = {
-      manifest : JSON.parse(aData.manifest),
-      installData : aData.installData,
-      storeURI : aData.storeURI,
-      manifestURI : aData.manifestURIs,
-      capabilities : [],
-      callbackID : aData.callbackID
-    }
-
-    let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry).QueryInterface(Ci.nsIToolkitChromeRegistry);
-    let locale = chrome.getSelectedLocale("browser");
-
-    let localeRoot;
-    if (app.manifest.locales)
-      localeRoot = app.manifest.locales[locale];
-
-    if (!localeRoot)
-      localeRoot = app.manifest;
-
-    let baseURI = Services.io.newURI(aData.manifestURI, null, null);
-    app.title = localeRoot.name || app.manifest.name;
-
-    // choose the larger icon
-    let max = 0;
-    let icon;
-    for (let size in app.manifest.icons) {
-      let iSize = parseInt(size);
-      if (iSize > max) {
-        icon = baseURI.resolve(app.manifest.icons[size]);
-        max = iSize;
-      }
-    }
-    if (icon)
-      app.iconURI = icon;
-
-    let root = baseURI.resolve("/").toString();
-    app.appURI = app.manifest.launch_path ? baseURI.resolve(app.manifest.launch_path) : root.substring(0, root.length - 1);
-
-    return app;
-  },
-
-  receiveMessage: function(aMessage) {
-    let browser = aMessage.target;
-    switch(aMessage.name) {
-      case "OpenWebapps:Install":
-        WebappsUI._openwebapps = browser;
-        WebappsUI.show(WebappsUI.convertManifest(aMessage.json));
-        break;
-      case "OpenWebapps:GetInstalledBy":
-        let apps = OpenWebapps.getInstalledBy(aMessage.json.storeURI);
-        browser.messageManager.sendAsyncMessage("OpenWebapps:GetInstalledBy:Return",
-            { apps: apps, callbackID: aMessage.json.callbackID });
-        break;
-      case "OpenWebapps:AmInstalled":
-        let app = OpenWebapps.amInstalled(aMessage.json.appURI);
-        browser.messageManager.sendAsyncMessage("OpenWebapps:AmInstalled:Return",
-            { installed: app != null, app: app, callbackID: aMessage.json.callbackID });
-        break;
-      case "OpenWebapps:MgmtList":
-        let list = OpenWebapps.mgmtList();
-        browser.messageManager.sendAsyncMessage("OpenWebapps:MgmtList:Return",
-            { ok: true, apps: list, callbackID: aMessage.json.callbackID });
-        break;
-      case "OpenWebapps:MgmtLaunch":
-        let res = OpenWebapps.mgmtLaunch(aMessage.json.origin);
-        browser.messageManager.sendAsyncMessage("OpenWebapps:MgmtLaunch:Return",
-            { ok: res, callbackID: aMessage.json.callbackID });
-        break;
-      case "OpenWebapps:MgmtUninstall":
-        let uninstalled = OpenWebapps.mgmtUninstall(aMessage.json.origin);
-        browser.messageManager.sendAsyncMessage("OpenWebapps:MgmtUninstall:Return",
-            { ok: uninstalled, callbackID: aMessage.json.callbackID });
-        break;
-    }
-  },
-
+  
   checkBox: function(aEvent) {
     let elem = aEvent.originalTarget;
     let perm = elem.getAttribute("perm");
-    if (this._application.capabilities && this._application.capabilities.indexOf(perm) != -1) {
+    if (this._manifest.capabilities && this._manifest.capabilities.indexOf(perm) != -1) {
       if (elem.checked) {
         elem.classList.remove("webapps-noperm");
         elem.classList.add("webapps-perm");
       } else {
         elem.classList.remove("webapps-perm");
         elem.classList.add("webapps-noperm");
       }
     }
   },
 
-  show: function show(aApplication) {
-    if (!aApplication) {
-      this._openwebapps = null;
-
+  show: function show(aManifest) {
+    if (!aManifest) {
       // Try every way to get an icon
       let browser = Browser.selectedBrowser;
       let icon = browser.appIcon.href;
       if (!icon)
         icon = browser.mIconURL;
       if (!icon) 
         icon = gFaviconService.getFaviconImageForPage(browser.currentURI).spec;
 
-      // Create a simple application object
-      aApplication = {
-        appURI: browser.currentURI.spec,
-        storeURI: browser.currentURI.spec,
-        title: browser.contentTitle,
-        iconURI: icon,
+      // Create a simple manifest
+      aManifest = {
+        uri: browser.currentURI.spec,
+        name: browser.contentTitle,
+        icon: icon,
         capabilities: [],
-        manifest: {
-          name: browser.contentTitle,
-          launch_path: browser.currentURI.spec,
-          icons: {
-            "64": icon
-          }
-        }
-      }
+      };
     }
 
-    this._application = aApplication;
+    this._manifest = aManifest;
     this._dialog = importDialog(window, "chrome://browser/content/webapps.xul", null);
 
-    if (aApplication.title)
-      document.getElementById("webapps-title").value = aApplication.title;
-    if (aApplication.iconURI)
-      document.getElementById("webapps-icon").src = aApplication.iconURI;  
+    if (aManifest.name)
+      document.getElementById("webapps-title").value = aManifest.name;
+    if (aManifest.icon)
+      document.getElementById("webapps-icon").src = aManifest.icon;  
 
-    let uri = Services.io.newURI(aApplication.appURI, null, null);
+    let uri = Services.io.newURI(aManifest.uri, null, null);
 
     let perms = [["offline", "offline-app"], ["geoloc", "geo"], ["notifications", "desktop-notification"]];
     let self = this;
     perms.forEach(function(tuple) {
       let elem = document.getElementById("webapps-" + tuple[0] + "-checkbox");
       let currentPerm = Services.perms.testExactPermission(uri, tuple[1]);
       self._perms[tuple[1]] = (currentPerm == Ci.nsIPermissionManager.ALLOW_ACTION);
-      if ((aApplication.capabilities && (aApplication.capabilities.indexOf(tuple[1]) != -1)) || (currentPerm == Ci.nsIPermissionManager.ALLOW_ACTION))
+      if ((aManifest.capabilities && (aManifest.capabilities.indexOf(tuple[1]) != -1)) || (currentPerm == Ci.nsIPermissionManager.ALLOW_ACTION))
         elem.checked = true;
       else
         elem.checked = (currentPerm == Ci.nsIPermissionManager.ALLOW_ACTION);
       elem.classList.remove("webapps-noperm");
       elem.classList.add("webapps-perm");
     });
 
     BrowserUI.pushPopup(this, this._dialog);
@@ -1841,86 +1742,72 @@ var WebappsUI = {
     // Force a modal dialog
     this._dialog.waitForClose();
   },
 
   hide: function hide() {
     this._dialog.close();
     this._dialog = null;
     BrowserUI.popPopup(this);
-
-    if (this._openwebapps) {
-      let browser = this._openwebapps;
-      browser.messageManager.sendAsyncMessage("OpenWebapps:InstallAborted", { callbackID: this._application.callbackID });
-    }
-
-    this._openwebapps = null;
   },
 
   _updatePermission: function updatePermission(aId, aPerm) {
     try {
-      let uri = Services.io.newURI(this._application.appURI, null, null);
+      let uri = Services.io.newURI(this._manifest.uri, null, null);
       let currentState = document.getElementById(aId).checked;
       if (currentState != this._perms[aPerm])
         Services.perms.add(uri, aPerm, currentState ? Ci.nsIPermissionManager.ALLOW_ACTION : Ci.nsIPermissionManager.DENY_ACTION);
     } catch(e) {
       Cu.reportError(e);
     }
   },
   
   launch: function launch() {
     let title = document.getElementById("webapps-title").value;
     if (!title)
       return;
 
-    this._application.title = title;
-
     this._updatePermission("webapps-offline-checkbox", "offline-app");
     this._updatePermission("webapps-geoloc-checkbox", "geo");
     this._updatePermission("webapps-notifications-checkbox", "desktop-notification");
 
-    let browser = this._openwebapps;
-    this._openwebapps = null;
     this.hide();
-    this.install();
-
-    if (browser != null)
-      browser.messageManager.sendAsyncMessage("OpenWebapps:InstallDone", { callbackID: this._application.callbackID });
+    this.install(this._manifest.uri, title, this._manifest.icon);
   },
   
   updateWebappsInstall: function updateWebappsInstall(aNode) {
     if (document.getElementById("main-window").hasAttribute("webapp"))
       return false;
 
     let browser = Browser.selectedBrowser;
 
-    return !(OpenWebapps.amInstalled(browser.currentURI.spec));
+    let webapp = Cc["@mozilla.org/webapps/support;1"].getService(Ci.nsIWebappsSupport);
+    return !(webapp && webapp.isApplicationInstalled(browser.currentURI.spec));
   },
   
-  install: function(aIconURI) {
+  install: function(aURI, aTitle, aIcon) {
     const kIconSize = 64;
     
     let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
     canvas.setAttribute("style", "display: none");
 
     let self = this;
     let image = new Image();
     image.onload = function() {
       canvas.width = canvas.height = kIconSize; // clears the canvas
       let ctx = canvas.getContext("2d");
       ctx.drawImage(image, 0, 0, kIconSize, kIconSize);
-      self._application.iconData = canvas.toDataURL("image/png", "");
+      let data = canvas.toDataURL("image/png", "");
       canvas = null;
       try {
-        OpenWebapps.install(self._application);
+        let webapp = Cc["@mozilla.org/webapps/support;1"].getService(Ci.nsIWebappsSupport);
+        webapp.installApplication(aTitle, aURI, aIcon, data);
       } catch(e) {
         Cu.reportError(e);
       }
     }
-
     image.onerror = function() {
       // can't load the icon (bad URI) : fallback to the default one from chrome
-      self.install("chrome://browser/skin/images/favicon-default-30.png");
+      self.install(aURI, aTitle, "chrome://browser/skin/images/favicon-default-30.png");
     }
-
-    image.src = aIconURI || this._application.iconURI;
+    image.src = aIcon;
   }
 };
--- a/mobile/chrome/content/content.js
+++ b/mobile/chrome/content/content.js
@@ -1518,179 +1518,8 @@ var SelectionHandler = {
     cache.rect.bottom += aOffset.y;
     cache.offset = aOffset;
 
     return cache;
   }
 };
 
 SelectionHandler.init();
-
-// Implementation of https://developer.mozilla.org/en/OpenWebApps/The_JavaScript_API
-let OpenWebapps = {
-  _callbacks: [],
-
-  /** from https://developer.mozilla.org/en/OpenWebApps/The_Manifest
-   * only the name property is mandatory
-   */
-  checkManifest: function(aManifest) {
-    return ("name" in aManifest);
-  },
-  
-  getCallbackId: function(aCallback) {
-    let id = "id" + Math.random();
-    this._callbacks[id] = aCallback;
-    return id;
-  },
-  
-  getCallback: function(aId) {
-    return this._callbacks[aId];
-  },
-
-  removeCallback: function(aId) {
-    delete this._callbacks[aId];
-  },
-
-  install: function(aStoreURI, aManifestURI, aInstallData, aSuccessCallback, aErrorCallback) {
-    let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
-    xhr.open("GET", aManifestURI, true);
-
-    xhr.onload = function() {
-      if (xhr.status == 200) {
-        try {
-          let manifest = JSON.parse(xhr.responseText);
-          if (!OpenWebapps.checkManifest(manifest)) {
-            if (aErrorCallback)
-              aErrorCallback({ code: "invalidManifest", message: "Invalid manifest" });
-          } else {
-            sendAsyncMessage("OpenWebapps:Install", { storeURI: aStoreURI.href, manifestURI: aManifestURI, manifest: xhr.responseText,
-                             installData: aInstallData, callbackID:  OpenWebapps.getCallbackId({ success: aSuccessCallback, error: aErrorCallback }) });
-          }
-        } catch(e) {
-          if (aErrorCallback)
-            aErrorCallback({ code: "manifestParseError", message: "Unable to parse the manifest" });
-        }
-      }
-      else if (aErrorCallback) {
-        aErrorCallback({ code: "networkError", message: "Unable to retrieve manifest" });
-      }      
-    }
-
-    xhr.onerror = function() {
-      if (aErrorCallback)
-        aErrorCallback({ code: "networkError", message: "Unable to retrieve manifest" });
-    }
-
-    xhr.send(null);
-  },
-  
-  amInstalled: function(aAppURI, aSuccessCallback, aErrorCallback) {
-    sendAsyncMessage("OpenWebapps:AmInstalled", { appURI: aAppURI, callbackID:  OpenWebapps.getCallbackId({ success: aSuccessCallback, error: aErrorCallback }) });
-  },
-  
-  getInstalledBy: function(aStoreURI, aSuccessCallback, aErrorCallback) {
-    sendAsyncMessage("OpenWebapps:GetInstalledBy", { storeURI: aStoreURI.href, callbackID:  OpenWebapps.getCallbackId({ success: aSuccessCallback, error: aErrorCallback }) });
-  },
-  
-  mgmtLaunch: function(aOrigin, aSuccessCallback, aErrorCallback) {
-    sendAsyncMessage("OpenWebapps:MgmtLaunch", { origin: aOrigin, callbackID:  OpenWebapps.getCallbackId({ success: aSuccessCallback, error: aErrorCallback }) });
-  },
-  
-  mgmtList: function(aSuccessCallback, aErrorCallback) {
-    sendAsyncMessage("OpenWebapps:MgmtList", { callbackID:  OpenWebapps.getCallbackId({ success: aSuccessCallback, error: aErrorCallback }) });
-  },
-  
-  mgmtUninstall: function(aOrigin, aSuccessCallback, aErrorCallback) {
-    sendAsyncMessage("OpenWebapps:MgmtUninstall", { origin: aOrigin, callbackID:  OpenWebapps.getCallbackId({ success: aSuccessCallback, error: aErrorCallback }) });
-  },
-  
-  receiveMessage: function(aMessage) {
-    let msg = aMessage.json;
-    let callbacks = OpenWebapps.getCallback(msg.callbackID);
-    switch(aMessage.name) {
-      case "OpenWebapps:InstallAborted" :
-        if (callbacks.error)
-          callbacks.error({ code: "denied", message: "User denied installation" });
-        break;
-      case "OpenWebapps:InstallDone" :
-        callbacks.success();
-        break;
-      case "OpenWebapps:GetInstalledBy:Return":
-        callbacks.success(msg.apps);
-        break;
-      case "OpenWebapps:AmInstalled:Return":
-        callbacks.success(msg.installed ? msg.app : null);
-        break;
-      case "OpenWebapps:MgmtLaunch:Return":
-        if (msg.ok && callbacks.success)
-          callbacks.success();
-        else if (!msg.ok && callbacks.error)
-          callbacks.error({ code: "noSuchApp", message: "Unable to launch application"});
-        break;
-      case "OpenWebapps:MgmtList:Return":
-        if (msg.ok && callbacks.success)
-          callbacks.success(msg.apps);
-        else if (!msg.ok && callbacks.error)
-          callbacks.error({ code: "noAppList", message: "Unable to get application list"});
-        break;
-      case "OpenWebapps:MgmtUninstall:Return":
-        if (msg.ok && callbacks.success)
-          callbacks.success();
-        else if (!msg.ok && callbacks.error)
-          callbacks.error({ code: "noSuchApp", message: "Unable to uninstall application"});
-        break;
-    }
-    OpenWebapps.removeCallback(msg.callbackID);
-  },
-  
-  init: function() {
-    addMessageListener("OpenWebapps:InstallDone", this);
-    addMessageListener("OpenWebapps:InstallAborted", this);
-    addMessageListener("OpenWebapps:GetInstalledBy:Return", this);
-    addMessageListener("OpenWebapps:AmInstalled:Return", this);
-    addMessageListener("OpenWebapps:MgmtLaunch:Return", this);
-    addMessageListener("OpenWebapps:MgmtList:Return", this);
-    addMessageListener("OpenWebapps:MgmtUninstall:Return", this);
-    Services.obs.addObserver(this, "content-document-global-created", false);
-  },
-  
-  getInjected: function() {
-    let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
-    xhr.open("GET", "chrome://browser/content/injected.js", false);
-    xhr.overrideMimeType("text/plain");
-    xhr.send(null);
-    return xhr.responseText;
-  },
-
-  observe: function(subject, topic, data) {
-    let sandbox = new Components.utils.Sandbox(Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal));
-    sandbox.window = subject.wrappedJSObject;
-
-    sandbox.importFunction(function(aStoreURI, aManifestURI, aInstallData, aSuccessCallback, aErrorCallback) {
-        OpenWebapps.install(aStoreURI, aManifestURI, aInstallData, aSuccessCallback, aErrorCallback);
-        }, "OpenWebapps_install");
-    
-    sandbox.importFunction(function(aAppURI, aSuccessCallback, aErrorCallback) {
-        OpenWebapps.amInstalled(aAppURI, aSuccessCallback, aErrorCallback);
-        }, "OpenWebapps_amInstalled");
-    
-    sandbox.importFunction(function(aStoreURI, aSuccessCallback, aErrorCallback) {
-        OpenWebapps.getInstalledBy(aStoreURI, aSuccessCallback, aErrorCallback);
-        }, "OpenWebapps_getInstalledBy");
-    
-    sandbox.importFunction(function(aOrigin, aSuccessCallback, aErrorCallback) {
-        OpenWebapps.mgmtLaunch(aOrigin, aSuccessCallback, aErrorCallback);
-        }, "OpenWebappsMgmt_launch");
-    
-    sandbox.importFunction(function(aSuccessCallback, aErrorCallback) {
-        OpenWebapps.mgmtList(aSuccessCallback, aErrorCallback);
-        }, "OpenWebappsMgmt_list");
-    
-    sandbox.importFunction(function(aOrigin, aSuccessCallback, aErrorCallback) {
-        OpenWebapps.mgmtUninstall(aOrigin, aSuccessCallback, aErrorCallback);
-        }, "OpenWebappsMgmt_uninstall");
-
-    let toInject = OpenWebapps.getInjected();
-    Cu.evalInSandbox(toInject, sandbox, "1.8", "chrome://browser/content/injected.js", 1);
-  }
-};
-
-OpenWebapps.init();
deleted file mode 100644
--- a/mobile/chrome/content/injected.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Mobile Browser.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Fabrice Desré <fabrice@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/* Expose API under window.navigator.apps */
-if (window && window.navigator) {
-  window.navigator.mozApps = {
-    install: function(aParam) {
-      return OpenWebapps_install(window.location, aParam.url, aParam.install_data, aParam.onsuccess, aParam.onerror);
-    },
-    
-    amInstalled: function(aSuccessCallback, aErrorCallback) {
-      return OpenWebapps_amInstalled(window.location, aSuccessCallback, aErrorCallback);
-    },
-    
-    getInstalledBy: function(aSuccessCallback, aErrorCallback) {
-      return OpenWebapps_getInstalledBy(window.location, aSuccessCallback, aErrorCallback);
-    }
-  }
-  
-  window.navigator.mozApps.mgmt = {
-    launch: function(aOrigin, aSuccessCallback, aErrorCallback) {
-      return OpenWebappsMgmt_launch(aOrigin, aSuccessCallback, aErrorCallback);
-    },
-    
-    list: function(aSuccessCallback, aErrorCallback) {
-      return OpenWebappsMgmt_list(aSuccessCallback, aErrorCallback);
-    },
-    
-    uninstall: function(aOrigin, aSuccessCallback, aErrorCallback) {
-      return OpenWebappsMgmt_uninstall(aOrigin, aSuccessCallback, aErrorCallback);
-    }
-  }
-}
--- a/mobile/chrome/jar.mn
+++ b/mobile/chrome/jar.mn
@@ -71,12 +71,11 @@ chrome.jar:
   content/AnimatedZoom.js              (content/AnimatedZoom.js)
 #ifdef MOZ_SERVICES_SYNC
   content/sync.js                      (content/sync.js)
 #endif
   content/LoginManagerChild.js         (content/LoginManagerChild.js)
   content/fullscreen-video.js          (content/fullscreen-video.js)
   content/fullscreen-video.xhtml       (content/fullscreen-video.xhtml)
   content/netError.xhtml               (content/netError.xhtml)
-  content/injected.js                  (content/injected.js)
 
 % override chrome://global/content/config.xul chrome://browser/content/config.xul
 % override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
--- a/mobile/components/Makefile.in
+++ b/mobile/components/Makefile.in
@@ -44,16 +44,17 @@ VPATH      = @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = MobileComponents
 XPIDL_MODULE = MobileComponents
 
 XPIDLSRCS = \
         SessionStore.idl \
         LoginManagerPrompter.idl \
+        WebappsSupport.idl \
         $(NULL)
 
 EXTRA_PP_COMPONENTS = \
         MobileComponents.manifest \
         AboutRedirector.js \
         BrowserCLH.js \
         DirectoryProvider.js\
         HelperAppDialog.js \
@@ -70,16 +71,17 @@ EXTRA_COMPONENTS = \
         PromptService.js \
         ContentDispatchChooser.js \
         AutoCompleteCache.js \
         AddonUpdateService.js \
         FormAutoComplete.js \
         LoginManager.js \
         LoginManagerPrompter.js \
         BlocklistPrompt.js \
+        WebappsSupport.js \
         $(NULL)
 
 ifdef MOZ_SAFE_BROWSING
 EXTRA_COMPONENTS += SafeBrowsing.js
 endif
 
 ifdef MOZ_UPDATER
 EXTRA_COMPONENTS += UpdatePrompt.js
--- a/mobile/components/MobileComponents.manifest
+++ b/mobile/components/MobileComponents.manifest
@@ -115,8 +115,12 @@ contract @mozilla.org/safebrowsing/appli
 category app-startup SafeBrowsing service,@mozilla.org/safebrowsing/application;1
 #endif
 
 #ifdef MOZ_UPDATER
 # UpdatePrompt.js
 component {88b3eb21-d072-4e3b-886d-f89d8c49fe59} UpdatePrompt.js
 contract @mozilla.org/updates/update-prompt;1 {88b3eb21-d072-4e3b-886d-f89d8c49fe59}
 #endif
+
+# webapps
+component {cb1107c1-1e15-4f11-99c8-27b9ec221a2a} WebappsSupport.js
+contract @mozilla.org/webapps/support;1 {cb1107c1-1e15-4f11-99c8-27b9ec221a2a}
new file mode 100644
--- /dev/null
+++ b/mobile/components/WebappsSupport.idl
@@ -0,0 +1,60 @@
+/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Webapp code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Fabrice Desré <fabrice@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(adb91273-0cf1-4bbe-a37b-22e660192e2a)]
+interface nsIWebappsSupport : nsISupports
+{
+  /**
+   * This method installs a web app.
+   *
+   * @param title     the user-friendly name of the application.
+   * @param uri       the uri of the web app.
+   * @param iconData  a base64 encoded representation of the application's icon.
+   */
+  void installApplication(in wstring title, in wstring uri, in wstring iconUri, in wstring iconData);
+  
+  /**
+   * Checks is a web app is already installed
+   *
+   * @param uri the uri of the web app
+   * @return true if the web app is installed, false if it's not installed
+   */
+  boolean isApplicationInstalled(in wstring uri);
+};
+
new file mode 100644
--- /dev/null
+++ b/mobile/components/WebappsSupport.js
@@ -0,0 +1,125 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Mobile Browser.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Fabrice Desré <fabrice@mozilla.com>
+ *   Mark Finkle <mfinkle@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const Cu = Components.utils; 
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+const DB_VERSION = 1;
+
+function WebappsSupport() {
+  this.init();
+}
+
+WebappsSupport.prototype = {
+  db: null,
+  
+  init: function() {
+    let file =  Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile);
+    file.append("webapps.sqlite");
+    this.db = Services.storage.openDatabase(file);
+    let version = this.db.schemaVersion;
+    
+    if (version == 0) {
+      this.db.executeSimpleSQL("CREATE TABLE webapps (title TEXT, uri TEXT PRIMARY KEY, icon TEXT)");
+      this.db.schemaVersion = DB_VERSION;
+    }
+
+    XPCOMUtils.defineLazyGetter(this, "_installQuery", function() {
+      return this.db.createAsyncStatement("INSERT INTO webapps (title, uri, icon) VALUES(:title, :uri, :icon)");
+    });
+
+    XPCOMUtils.defineLazyGetter(this, "_findQuery", function() {
+      return this.db.createStatement("SELECT uri FROM webapps where uri = :uri");
+    });
+
+    Services.obs.addObserver(this, "quit-application-granted", false);
+  },
+ 
+  // entry point
+  installApplication: function(aTitle, aURI, aIconURI, aIconData) {
+    let stmt = this._installQuery;
+    stmt.params.title = aTitle;
+    stmt.params.uri = aURI;
+    stmt.params.icon = aIconData;
+    stmt.executeAsync();
+  },
+ 
+  isApplicationInstalled: function(aURI) {
+    let stmt = this._findQuery;
+    let found = false;
+    try {
+      stmt.params.uri = aURI;
+      found = stmt.executeStep();
+    } finally {
+      stmt.reset();
+    }
+    return found;
+  },
+
+  // nsIObserver
+  observe: function(aSubject, aTopic, aData) {
+    Services.obs.removeObserver(this, "quit-application-granted");
+
+    // Finalize the statements that we have used
+    let stmts = [
+      "_installQuery",
+      "_findQuery"
+    ];
+    for (let i = 0; i < stmts.length; i++) {
+      // We do not want to create any query we haven't already created, so
+      // see if it is a getter first.
+      if (Object.getOwnPropertyDescriptor(this, stmts[i]).value !== undefined) {
+        this[stmts[i]].finalize();
+      }
+    }
+
+    this.db.asyncClose();
+  },
+
+  // QI
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebappsSupport]),
+
+  // XPCOMUtils factory
+  classID: Components.ID("{cb1107c1-1e15-4f11-99c8-27b9ec221a2a}")
+};
+
+const NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsSupport]);
+
--- a/mobile/installer/package-manifest.in
+++ b/mobile/installer/package-manifest.in
@@ -607,11 +607,12 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
 @BINPATH@/components/SessionStore.js
 @BINPATH@/components/Sidebar.js
 #ifdef MOZ_SAFE_BROWSING
 @BINPATH@/components/SafeBrowsing.js
 #endif
 #ifdef MOZ_UPDATER
 @BINPATH@/components/UpdatePrompt.js
 #endif
+@BINPATH@/components/WebappsSupport.js
 @BINPATH@/components/XPIDialogService.js
 @BINPATH@/components/browsercomps.xpt
 @BINPATH@/extensions/feedback@mobile.mozilla.org.xpi
--- a/mobile/modules/Makefile.in
+++ b/mobile/modules/Makefile.in
@@ -41,16 +41,15 @@ srcdir     = @srcdir@
 VPATH      = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 EXTRA_JS_MODULES = \
   LocaleRepository.jsm \
   linuxTypes.jsm \
   video.jsm \
-  openWebapps.jsm \
   $(NULL)
 
 EXTRA_PP_JS_MODULES = \
   contacts.jsm \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/mobile/modules/openWebapps.jsm
+++ /dev/null
@@ -1,209 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Mobile Browser.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Fabrice Desré <fabrice@mozilla.com>
- *   Mark Finkle <mfinkle@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-const Cu = Components.utils; 
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-
-let EXPORTED_SYMBOLS = ["OpenWebapps"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
-  Cu.import("resource://gre/modules/NetUtil.jsm");
-  return NetUtil;
-});
-
-let OpenWebapps = {
-  appsDir: null,
-  appsFile: null,
-  webapps: { },
-
-  init: function() {
-    let file =  Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile);
-    file.append("webapps");
-    if (!file.exists() || !file.isDirectory()) {
-      file.create(Ci.nsIFile.DIRECTORY_TYPE, 0700);
-    }
-    this.appsDir = file;
-    this.appsFile = file.clone();
-    this.appsFile.append("webapps.json");
-    if (!this.appsFile.exists())
-      return;
-    
-    try {
-      let channel = NetUtil.newChannel(this.appsFile);
-      channel.contentType = "application/json";
-      let self = this;
-      NetUtil.asyncFetch(channel, function(aStream, aResult) {
-        if (!Components.isSuccessCode(aResult)) {
-          Cu.reportError("OpenWebappsSupport: Could not read from webapps.json file");
-          return;
-        }
-
-        // Read webapps json file into a string
-        let data = null;
-        try {
-          data = JSON.parse(NetUtil.readInputStreamToString(aStream, aStream.available()) || "");
-          self.webapps = data;
-          aStream.close();
-        } catch (ex) {
-          Cu.reportError("OpenWebsappsStore: Could not parse JSON: " + ex);
-        }
-      });
-    } catch (ex) {
-      Cu.reportError("OpenWebappsSupport: Could not read from webapps.json file: " + ex);
-    }
-  },
- 
-  _writeFile: function ss_writeFile(aFile, aData) {
-    // Initialize the file output stream.
-    let ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
-    ostream.init(aFile, 0x02 | 0x08 | 0x20, 0600, ostream.DEFER_OPEN);
-
-    // Obtain a converter to convert our data to a UTF-8 encoded input stream.
-    let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
-    converter.charset = "UTF-8";
-
-    // Asynchronously copy the data to the file.
-    let istream = converter.convertToInputStream(aData);
-    NetUtil.asyncCopy(istream, ostream, function(rc) {
-      // nothing to do
-    });
-  },
-  
-  install: function(aApplication) {
-    // Don't install twice an application
-    if (this.amInstalled(aApplication.appURI))
-      return;
-
-    let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
-    let id = uuidGenerator.generateUUID().toString();
-    let dir = this.appsDir.clone();
-    dir.append(id);
-    dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0700);
-    
-    let manFile = dir.clone();
-    manFile.append("manifest.json");
-    this._writeFile(manFile, JSON.stringify(aApplication.manifest));
-    
-    this.webapps[id] = {
-      title: aApplication.title,
-      storeURI: aApplication.storeURI,
-      appURI: aApplication.appURI,
-      iconData: aApplication.iconData,
-      installData: aApplication.installData,
-      installTime: (new Date()).getTime(),
-      manifest: aApplication.manifest
-    };
-    this._writeFile(this.appsFile, JSON.stringify(this.webapps));
-  },
- 
-  amInstalled: function(aURI) {
-    for (let id in this.webapps) {
-      let app = this.webapps[id];
-      if (app.appURI == aURI) {
-        return { origin: app.appURI,
-                 install_origin: app.storeURI,
-                 install_data: app.installData,
-                 install_time: app.installTime,
-                 manifest: app.manifest };
-      }
-    }
-    return null;
-  },
-
-  getInstalledBy: function(aStoreURI) {
-    let res = [];
-    for (let id in this.webapps) {
-      let app = this.webapps[id];
-      if (app.storeURI == aStoreURI)
-        res.push({ origin: app.appURI,
-                   install_origin: app.storeURI,
-                   install_data: app.installData,
-                   install_time: app.installTime,
-                   manifest: app.manifest });
-    }
-    return res;
-  },
-  
-  mgmtList: function() {
-    let res = {};
-    for (let id in this.webapps) {
-      let app = this.webapps[id];
-      res[app.appURI] = { origin: app.appURI,
-                          install_origin: app.storeURI,
-                          install_data: app.installData,
-                          install_time: app.installTime,
-                          manifest: app.manifest };
-    }
-    return res;
-  },
-  
-  mgmtLaunch: function(aOrigin) {
-    for (let id in this.webapps) {
-      let app = this.webapps[id];
-      if (app.appURI == aOrigin) {
-        let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
-        browserWin.browserDOMWindow.openURI(Services.io.newURI(aOrigin, null, null), null, browserWin.OPEN_APPTAB, Ci.nsIBrowserDOMWindow.OPEN_NEW);
-        return true;
-      }
-    }
-    return false;
-  },
-  
-  mgmtUninstall: function(aOrigin) {
-    for (let id in this.webapps) {
-      let app = this.webapps[id];
-      if (app.appURI == aOrigin) {
-        delete this.webapps[id];
-        this._writeFile(this.appsFile, JSON.stringify(this.webapps));
-        let dir = this.appsFile.clone();
-        dir.append(id);
-        try {
-          dir.remove(true);
-        } catch (e) {
-        }
-        return true;
-      }
-    }
-    return false;
-  }
-};
-
-OpenWebapps.init();