Bug 676293 - Add ability to make 'home screen shortcut' for Bookmarks [r=fabrice, r=blassey]
authorMark Finkle <mfinkle@mozilla.com>
Mon, 08 Aug 2011 22:37:57 -0400
changeset 74821 39c342b0c16d213afdf344e9c5f63a6c24261d01
parent 74820 65a834be2590329718573fefd6c6d27ef64df48f
child 74822 d20e5ec041a4a0eb132984f610f1240141b3f24b
push id235
push userbzbarsky@mozilla.com
push dateTue, 27 Sep 2011 17:13:04 +0000
treeherdermozilla-beta@2d1e082d176a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice, blassey
bugs676293
milestone8.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 676293 - Add ability to make 'home screen shortcut' for Bookmarks [r=fabrice, r=blassey]
embedding/android/GeckoApp.java
embedding/android/GeckoAppShell.java
mobile/chrome/content/ContextCommands.js
mobile/chrome/content/browser-ui.js
mobile/chrome/content/browser.xul
mobile/components/Makefile.in
mobile/components/WebappsSupport.idl
mobile/components/build/Makefile.in
mobile/components/build/nsBrowserModule.cpp
mobile/components/build/nsIPhoneSupport.idl
mobile/components/build/nsIShellService.idl
mobile/components/build/nsPhoneSupport.cpp
mobile/components/build/nsPhoneSupport.h
mobile/components/build/nsShellService.cpp
mobile/components/build/nsShellService.h
mobile/locales/en-US/chrome/browser.dtd
mobile/makefiles.sh
toolkit/components/Makefile.in
toolkit/components/build/Makefile.in
toolkit/components/build/nsToolkitCompsCID.h
toolkit/components/build/nsToolkitCompsModule.cpp
toolkit/components/webapps/Makefile.in
toolkit/components/webapps/nsIWebappsSupport.idl
toolkit/components/webapps/nsWebappsSupport.cpp
toolkit/components/webapps/nsWebappsSupport.h
widget/src/android/AndroidBridge.cpp
widget/src/android/AndroidBridge.h
--- a/embedding/android/GeckoApp.java
+++ b/embedding/android/GeckoApp.java
@@ -65,16 +65,17 @@ import android.telephony.*;
 
 abstract public class GeckoApp
     extends Activity
 {
     public static final String ACTION_ALERT_CLICK = "org.mozilla.gecko.ACTION_ALERT_CLICK";
     public static final String ACTION_ALERT_CLEAR = "org.mozilla.gecko.ACTION_ALERT_CLEAR";
     public static final String ACTION_WEBAPP      = "org.mozilla.gecko.WEBAPP";
     public static final String ACTION_DEBUG       = "org.mozilla.gecko.DEBUG";
+    public static final String ACTION_BOOKMARK    = "org.mozilla.gecko.BOOKMARK";
 
     public static FrameLayout mainLayout;
     public static GeckoSurfaceView surfaceView;
     public static GeckoApp mAppContext;
     public static boolean mFullscreen = false;
     public static File sGREDir = null;
     static Thread mLibLoadThread = null;
     public Handler mMainHandler;
@@ -312,30 +313,35 @@ abstract public class GeckoApp
                 }
             });
             mainLayout.addView(launchButton, 300, 200);
             return;
         }
         if (checkLaunchState(LaunchState.WaitButton) || launch(intent))
             return;
 
-        if (Intent.ACTION_VIEW.equals(action)) {
+        if (Intent.ACTION_MAIN.equals(action)) {
+            Log.i("GeckoApp", "Intent : ACTION_MAIN");
+            GeckoAppShell.sendEventToGecko(new GeckoEvent(""));
+        }
+        else if (Intent.ACTION_VIEW.equals(action)) {
             String uri = intent.getDataString();
             GeckoAppShell.sendEventToGecko(new GeckoEvent(uri));
             Log.i("GeckoApp","onNewIntent: "+uri);
         }
-        else if (Intent.ACTION_MAIN.equals(action)) {
-            Log.i("GeckoApp", "Intent : ACTION_MAIN");
-            GeckoAppShell.sendEventToGecko(new GeckoEvent(""));
-        }
         else if (ACTION_WEBAPP.equals(action)) {
             String uri = intent.getStringExtra("args");
             GeckoAppShell.sendEventToGecko(new GeckoEvent(uri));
             Log.i("GeckoApp","Intent : WEBAPP - " + uri);
         }
+        else if (ACTION_BOOKMARK.equals(action)) {
+            String args = intent.getStringExtra("args");
+            GeckoAppShell.sendEventToGecko(new GeckoEvent(args));
+            Log.i("GeckoApp","Intent : BOOKMARK - " + args);
+        }
     }
 
     @Override
     public void onPause()
     {
         Log.i("GeckoApp", "pause");
         GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_PAUSING));
         // The user is navigating away from this activity, but nothing
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -677,24 +677,30 @@ public class GeckoAppShell
         System.exit(0);
     }
     static void scheduleRestart() {
         Log.i("GeckoAppJava", "scheduling restart");
         gRestartScheduled = true;
     }
 
     // "Installs" an application by creating a shortcut
-    static void installWebApplication(String aURI, String aTitle, String aIconData) {
-        Log.w("GeckoAppJava", "installWebApplication for " + aURI + " [" + aTitle + "]");
+    static void createShortcut(String aTitle, String aURI, String aIconData, String aType) {
+        Log.w("GeckoAppJava", "createShortcut for " + aURI + " [" + aTitle + "]");
 
         // the intent to be launched by the shortcut
-        Intent shortcutIntent = new Intent("org.mozilla.gecko.WEBAPP");
+        Intent shortcutIntent = new Intent();
+        if (aType == "webapp") {
+            shortcutIntent.setAction("org.mozilla.gecko.WEBAPP");
+            shortcutIntent.putExtra("args", "--webapp=" + aURI);
+        } else {
+            shortcutIntent.setAction("org.mozilla.gecko.BOOKMARK");
+            shortcutIntent.putExtra("args", "--url=" + aURI);
+        }
         shortcutIntent.setClassName(GeckoApp.mAppContext,
                                     GeckoApp.mAppContext.getPackageName() + ".App");
-        shortcutIntent.putExtra("args", "--webapp=" + aURI);
 
         Intent intent = new Intent();
         intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
         intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, aTitle);
         byte[] raw = Base64.decode(aIconData.substring(22), Base64.DEFAULT);
         Bitmap bitmap = BitmapFactory.decodeByteArray(raw, 0, raw.length);
         intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmap);
         intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
--- a/mobile/chrome/content/ContextCommands.js
+++ b/mobile/chrome/content/ContextCommands.js
@@ -103,10 +103,36 @@ var ContextCommands = {
   editBookmark: function cc_editBookmark() {
     let target = ContextHelper.popupState.target;
     target.startEditing();
   },
 
   removeBookmark: function cc_removeBookmark() {
     let target = ContextHelper.popupState.target;
     target.remove();
+  },
+
+  shortcutBookmark: function cc_shortcutBookmark() {
+    const kIconSize = 64;
+
+    let target = ContextHelper.popupState.target;
+    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);
+      let icon = canvas.toDataURL("image/png", "");
+      canvas = null;
+      try {
+        let shell = Cc["@mozilla.org/browser/shell-service;1"].createInstance(Ci.nsIShellService);
+        shell.createShortcut(target.getAttribute("title"), target.getAttribute("uri"), icon, "bookmark");
+      } catch(e) {
+        Cu.reportError(e);
+      }
+    }
+
+    image.src = target.getAttribute("src");
   }
 };
--- a/mobile/chrome/content/browser-ui.js
+++ b/mobile/chrome/content/browser-ui.js
@@ -869,18 +869,18 @@ var BrowserUI = {
   blurFocusedElement: function blurFocusedElement() {
     let focusedElement = document.commandDispatcher.focusedElement;
     if (focusedElement)
       focusedElement.blur();
   },
 
   switchTask: function switchTask() {
     try {
-      let phone = Cc["@mozilla.org/phone/support;1"].createInstance(Ci.nsIPhoneSupport);
-      phone.switchTask();
+      let shell = Cc["@mozilla.org/browser/shell-service;1"].createInstance(Ci.nsIShellService);
+      shell.switchTask();
     } catch(e) { }
   },
 
   handleEscape: function (aEvent) {
     aEvent.stopPropagation();
 
     // Check open popups
     if (this._popup) {
--- a/mobile/chrome/content/browser.xul
+++ b/mobile/chrome/content/browser.xul
@@ -658,16 +658,19 @@
           </richlistitem>
           <richlistitem class="context-command" id="context-editbookmark" type="edit-bookmark" onclick="ContextCommands.editBookmark();">
             <label value="&contextEditBookmark.label;"/>
           </richlistitem>
           <richlistitem class="context-command" id="context-removebookmark" type="edit-bookmark" onclick="ContextCommands.removeBookmark();">
             <label value="&contextRemoveBookmark.label;"/>
           </richlistitem>
 #ifdef ANDROID
+          <richlistitem class="context-command" id="context-shortcutbookmark" type="edit-bookmark" onclick="ContextCommands.shortcutBookmark();">
+            <label value="&contextShortcutBookmark.label;"/>
+          </richlistitem>
           <richlistitem class="context-command" id="context-select-input" type="input-text" onclick="ContextCommands.selectInput();">
             <label value="&inputMethod.label;"/>
           </richlistitem>
 #endif
         </richlistbox>
       </vbox>
     </hbox>
 
--- 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 \
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);
+};
+
--- a/mobile/components/build/Makefile.in
+++ b/mobile/components/build/Makefile.in
@@ -54,26 +54,26 @@ EXPORT_LIBRARY  = 1
 EXPORTS = nsBrowserComponents.h
 
 REQUIRES	= \
 		  xpcom \
 		  string \
 		  pref \
 		  $(NULL)
 
+XPIDL_MODULE = browsercomps
+
+XPIDLSRCS = nsIShellService.idl
+
 CPPSRCS = \
 	nsSSLCertErrorDialog.cpp \
 	nsBrowserModule.cpp \
+	nsShellService.cpp \
 	$(NULL)
 
-ifndef ANDROID
-CPPSRCS += nsPhoneSupport.cpp
-XPIDLSRCS = nsIPhoneSupport.idl
-endif
-
 ifeq ($(MOZ_PLATFORM_MAEMO),5)
 LOCAL_INCLUDES   += $(MOZ_DBUS_GLIB_CFLAGS)
 endif
 
 ifneq (,$(filter $(MOZ_WIDGET_TOOLKIT),qt))
 LOCAL_INCLUDES += $(MOZ_QT_CFLAGS)
 endif
 
--- a/mobile/components/build/nsBrowserModule.cpp
+++ b/mobile/components/build/nsBrowserModule.cpp
@@ -34,42 +34,33 @@
  * 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 "mozilla/ModuleUtils.h"
 
-#ifndef ANDROID
-#include "nsPhoneSupport.h"
-#endif
-
+#include "nsShellService.h"
 #include "nsSSLCertErrorDialog.h"
 
-#ifndef ANDROID
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsPhoneSupport)
-NS_DEFINE_NAMED_CID(nsPhoneSupport_CID);
-#endif
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsShellService)
+NS_DEFINE_NAMED_CID(nsShellService_CID);
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSSLCertErrorDialog)
 NS_DEFINE_NAMED_CID(nsSSLCertErrorDialog_CID);
 
 static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
-#ifndef ANDROID
-  { &knsPhoneSupport_CID, false, NULL, nsPhoneSupportConstructor },
-#endif
+  { &knsShellService_CID, false, NULL, nsShellServiceConstructor },
   { &knsSSLCertErrorDialog_CID, false, NULL, nsSSLCertErrorDialogConstructor },
   { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
-#ifndef ANDROID
-  { nsPhoneSupport_ContractID, &knsPhoneSupport_CID },
-#endif
+  { nsShellService_ContractID, &knsShellService_CID },
   { nsSSLCertErrorDialog_ContractID, &knsSSLCertErrorDialog_CID },
   { NULL }
 };
 
 static const mozilla::Module kBrowserModule = {
   mozilla::Module::kVersion,
   kBrowserCIDs,
   kBrowserContracts
rename from mobile/components/build/nsIPhoneSupport.idl
rename to mobile/components/build/nsIShellService.idl
--- a/mobile/components/build/nsIPhoneSupport.idl
+++ b/mobile/components/build/nsIShellService.idl
@@ -35,16 +35,27 @@
  * 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(c893eb89-8650-49d2-aed7-0ef809a2b940)]
-interface nsIPhoneSupport : nsISupports
+[scriptable, uuid(fd2450a3-966b-44a9-a8eb-316256bb80b4)]
+interface nsIShellService : nsISupports
 {
   /**
    * This method displays a UI to switch to (or launch) a different task
    */
   void switchTask();
+
+  /**
+   * This method creates a shortcut on a desktop or homescreen that opens in
+   * the our application.
+   *
+   * @param aTitle     the user-friendly name of the shortcut.
+   * @param aURI       the URI to open.
+   * @param aIconData  a base64 encoded representation of the shortcut's icon.
+   * @param aIntent    how the URI should be opened. Examples: "default", "bookmark" and "webapp"
+   */
+  void createShortcut(in AString aTitle, in AString aURI, in AString aIconData, in AString aIntent);
 };
rename from mobile/components/build/nsPhoneSupport.cpp
rename to mobile/components/build/nsShellService.cpp
--- a/mobile/components/build/nsPhoneSupport.cpp
+++ b/mobile/components/build/nsShellService.cpp
@@ -43,23 +43,27 @@
 #include <dbus/dbus.h>
 #endif
 
 #ifdef MOZ_WIDGET_QT
 #include <QtGui/QApplication>
 #include <QtGui/QWidget>
 #endif
 
-#include "nsPhoneSupport.h"
+#ifdef ANDROID
+#include "AndroidBridge.h"
+#endif
+
+#include "nsShellService.h"
 #include "nsString.h"
 
-NS_IMPL_ISUPPORTS1(nsPhoneSupport, nsIPhoneSupport)
+NS_IMPL_ISUPPORTS1(nsShellService, nsIShellService)
 
 NS_IMETHODIMP
-nsPhoneSupport::SwitchTask()
+nsShellService::SwitchTask()
 {
 #if (MOZ_PLATFORM_MAEMO == 5)
   DBusError error;
   dbus_error_init(&error);
 
   DBusConnection *conn = dbus_bus_get(DBUS_BUS_SESSION, &error);
 
   DBusMessage *msg = dbus_message_new_signal("/com/nokia/hildon_desktop",
@@ -76,8 +80,22 @@ nsPhoneSupport::SwitchTask()
   QWidget * window = QApplication::activeWindow();
   if (window)
       window->showMinimized();
   return NS_OK;
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif
 }
+
+NS_IMETHODIMP
+nsShellService::CreateShortcut(const nsAString& aTitle, const nsAString& aURI, const nsAString& aIconData, const nsAString& aIntent)
+{
+  if (!aTitle.Length() || !aURI.Length() || !aIconData.Length())
+    return NS_ERROR_FAILURE;
+
+#if ANDROID
+  mozilla::AndroidBridge::Bridge()->CreateShortcut(aTitle, aURI, aIconData, aIntent);
+  return NS_OK;
+#else
+  return NS_ERROR_NOT_IMPLEMENTED;
+#endif
+}
rename from mobile/components/build/nsPhoneSupport.h
rename to mobile/components/build/nsShellService.h
--- a/mobile/components/build/nsPhoneSupport.h
+++ b/mobile/components/build/nsShellService.h
@@ -34,32 +34,31 @@
  * 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 ***** */
 
-#ifndef __NS_PHONESUPPORT_H__
-#define __NS_PHONESUPPORT_H__
+#ifndef __NS_SHELLSERVICE_H__
+#define __NS_SHELLSERVICE_H__
 
-#include "nsIPhoneSupport.h"
+#include "nsIShellService.h"
 
-class nsPhoneSupport : public nsIPhoneSupport
+class nsShellService : public nsIShellService
 {
 public:
 
   NS_DECL_ISUPPORTS
-  NS_DECL_NSIPHONESUPPORT
+  NS_DECL_NSISHELLSERVICE
 
-  nsPhoneSupport() {};
-  ~nsPhoneSupport() {};
+  nsShellService() {};
+  ~nsShellService() {};
 
 };
 
-#define nsPhoneSupport_CID                          \
-{ 0x2a08c9e4, 0xf853, 0x4f02,                       \
-{0x88, 0xd8, 0xd6, 0x2f, 0x27, 0xca, 0x06, 0x85} }
+#define nsShellService_CID                          \
+{0xae9ebe1c, 0x61e9, 0x45fa, {0x8f, 0x34, 0xc1, 0x07, 0x80, 0x3a, 0x5b, 0x44}}
 
-#define nsPhoneSupport_ContractID "@mozilla.org/phone/support;1"
+#define nsShellService_ContractID "@mozilla.org/browser/shell-service;1"
 
 #endif
--- a/mobile/locales/en-US/chrome/browser.dtd
+++ b/mobile/locales/en-US/chrome/browser.dtd
@@ -99,16 +99,17 @@
 <!ENTITY contextBookmarkLink.label    "Bookmark Link">
 <!ENTITY contextSaveVideo.label       "Save Video">
 <!ENTITY contextShareVideo.label      "Share Video">
 <!ENTITY contextPlayMedia.label       "Play">
 <!ENTITY contextPauseMedia.label      "Pause">
 <!ENTITY contextFullScreen.label      "Full Screen">
 <!ENTITY contextEditBookmark.label    "Edit">
 <!ENTITY contextRemoveBookmark.label  "Remove">
+<!ENTITY contextShortcutBookmark.label "Add Shortcut to Home">
 
 <!ENTITY pageactions.saveas.pdf      "Save As PDF">
 <!ENTITY pageactions.share.page      "Share Page">
 <!ENTITY pageactions.password.forget "Forget Password">
 <!ENTITY pageactions.quit            "Quit">
 <!ENTITY pageactions.reset           "Clear Site Preferences">
 <!ENTITY pageactions.findInPage      "Find In Page">
 <!ENTITY pageactions.search.addNew   "Add Search Engine">
--- a/mobile/makefiles.sh
+++ b/mobile/makefiles.sh
@@ -42,17 +42,17 @@ toolkit/locales/Makefile
 security/manager/locales/Makefile
 mobile/app/Makefile
 mobile/app/profile/extensions/Makefile
 $MOZ_BRANDING_DIRECTORY/Makefile
 $MOZ_BRANDING_DIRECTORY/locales/Makefile
 mobile/chrome/Makefile
 mobile/chrome/tests/Makefile
 mobile/components/Makefile
-mobile/components/phone/Makefile
+mobile/components/build/Makefile
 mobile/modules/Makefile
 mobile/installer/Makefile
 mobile/locales/Makefile
 mobile/Makefile
 mobile/themes/Makefile
 mobile/themes/core/Makefile"
 
 if test -n "$MOZ_UPDATE_PACKAGING"; then
--- a/toolkit/components/Makefile.in
+++ b/toolkit/components/Makefile.in
@@ -67,17 +67,16 @@ PARALLEL_DIRS += \
   prompts \
   reflect \
   startup \
   statusfilter \
   typeaheadfind \
   urlformatter \
   viewconfig \
   viewsource \
-  webapps \
   telemetry \
   $(NULL)
 
 ifdef BUILD_CTYPES
 PARALLEL_DIRS += \
   ctypes \
   $(NULL)
 endif
--- a/toolkit/components/build/Makefile.in
+++ b/toolkit/components/build/Makefile.in
@@ -73,22 +73,16 @@ LOCAL_INCLUDES = \
   $(NULL)
 
 ifdef ALERTS_SERVICE
 LOCAL_INCLUDES += \
   -I$(srcdir)/../alerts \
   $(NULL)
 endif
 
-ifeq (Android,$(OS_TARGET))
-LOCAL_INCLUDES += \
-  -I$(srcdir)/../webapps \
-  $(NULL)
-endif
-
 SHARED_LIBRARY_LIBS = \
   ../find/$(LIB_PREFIX)mozfind_s.$(LIB_SUFFIX) \
   ../typeaheadfind/$(LIB_PREFIX)fastfind_s.$(LIB_SUFFIX) \
   ../startup/$(LIB_PREFIX)appstartup_s.$(LIB_SUFFIX) \
   ../statusfilter/$(LIB_PREFIX)mozbrwsr_s.$(LIB_SUFFIX) \
   $(NULL)
 
 ifndef MOZ_DISABLE_PARENTAL_CONTROLS
@@ -118,13 +112,9 @@ endif
 ifdef MOZ_URL_CLASSIFIER
 SHARED_LIBRARY_LIBS += ../url-classifier/$(LIB_PREFIX)urlclassifier_s.$(LIB_SUFFIX)
 endif
 
 ifdef MOZ_FEEDS
 SHARED_LIBRARY_LIBS += ../feeds/$(LIB_PREFIX)feed_s.$(LIB_SUFFIX)
 endif
 
-ifeq (Android,$(OS_TARGET))
-SHARED_LIBRARY_LIBS += ../webapps/$(LIB_PREFIX)webapps_s.$(LIB_SUFFIX)
-endif
-
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/components/build/nsToolkitCompsCID.h
+++ b/toolkit/components/build/nsToolkitCompsCID.h
@@ -111,19 +111,16 @@
   "@mozilla.org/browser/favicon-service;1"
 
 #define NS_PLACESIMPORTEXPORTSERVICE_CONTRACTID \
   "@mozilla.org/browser/places/import-export-service;1"
 
 #define NS_APPSTARTUP_CONTRACTID \
   "@mozilla.org/toolkit/app-startup;1"
 
-#define NS_WEBAPPSSUPPORT_CONTRACTID \
-  "@mozilla.org/webapps/installer;1"
-
 /////////////////////////////////////////////////////////////////////////////
 
 // {A0CCAAF8-09DA-44D8-B250-9AC3E93C8117}
 #define NS_ALERTSSERVICE_CID \
 { 0xa0ccaaf8, 0x9da, 0x44d8, { 0xb2, 0x50, 0x9a, 0xc3, 0xe9, 0x3c, 0x81, 0x17 } }
 
 // {84E11F80-CA55-11DD-AD8B-0800200C9A66}
 #define NS_SYSTEMALERTSSERVICE_CID \
@@ -189,12 +186,8 @@
 { 0x9de95a0c, 0x39a4, 0x4d64, {0x9a, 0x53, 0x17, 0x94, 0x0d, 0xd7, 0xca, 0xbb}}
 
 #define NS_FAVICONSERVICE_CID \
 { 0x984e3259, 0x9266, 0x49cf, { 0xb6, 0x05, 0x60, 0xb0, 0x22, 0xa0, 0x07, 0x56 } }
 
 // {6fb0c970-e1b1-11db-8314-0800200c9a66}
 #define NS_PLACESIMPORTEXPORTSERVICE_CID \
 { 0x6fb0c970, 0xe1b1, 0x11db, { 0x83, 0x14, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }
-
-#define NS_WEBAPPSSUPPORT_CID \
-{ 0xd0b62752, 0x88be, 0x4c88, {0x94, 0xe5, 0xc6, 0x9e, 0x15, 0xa1, 0x0c, 0x4e} }
-
--- a/toolkit/components/build/nsToolkitCompsModule.cpp
+++ b/toolkit/components/build/nsToolkitCompsModule.cpp
@@ -66,20 +66,16 @@
 #endif
 
 #ifdef MOZ_FEEDS
 #include "nsScriptableUnescapeHTML.h"
 #endif
 
 #include "nsBrowserStatusFilter.h"
 
-#ifdef ANDROID
-#include "nsWebappsSupport.h"
-#endif
-
 /////////////////////////////////////////////////////////////////////////////
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsAppStartup, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsUserInfo)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFindService)
 
 #if defined(XP_WIN) && !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsParentalControlsServiceWin)
@@ -122,20 +118,16 @@ nsUrlClassifierDBServiceConstructor(nsIS
 #endif
 
 #ifdef MOZ_FEEDS
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsScriptableUnescapeHTML)
 #endif
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBrowserStatusFilter)
 
-#ifdef ANDROID
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebappsSupport)
-#endif
-
 NS_DEFINE_NAMED_CID(NS_TOOLKIT_APPSTARTUP_CID);
 NS_DEFINE_NAMED_CID(NS_USERINFO_CID);
 #ifdef ALERTS_SERVICE
 NS_DEFINE_NAMED_CID(NS_ALERTSSERVICE_CID);
 #endif
 #if defined(XP_WIN) && !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
 NS_DEFINE_NAMED_CID(NS_PARENTALCONTROLSSERVICE_CID);
 #endif
@@ -151,20 +143,16 @@ NS_DEFINE_NAMED_CID(NS_URLCLASSIFIERSTRE
 NS_DEFINE_NAMED_CID(NS_URLCLASSIFIERUTILS_CID);
 #endif
 #ifdef MOZ_FEEDS
 NS_DEFINE_NAMED_CID(NS_SCRIPTABLEUNESCAPEHTML_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_BROWSERSTATUSFILTER_CID);
 NS_DEFINE_NAMED_CID(NS_CHARSETMENU_CID);
 
-#ifdef ANDROID
-NS_DEFINE_NAMED_CID(NS_WEBAPPSSUPPORT_CID);
-#endif
-
 static const mozilla::Module::CIDEntry kToolkitCIDs[] = {
   { &kNS_TOOLKIT_APPSTARTUP_CID, false, NULL, nsAppStartupConstructor },
   { &kNS_USERINFO_CID, false, NULL, nsUserInfoConstructor },
 #ifdef ALERTS_SERVICE
   { &kNS_ALERTSSERVICE_CID, false, NULL, nsAlertsServiceConstructor },
 #endif
 #if defined(XP_WIN) && !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
   { &kNS_PARENTALCONTROLSSERVICE_CID, false, NULL, nsParentalControlsServiceWinConstructor },
@@ -180,19 +168,16 @@ static const mozilla::Module::CIDEntry k
   { &kNS_URLCLASSIFIERSTREAMUPDATER_CID, false, NULL, nsUrlClassifierStreamUpdaterConstructor },
   { &kNS_URLCLASSIFIERUTILS_CID, false, NULL, nsUrlClassifierUtilsConstructor },
 #endif
 #ifdef MOZ_FEEDS
   { &kNS_SCRIPTABLEUNESCAPEHTML_CID, false, NULL, nsScriptableUnescapeHTMLConstructor },
 #endif
   { &kNS_BROWSERSTATUSFILTER_CID, false, NULL, nsBrowserStatusFilterConstructor },
   { &kNS_CHARSETMENU_CID, false, NULL, NS_NewCharsetMenu },
-#ifdef ANDROID
-  { &kNS_WEBAPPSSUPPORT_CID, false, NULL, nsWebappsSupportConstructor },
-#endif
   { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kToolkitContracts[] = {
   { NS_APPSTARTUP_CONTRACTID, &kNS_TOOLKIT_APPSTARTUP_CID },
   { NS_USERINFO_CONTRACTID, &kNS_USERINFO_CID },
 #ifdef ALERTS_SERVICE
   { NS_ALERTSERVICE_CONTRACTID, &kNS_ALERTSSERVICE_CID },
@@ -212,19 +197,16 @@ static const mozilla::Module::ContractID
   { NS_URLCLASSIFIERSTREAMUPDATER_CONTRACTID, &kNS_URLCLASSIFIERSTREAMUPDATER_CID },
   { NS_URLCLASSIFIERUTILS_CONTRACTID, &kNS_URLCLASSIFIERUTILS_CID },
 #endif
 #ifdef MOZ_FEEDS
   { NS_SCRIPTABLEUNESCAPEHTML_CONTRACTID, &kNS_SCRIPTABLEUNESCAPEHTML_CID },
 #endif
   { NS_BROWSERSTATUSFILTER_CONTRACTID, &kNS_BROWSERSTATUSFILTER_CID },
   { NS_RDF_DATASOURCE_CONTRACTID_PREFIX NS_CHARSETMENU_PID, &kNS_CHARSETMENU_CID },
-#ifdef ANDROID
-  { NS_WEBAPPSSUPPORT_CONTRACTID, &kNS_WEBAPPSSUPPORT_CID },
-#endif
   { NULL }
 };
 
 static const mozilla::Module kToolkitModule = {
   mozilla::Module::kVersion,
   kToolkitCIDs,
   kToolkitContracts
 };
deleted file mode 100644
--- a/toolkit/components/webapps/Makefile.in
+++ /dev/null
@@ -1,61 +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 Webapp code.
-#
-# The Initial Developer of the Original Code is
-# the 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 *****
-
-DEPTH		= ../../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-MODULE_NAME = webapps
-MODULE      = webapps
- 
-ifeq (Android,$(OS_TARGET))
-LIBRARY_NAME    = webapps_s
-LIBXUL_LIBRARY  = 1
-IS_COMPONENT    = 1
-EXPORT_LIBRARY  = 1
-
-CPPSRCS = \
-        nsWebappsSupport.cpp \
-        $(NULL)
-endif
-
-XPIDLSRCS = nsIWebappsSupport.idl
-
-include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/toolkit/components/webapps/nsIWebappsSupport.idl
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- 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);
-};
-
deleted file mode 100644
--- a/toolkit/components/webapps/nsWebappsSupport.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/* -*- 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 "AndroidBridge.h"
-#include "nsCRTGlue.h"
-#include "nsWebappsSupport.h"
-
-using namespace mozilla;
-
-NS_IMPL_ISUPPORTS1(nsWebappsSupport, nsIWebappsSupport)
-
-NS_IMETHODIMP
-nsWebappsSupport::InstallApplication(const PRUnichar *aTitle, const PRUnichar *aURI, const PRUnichar *aIconURI, const PRUnichar *aIconData)
-{
-  ALOG("in nsWebappsSupport::InstallApplication()\n");
-  AndroidBridge::AutoLocalJNIFrame jniFrame;
-  JNIEnv *jEnv = GetJNIForThread();
-  jclass jGeckoAppShellClass = GetGeckoAppShellClass();
-  
-  if (!jEnv || !jGeckoAppShellClass)
-    return NS_ERROR_FAILURE;
-    
-  jmethodID jInstallWebApplication = jEnv->GetStaticMethodID(jGeckoAppShellClass, "installWebApplication", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
-  jstring jstrURI = jEnv->NewString(aURI, NS_strlen(aURI));
-  jstring jstrTitle = jEnv->NewString(aTitle, NS_strlen(aTitle));
-  jstring jstrIconData = jEnv->NewString(aIconData, NS_strlen(aIconData));
-  
-  if (!jstrURI || !jstrTitle || !jstrIconData)
-    return NS_ERROR_FAILURE;
-    
-  jEnv->CallStaticVoidMethod(jGeckoAppShellClass, jInstallWebApplication, jstrURI, jstrTitle, jstrIconData);
-  return NS_OK;
-}
-
-/*
- * we have no way to know if an application is installed, so pretend it's not installed
- */
-NS_IMETHODIMP
-nsWebappsSupport::IsApplicationInstalled(const PRUnichar *aURI, PRBool *_retval)
-{
-  *_retval = PR_FALSE;
-  return NS_OK;
-}
-
deleted file mode 100644
--- a/toolkit/components/webapps/nsWebappsSupport.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*- 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 ***** */
-
-#ifndef nsWebappsSupport_h__
-#define nsWebappsSupport_h__
-
-#include "nsIWebappsSupport.h"
-
-class nsWebappsSupport : public nsIWebappsSupport
-{
-public:
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIWEBAPPSSUPPORT
-
-  nsWebappsSupport() {};
-  ~nsWebappsSupport() {};
-
-};
-
-#endif // nsWebappsSupport_h__
-
--- a/widget/src/android/AndroidBridge.cpp
+++ b/widget/src/android/AndroidBridge.cpp
@@ -142,16 +142,17 @@ AndroidBridge::Init(JNIEnv *jEnv,
     jSetKeepScreenOn = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setKeepScreenOn", "(Z)V");
     jIsNetworkLinkUp = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "isNetworkLinkUp", "()Z");
     jIsNetworkLinkKnown = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "isNetworkLinkKnown", "()Z");
     jGetNetworkLinkType = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getNetworkLinkType", "()I");
     jSetSelectedLocale = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setSelectedLocale", "(Ljava/lang/String;)V");
     jScanMedia = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "scanMedia", "(Ljava/lang/String;Ljava/lang/String;)V");
     jGetSystemColors = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getSystemColors", "()[I");
     jGetIconForExtension = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getIconForExtension", "(Ljava/lang/String;I)[B");
+    jCreateShortcut = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "createShortcut", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
 
     jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext"));
     jEGL10Class = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGL10"));
     jEGLSurfaceImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLSurfaceImpl"));
     jEGLContextImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLContextImpl"));
     jEGLConfigImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLConfigImpl"));
     jEGLDisplayImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLDisplayImpl"));
 
@@ -897,16 +898,31 @@ AndroidBridge::ScanMedia(const nsAString
 
     nsString mimeType2;
     CopyUTF8toUTF16(aMimeType, mimeType2);
     jstring jstrMimeTypes = mJNIEnv->NewString(nsPromiseFlatString(mimeType2).get(), mimeType2.Length());
 
     mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jScanMedia, jstrFile, jstrMimeTypes);
 }
 
+void
+AndroidBridge::CreateShortcut(const nsAString& aTitle, const nsAString& aURI, const nsAString& aIconData, const nsAString& aIntent)
+{
+  AutoLocalJNIFrame jniFrame;
+  jstring jstrTitle = mJNIEnv->NewString(nsPromiseFlatString(aTitle).get(), aTitle.Length());
+  jstring jstrURI = mJNIEnv->NewString(nsPromiseFlatString(aURI).get(), aURI.Length());
+  jstring jstrIconData = mJNIEnv->NewString(nsPromiseFlatString(aIconData).get(), aIconData.Length());
+  jstring jstrIntent = mJNIEnv->NewString(nsPromiseFlatString(aIntent).get(), aIntent.Length());
+  
+  if (!jstrURI || !jstrTitle || !jstrIconData)
+    return;
+    
+  mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jCreateShortcut, jstrTitle, jstrURI, jstrIconData, jstrIntent);
+}
+
 bool
 AndroidBridge::HasNativeBitmapAccess()
 {
     if (!mOpenedBitmapLibrary) {
         // Try to dlopen libjnigraphics.so for direct bitmap access on
         // Android 2.2+ (API level 8)
         mOpenedBitmapLibrary = true;
 
--- a/widget/src/android/AndroidBridge.h
+++ b/widget/src/android/AndroidBridge.h
@@ -244,16 +244,18 @@ public:
     bool GetStaticStringField(const char *classID, const char *field, nsAString &result);
 
     bool GetStaticIntField(const char *className, const char *fieldName, PRInt32* aInt);
 
     void SetKeepScreenOn(bool on);
 
     void ScanMedia(const nsAString& aFile, const nsACString& aMimeType);
 
+    void CreateShortcut(const nsAString& aTitle, const nsAString& aURI, const nsAString& aIconData, const nsAString& aIntent);
+
     // These next four functions are for native Bitmap access in Android 2.2+
     bool HasNativeBitmapAccess();
 
     bool ValidateBitmap(jobject bitmap, int width, int height);
 
     void *LockBitmap(jobject bitmap);
 
     void UnlockBitmap(jobject bitmap);
@@ -314,16 +316,17 @@ protected:
     jmethodID jSetKeepScreenOn;
     jmethodID jIsNetworkLinkUp;
     jmethodID jIsNetworkLinkKnown;
     jmethodID jGetNetworkLinkType;
     jmethodID jSetSelectedLocale;
     jmethodID jScanMedia;
     jmethodID jGetSystemColors;
     jmethodID jGetIconForExtension;
+    jmethodID jCreateShortcut;
 
     // stuff we need for CallEglCreateWindowSurface
     jclass jEGLSurfaceImplClass;
     jclass jEGLContextImplClass;
     jclass jEGLConfigImplClass;
     jclass jEGLDisplayImplClass;
     jclass jEGLContextClass;
     jclass jEGL10Class;