bug 582616 - Sharing back-end for Android r=mwu,mfinkle sr=stuart a=blocking-fennec
authorBrad Lassey <blassey@mozilla.com>
Thu, 30 Sep 2010 11:37:36 -0400
changeset 54802 8a6554580c4ee65421645ba65e7868472199fac6
parent 54801 0a01860cef281c032c1a7cab2538d07b4ad053a5
child 54803 71ab2e2fa1cce4d0a2d702f352c267856c747f0e
push id16032
push userblassey@mozilla.com
push dateThu, 30 Sep 2010 15:38:30 +0000
treeherdermozilla-central@8a6554580c4e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmwu, mfinkle, stuart, blocking-fennec
bugs582616
milestone2.0b7pre
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 582616 - Sharing back-end for Android r=mwu,mfinkle sr=stuart a=blocking-fennec
docshell/build/nsDocShellModule.cpp
embedding/android/GeckoAppShell.java
uriloader/exthandler/Makefile.in
uriloader/exthandler/android/nsAndroidHandlerApp.cpp
uriloader/exthandler/android/nsAndroidHandlerApp.h
uriloader/exthandler/android/nsExternalSharingAppService.cpp
uriloader/exthandler/android/nsExternalSharingAppService.h
uriloader/exthandler/android/nsMIMEInfoAndroid.cpp
uriloader/exthandler/android/nsOSHelperAppService.cpp
uriloader/exthandler/android/nsOSHelperAppService.h
uriloader/exthandler/beos/nsOSHelperAppService.h
uriloader/exthandler/mac/nsOSHelperAppService.h
uriloader/exthandler/nsExternalHelperAppService.cpp
uriloader/exthandler/nsExternalHelperAppService.h
uriloader/exthandler/nsIExternalSharingAppService.idl
uriloader/exthandler/os2/nsOSHelperAppService.h
uriloader/exthandler/unix/nsOSHelperAppService.h
uriloader/exthandler/win/nsOSHelperAppService.h
widget/src/android/AndroidBridge.cpp
widget/src/android/AndroidBridge.h
--- a/docshell/build/nsDocShellModule.cpp
+++ b/docshell/build/nsDocShellModule.cpp
@@ -52,16 +52,19 @@
 #include "nsOSHelperAppService.h"
 #include "nsExternalProtocolHandler.h"
 #include "nsPrefetchService.h"
 #include "nsOfflineCacheUpdate.h"
 #include "nsLocalHandlerApp.h"
 #ifdef MOZ_ENABLE_DBUS
 #include "nsDBusHandlerApp.h"
 #endif 
+#ifdef ANDROID
+#include "nsExternalSharingAppService.h"
+#endif
 
 // session history
 #include "nsSHEntry.h"
 #include "nsSHistory.h"
 #include "nsSHTransaction.h"
 
 // download history
 #include "nsDownloadHistory.h"
@@ -105,16 +108,19 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsExterna
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrefetchService, Init)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsOfflineCacheUpdateService,
                                          nsOfflineCacheUpdateService::GetInstance)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsOfflineCacheUpdate)
 NS_GENERIC_FACTORY_CONSTRUCTOR(PlatformLocalHandlerApp_t)
 #ifdef MOZ_ENABLE_DBUS
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDBusHandlerApp)
 #endif 
+#ifdef ANDROID
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsExternalSharingAppService)
+#endif
 
 // session history
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSHEntry)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSHTransaction)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSHistory)
 
 // download history
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloadHistory)
@@ -129,16 +135,19 @@ NS_DEFINE_NAMED_CID(NS_EXTERNALHELPERAPP
 NS_DEFINE_NAMED_CID(NS_EXTERNALPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_PREFETCHSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_OFFLINECACHEUPDATESERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_OFFLINECACHEUPDATE_CID);
 NS_DEFINE_NAMED_CID(NS_LOCALHANDLERAPP_CID);
 #ifdef MOZ_ENABLE_DBUS
 NS_DEFINE_NAMED_CID(NS_DBUSHANDLERAPP_CID);
 #endif
+#ifdef ANDROID
+NS_DEFINE_NAMED_CID(NS_EXTERNALSHARINGAPPSERVICE_CID);
+#endif
 NS_DEFINE_NAMED_CID(NS_SHENTRY_CID);
 NS_DEFINE_NAMED_CID(NS_HISTORYENTRY_CID);
 NS_DEFINE_NAMED_CID(NS_SHTRANSACTION_CID);
 NS_DEFINE_NAMED_CID(NS_SHISTORY_CID);
 NS_DEFINE_NAMED_CID(NS_SHISTORY_INTERNAL_CID);
 NS_DEFINE_NAMED_CID(NS_DOWNLOADHISTORY_CID);
 
 
@@ -153,16 +162,19 @@ const mozilla::Module::CIDEntry kDocShel
   { &kNS_EXTERNALPROTOCOLHANDLER_CID, false, NULL, nsExternalProtocolHandlerConstructor },
   { &kNS_PREFETCHSERVICE_CID, false, NULL, nsPrefetchServiceConstructor },
   { &kNS_OFFLINECACHEUPDATESERVICE_CID, false, NULL, nsOfflineCacheUpdateServiceConstructor },
   { &kNS_OFFLINECACHEUPDATE_CID, false, NULL, nsOfflineCacheUpdateConstructor },
   { &kNS_LOCALHANDLERAPP_CID, false, NULL, PlatformLocalHandlerApp_tConstructor },
 #ifdef MOZ_ENABLE_DBUS
   { &kNS_DBUSHANDLERAPP_CID, false, NULL, nsDBusHandlerAppConstructor },
 #endif
+#ifdef ANDROID
+  { &kNS_EXTERNALSHARINGAPPSERVICE_CID, false, NULL, nsExternalSharingAppServiceConstructor },
+#endif
   { &kNS_SHENTRY_CID, false, NULL, nsSHEntryConstructor },
   { &kNS_HISTORYENTRY_CID, false, NULL, nsSHEntryConstructor },
   { &kNS_SHTRANSACTION_CID, false, NULL, nsSHTransactionConstructor },
   { &kNS_SHISTORY_CID, false, NULL, nsSHistoryConstructor },
   { &kNS_SHISTORY_INTERNAL_CID, false, NULL, nsSHistoryConstructor },
   { &kNS_DOWNLOADHISTORY_CID, false, NULL, nsDownloadHistoryConstructor },
   { NULL }
 };
@@ -194,16 +206,19 @@ const mozilla::Module::ContractIDEntry k
   { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"default", &kNS_EXTERNALPROTOCOLHANDLER_CID },
   { NS_PREFETCHSERVICE_CONTRACTID, &kNS_PREFETCHSERVICE_CID },
   { NS_OFFLINECACHEUPDATESERVICE_CONTRACTID, &kNS_OFFLINECACHEUPDATESERVICE_CID },
   { NS_OFFLINECACHEUPDATE_CONTRACTID, &kNS_OFFLINECACHEUPDATE_CID },
   { NS_LOCALHANDLERAPP_CONTRACTID, &kNS_LOCALHANDLERAPP_CID },
 #ifdef MOZ_ENABLE_DBUS
   { NS_DBUSHANDLERAPP_CONTRACTID, &kNS_DBUSHANDLERAPP_CID },
 #endif
+#ifdef ANDROID
+  { NS_EXTERNALSHARINGAPPSERVICE_CONTRACTID, &kNS_EXTERNALSHARINGAPPSERVICE_CID },
+#endif
   { NS_SHENTRY_CONTRACTID, &kNS_SHENTRY_CID },
   { NS_HISTORYENTRY_CONTRACTID, &kNS_HISTORYENTRY_CID },
   { NS_SHTRANSACTION_CONTRACTID, &kNS_SHTRANSACTION_CID },
   { NS_SHISTORY_CONTRACTID, &kNS_SHISTORY_CID },
   { NS_SHISTORY_INTERNAL_CONTRACTID, &kNS_SHISTORY_INTERNAL_CID },
   { NS_DOWNLOADHISTORY_CONTRACTID, &kNS_DOWNLOADHISTORY_CID },
   { NULL }
 };
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -356,73 +356,73 @@ class GeckoAppShell
         }
 
     }
     static void scheduleRestart() {
         Log.i("GeckoAppJava", "scheduling restart");
         gRestartScheduled = true;        
     }
     
-    static String[] getHandlersForMimeType(String aMimeType) {
+    static String[] getHandlersForMimeType(String aMimeType, String aAction) {
+        Intent intent = getIntentForActionString(aAction);
+        if (aMimeType != null && aMimeType.length() > 0)
+            intent.setType(aMimeType);
+        return getHandlersForIntent(intent);
+    }
+
+    static String[] getHandlersForProtocol(String aScheme, String aAction) {
+        Intent intent = getIntentForActionString(aAction);
+        Uri uri = new Uri.Builder().scheme(aScheme).build();
+        intent.setData(uri);
+        return getHandlersForIntent(intent);
+    }
+
+    static String[] getHandlersForIntent(Intent intent) {
         PackageManager pm = 
             GeckoApp.surfaceView.getContext().getPackageManager();
-        Intent intent = new Intent();
-        intent.setType(aMimeType);
         List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
         int numAttr = 4;
         String[] ret = new String[list.size() * numAttr];
         for (int i = 0; i < list.size(); i++) {
             ResolveInfo resolveInfo = list.get(i);
             ret[i * numAttr] = resolveInfo.loadLabel(pm).toString();
             if (resolveInfo.isDefault)
                 ret[i * numAttr + 1] = "default";
             else
                 ret[i * numAttr + 1] = "";
             ret[i * numAttr + 2] = resolveInfo.activityInfo.applicationInfo.packageName;
             ret[i * numAttr + 3] = resolveInfo.activityInfo.name;
-            
         }
         return ret;
     }
 
-    static String[] getHandlersForProtocol(String aScheme) {
-        PackageManager pm = 
-            GeckoApp.surfaceView.getContext().getPackageManager();
-        Intent intent = new Intent();
-        Uri uri = new Uri.Builder().scheme(aScheme).build();
-        intent.setData(uri);
-        List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
-        int numAttr = 4;
-        String[] ret = new String[list.size() * numAttr];
-        for (int i = 0; i < list.size(); i++) {
-            ResolveInfo resolveInfo = list.get(i);
-                ret[i * numAttr] = resolveInfo.loadLabel(pm).toString();
-            if (resolveInfo.isDefault)
-                ret[i * numAttr + 1] = "default";
-            else
-                ret[i * numAttr + 1] = "";
-            ret[i * numAttr + 2] = resolveInfo.activityInfo.applicationInfo.packageName;
-            ret[i * numAttr + 3] = resolveInfo.activityInfo.name;
-
-        }
-        return ret;
+    static Intent getIntentForActionString(String aAction) {
+        // Default to the view action if no other action as been specified.
+        if (aAction != null && aAction.length() > 0)
+            return new Intent(aAction);
+        else
+            return new Intent(Intent.ACTION_VIEW);
     }
 
     static String getMimeTypeFromExtension(String aFileExt) {
         return android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(aFileExt);
     }
 
-    static boolean openUriExternal(String aUriSpec, String aMimeType, 
-                                   String aPackageName, String aClassName) {
-        // XXX: It's not clear if we should set the action to view or leave it open
-        Intent intent = new Intent(Intent.ACTION_VIEW);
-        if (aMimeType.length() > 0)
+    static boolean openUriExternal(String aUriSpec, String aMimeType, String aPackageName, 
+                                   String aClassName, String aAction) {
+        Intent intent = getIntentForActionString(aAction);
+        if (aAction.equalsIgnoreCase(Intent.ACTION_SEND)) {
+            intent.putExtra(Intent.EXTRA_TEXT, aUriSpec);
+            if (aMimeType != null && aMimeType.length() > 0)
+                intent.setType(aMimeType);
+        } else if (aMimeType.length() > 0) {
             intent.setDataAndType(Uri.parse(aUriSpec), aMimeType);
-        else
+        } else {
             intent.setData(Uri.parse(aUriSpec));
+        }
         if (aPackageName.length() > 0 && aClassName.length() > 0)
             intent.setClassName(aPackageName, aClassName);
 
         intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
         try {
             GeckoApp.surfaceView.getContext().startActivity(intent);
             return true;
         } catch(ActivityNotFoundException e) {
--- a/uriloader/exthandler/Makefile.in
+++ b/uriloader/exthandler/Makefile.in
@@ -101,16 +101,18 @@ endif
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 OSHELPER	+= nsGNOMERegistry.cpp
 OSHELPER  += nsMIMEInfoUnix.cpp
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),android)
 OSHELPER += nsMIMEInfoAndroid.cpp
 OSHELPER += nsAndroidHandlerApp.cpp
+OSHELPER += nsExternalSharingAppService.cpp
+EXPORTS += nsExternalSharingAppService.h
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
 OSHELPER += nsGNOMERegistry.cpp
 OSHELPER += nsMIMEInfoUnix.cpp
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
@@ -127,27 +129,29 @@ OSHELPER  += nsMIMEInfoOS2.cpp
 endif
 
 EXPORTS_NAMESPACES = mozilla/dom
 
 EXPORTS_mozilla/dom = \
     ExternalHelperAppParent.h \
     ExternalHelperAppChild.h
 
-EXPORTS = \
+EXPORTS += \
 		$(OSDIR)/nsOSHelperAppService.h \
+		nsExternalHelperAppService.h \
 		$(NULL)
 
 XPIDLSRCS = \
 	nsCExternalHandlerService.idl	\
 	nsIExternalProtocolService.idl \
 	nsIExternalHelperAppService.idl	\
 	nsIHelperAppLauncherDialog.idl \
 	nsIContentDispatchChooser.idl \
 	nsIHandlerService.idl	\
+	nsIExternalSharingAppService.idl \
 	$(NULL)
 
 CPPSRCS	= \
 	nsExternalHelperAppService.cpp	\
 	nsExternalProtocolHandler.cpp \
 	nsMIMEInfoImpl.cpp \
 	nsLocalHandlerApp.cpp \
 	$(OSHELPER) \
--- a/uriloader/exthandler/android/nsAndroidHandlerApp.cpp
+++ b/uriloader/exthandler/android/nsAndroidHandlerApp.cpp
@@ -34,70 +34,88 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsAndroidHandlerApp.h"
 #include "AndroidBridge.h"
 
 
-NS_IMPL_ISUPPORTS1(nsAndroidHandlerApp, nsIHandlerApp)
+NS_IMPL_ISUPPORTS1(nsAndroidHandlerApp, nsISharingHandlerApp)
 
 
 nsAndroidHandlerApp::nsAndroidHandlerApp(const nsAString& aName,
                                          const nsAString& aDescription,
                                          const nsAString& aPackageName,
                                          const nsAString& aClassName,
-                                         const nsACString& aMimeType) :
+                                         const nsACString& aMimeType,
+                                         const nsAString& aAction) :
 mName(aName), mDescription(aDescription), mPackageName(aPackageName),
-  mClassName(aClassName), mMimeType(aMimeType)
+  mClassName(aClassName), mMimeType(aMimeType), mAction(aAction)
 {
 }
 
 nsAndroidHandlerApp::~nsAndroidHandlerApp()
 {
 }
 
-nsresult nsAndroidHandlerApp::GetName(nsAString & aName)
+NS_IMETHODIMP
+nsAndroidHandlerApp::GetName(nsAString & aName)
 {
   aName.Assign(mName);
   return NS_OK;
 }
 
-nsresult nsAndroidHandlerApp::SetName(const nsAString & aName)
+NS_IMETHODIMP
+nsAndroidHandlerApp::SetName(const nsAString & aName)
 {
   mName.Assign(aName);
   return NS_OK;
 }
 
-nsresult nsAndroidHandlerApp::GetDetailedDescription(nsAString & aDescription)
+NS_IMETHODIMP
+nsAndroidHandlerApp::GetDetailedDescription(nsAString & aDescription)
 {
   aDescription.Assign(mDescription);
   return NS_OK;
 }
 
-nsresult nsAndroidHandlerApp::SetDetailedDescription(const nsAString & aDescription)
+NS_IMETHODIMP
+nsAndroidHandlerApp::SetDetailedDescription(const nsAString & aDescription)
 {
   mDescription.Assign(aDescription);
 
   return NS_OK;
 }
 
-nsresult nsAndroidHandlerApp::Equals(nsIHandlerApp *aHandlerApp, PRBool *aRetval)
+NS_IMETHODIMP
+nsAndroidHandlerApp::Equals(nsIHandlerApp *aHandlerApp, PRBool *aRetval)
 {
   nsCOMPtr<nsAndroidHandlerApp> aApp = do_QueryInterface(aHandlerApp);
   *aRetval = aApp && aApp->mName.Equals(mName) &&
     aApp->mDescription.Equals(mDescription);
   return NS_OK;
 }
 
-nsresult nsAndroidHandlerApp::LaunchWithURI(nsIURI *aURI, nsIInterfaceRequestor *aWindowContext)
+NS_IMETHODIMP
+nsAndroidHandlerApp::LaunchWithURI(nsIURI *aURI, nsIInterfaceRequestor *aWindowContext)
 {
   if (!mozilla::AndroidBridge::Bridge())
     return NS_ERROR_FAILURE;
 
   nsCString uriSpec;
   aURI->GetSpec(uriSpec);
   return mozilla::AndroidBridge::Bridge()->
-    OpenUriExternal(uriSpec, mMimeType, mPackageName, mClassName) ? 
+    OpenUriExternal(uriSpec, mMimeType, mPackageName, mClassName, mAction) ? 
     NS_OK : NS_ERROR_FAILURE;
+}
 
+NS_IMETHODIMP
+nsAndroidHandlerApp::Share(const nsAString & data, const nsAString & title)
+{
+  if (!mozilla::AndroidBridge::Bridge())
+    return NS_ERROR_FAILURE;
+
+  return mozilla::AndroidBridge::Bridge()->
+    OpenUriExternal(NS_ConvertUTF16toUTF8(data), mMimeType, mPackageName, 
+                    mClassName, mAction) ? NS_OK : NS_ERROR_FAILURE;
 }
+
--- a/uriloader/exthandler/android/nsAndroidHandlerApp.h
+++ b/uriloader/exthandler/android/nsAndroidHandlerApp.h
@@ -34,27 +34,32 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsAndroidHandlerApp_h
 #define nsAndroidHandlerApp_h
 
 #include "nsMIMEInfoImpl.h"
+#include "nsIExternalSharingAppService.h"
 
-class nsAndroidHandlerApp : public nsIHandlerApp {
+class nsAndroidHandlerApp : public nsISharingHandlerApp {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIHANDLERAPP
+    NS_DECL_NSISHARINGHANDLERAPP
+
     public:
     nsAndroidHandlerApp(const nsAString& aName, const nsAString& aDescription,
-                        const nsAString& aPackageName, const nsAString& aClassName, 
-                        const nsACString& aMimeType);
+                        const nsAString& aPackageName, 
+                        const nsAString& aClassName, 
+                        const nsACString& aMimeType, const nsAString& aAction);
     virtual ~nsAndroidHandlerApp();
 
 private:
     nsString mName;
     nsString mDescription;
     nsCString mMimeType;
     nsString mClassName;
     nsString mPackageName;
+    nsString mAction;
 };
 #endif
new file mode 100644
--- /dev/null
+++ b/uriloader/exthandler/android/nsExternalSharingAppService.cpp
@@ -0,0 +1,99 @@
+/* ***** 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 browser.
+ *
+ * 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):
+ *   Brad Lassey <blassey@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 "nsExternalSharingAppService.h"
+
+#include "mozilla/ModuleUtils.h"
+#include "nsIClassInfoImpl.h"
+
+#include "AndroidBridge.h"
+#include "nsArrayUtils.h"
+#include "nsISupportsUtils.h"
+#include "nsComponentManagerUtils.h"
+
+using namespace mozilla;
+
+NS_IMPL_ISUPPORTS1(nsExternalSharingAppService, nsIExternalSharingAppService)
+
+nsExternalSharingAppService::nsExternalSharingAppService()
+{
+}
+
+nsExternalSharingAppService::~nsExternalSharingAppService()
+{
+}
+
+NS_IMETHODIMP
+nsExternalSharingAppService::ShareWithDefault(const nsAString & data,
+                                              const nsAString & mime,
+                                              const nsAString & title)
+{
+  NS_NAMED_LITERAL_STRING(sendAction, "android.intent.action.SEND");
+  const nsString emptyString = EmptyString();
+  if (AndroidBridge::Bridge())
+    return AndroidBridge::Bridge()->
+      OpenUriExternal(NS_ConvertUTF16toUTF8(data), NS_ConvertUTF16toUTF8(mime),
+                      emptyString,emptyString, sendAction) ? NS_OK : NS_ERROR_FAILURE;
+
+  return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsExternalSharingAppService::GetSharingApps(const nsAString & aMIMEType,
+                                            PRUint32 *aLen NS_OUTPARAM,
+                                            nsISharingHandlerApp ***aHandlers NS_OUTPARAM)
+{
+  nsresult rv;
+  NS_NAMED_LITERAL_STRING(sendAction, "android.intent.action.SEND");
+  nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ConvertUTF16toUTF8 nMimeType(aMIMEType);
+  if (!AndroidBridge::Bridge())
+    return NS_OK;
+  AndroidBridge::Bridge()->GetHandlersForMimeType(nMimeType.get(), array,
+                                                  nsnull, sendAction);
+  array->GetLength(aLen);
+  *aHandlers =
+    static_cast<nsISharingHandlerApp**>(NS_Alloc(sizeof(nsISharingHandlerApp*)
+                                                 * *aLen));
+  for (int i = 0; i < *aLen; i++) {
+    rv = array->QueryElementAt(i, nsISharingHandlerApp::GetIID(),
+                               (void**)(*aHandlers + i));
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/uriloader/exthandler/android/nsExternalSharingAppService.h
@@ -0,0 +1,60 @@
+/* ***** 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 browser.
+ *
+ * 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):
+ *   Brad Lassey <blassey@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 NS_EXTERNAL_SHARING_APP_SERVICE_H
+#define NS_EXTERNAL_SHARING_APP_SERVICE_H
+#include "nsIExternalSharingAppService.h"
+
+
+#define NS_EXTERNALSHARINGAPPSERVICE_CID                \
+  {0x93e2c46e, 0x0011, 0x434b,                          \
+    {0x81, 0x2e, 0xb6, 0xf3, 0xa8, 0x1e, 0x2a, 0x58}}
+
+class nsExternalSharingAppService : public nsIExternalSharingAppService
+{
+public:
+  NS_DECL_ISUPPORTS
+    NS_DECL_NSIEXTERNALSHARINGAPPSERVICE
+
+    nsExternalSharingAppService();
+
+private:
+  ~nsExternalSharingAppService();
+
+};
+
+#endif /*NS_EXTERNAL_SHARING_APP_SERVICE_H */
--- a/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp
+++ b/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp
@@ -71,34 +71,30 @@ nsMIMEInfoAndroid::GetMimeInfoForMimeTyp
   nsRefPtr<nsMIMEInfoAndroid> info = new nsMIMEInfoAndroid(aMimeType);
   mozilla::AndroidBridge* bridge = mozilla::AndroidBridge::Bridge();
   // we don't have access to the bridge, so just assume we can handle
   // the mime type for now and let the system deal with it
   if (!bridge){
     info.forget(aMimeInfo);
     return PR_TRUE;
   }
-  nsStringArray stringArray;
-  bridge->GetHandlersForMimeType(nsCAutoString(aMimeType).get(), &stringArray);
 
-  nsString empty = EmptyString();
-  PRInt32 len = stringArray.Count();
-  if (len == 0) {
+  nsIHandlerApp* systemDefault = nsnull;
+  bridge->GetHandlersForMimeType(nsCAutoString(aMimeType).get(), 
+                                 info->mHandlerApps, &systemDefault);
+  
+  if (systemDefault)
+    info->mPrefApp = systemDefault;
+
+  PRUint32 len;
+  info->mHandlerApps->GetLength(&len);
+  if (len == 1) {
     info.forget(aMimeInfo);
     return PR_FALSE;
   }
-
-  for (jsize i = 0; i < len; i+=4) {
-    nsAndroidHandlerApp* app =
-      new nsAndroidHandlerApp(*stringArray[i], empty, *stringArray[i + 2],
-                              *stringArray[i + 3], aMimeType);
-    info->mHandlerApps->AppendElement(app, PR_FALSE);
-    if (stringArray[i + 1] > 0)
-      info->mPrefApp = app;
-  }
   
   info.forget(aMimeInfo);
   return PR_TRUE;
 }
   
 PRBool
 nsMIMEInfoAndroid::GetMimeInfoForFileExt(const nsACString& aFileExt,
                                          nsMIMEInfoAndroid **aMimeInfo)
@@ -110,49 +106,45 @@ nsMIMEInfoAndroid::GetMimeInfoForFileExt
   return GetMimeInfoForMimeType(mimeType, aMimeInfo);
 }
 
 nsresult
 nsMIMEInfoAndroid::GetMimeInfoForProtocol(const nsACString &aScheme,
                                           PRBool *found,
                                           nsIHandlerInfo **info)
 {
-  const nsString &empty = EmptyString();
   const nsCString &emptyC = EmptyCString();
   mozilla::AndroidBridge* bridge = mozilla::AndroidBridge::Bridge();
   nsMIMEInfoAndroid *mimeinfo = new nsMIMEInfoAndroid(emptyC);
   NS_ADDREF(*info = mimeinfo);
   *found = PR_TRUE;
   
   if (!bridge) {
     // we don't have access to the bridge, so just assume we can handle
     // the protocol for now and let the system deal with it
     return NS_OK;
   }
 
+  nsIHandlerApp* systemDefault = nsnull;
+  bridge->GetHandlersForProtocol(nsCAutoString(aScheme).get(), 
+                                 mimeinfo->mHandlerApps, &systemDefault);
+  
+  if (systemDefault)
+    mimeinfo->mPrefApp = systemDefault;
 
-  nsStringArray stringArray;
-  bridge->GetHandlersForProtocol(nsCAutoString(aScheme).get(), &stringArray);
 
-  PRInt32 len = stringArray.Count();
-  if (len == 0) {
+  PRUint32 len;
+  mimeinfo->mHandlerApps->GetLength(&len);
+  if (len == 1) {
     // Code that calls this requires an object regardless if the OS has
     // something for us, so we return the empty object.
     *found = PR_FALSE;
     return NS_OK;
   }
   
-  for (jsize i = 0; i < len; i+=4) {
-    nsAndroidHandlerApp* app =
-      new nsAndroidHandlerApp(*stringArray[i], empty, *stringArray[i + 2],
-                              *stringArray[i + 3], emptyC);
-    mimeinfo->mHandlerApps->AppendElement(app, PR_FALSE);
-    if (!stringArray[i + 1]->IsEmpty())
-      mimeinfo->mPrefApp = app;
-  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMIMEInfoAndroid::GetType(nsACString& aType)
 {
   aType.Assign(mMimeType);
   return NS_OK;
--- a/uriloader/exthandler/android/nsOSHelperAppService.cpp
+++ b/uriloader/exthandler/android/nsOSHelperAppService.cpp
@@ -81,8 +81,19 @@ nsOSHelperAppService::OSProtocolHandlerE
 
 nsresult nsOSHelperAppService::GetProtocolHandlerInfoFromOS(const nsACString &aScheme,
                                       PRBool *found,
                                       nsIHandlerInfo **info)
 {
     return nsMIMEInfoAndroid::GetMimeInfoForProtocol(aScheme, found, info);
 }
 
+nsIHandlerApp*
+nsOSHelperAppService::CreateAndroidHandlerApp(const nsAString& aName,
+                                              const nsAString& aDescription,
+                                              const nsAString& aPackageName,
+                                              const nsAString& aClassName, 
+                                              const nsACString& aMimeType,
+                                              const nsAString& aAction)
+{
+    return new nsAndroidHandlerApp(aName, aDescription, aPackageName,
+                                   aClassName, aMimeType, aAction);
+}
--- a/uriloader/exthandler/android/nsOSHelperAppService.h
+++ b/uriloader/exthandler/android/nsOSHelperAppService.h
@@ -55,12 +55,18 @@ public:
     virtual NS_HIDDEN_(nsresult)
     OSProtocolHandlerExists(const char* aScheme,
                             PRBool* aExists);
 
     NS_IMETHOD GetProtocolHandlerInfoFromOS(const nsACString &aScheme,
                                             PRBool *found,
                                             nsIHandlerInfo **_retval);
 
-
+    static nsIHandlerApp*
+    CreateAndroidHandlerApp(const nsAString& aName,
+                            const nsAString& aDescription,
+                            const nsAString& aPackageName,
+                            const nsAString& aClassName, 
+                            const nsACString& aMimeType,
+                            const nsAString& aAction = EmptyString());
 };
 
 #endif /* nsOSHelperAppService_h */
--- a/uriloader/exthandler/beos/nsOSHelperAppService.h
+++ b/uriloader/exthandler/beos/nsOSHelperAppService.h
@@ -38,16 +38,17 @@
 #define nsOSHelperAppService_h__
 
 // The OS helper app service is a subclass of nsExternalHelperAppService and is implemented on each
 // platform. It contains platform specific code for finding helper applications for a given mime type
 // in addition to launching those applications.
 
 #include "nsExternalHelperAppService.h"
 #include "nsCExternalHandlerService.h"
+#include "nsMIMEInfoImpl.h"
 #include "nsCOMPtr.h"
 
 class nsMIMEInfoBeOS;
 
 class nsOSHelperAppService : public nsExternalHelperAppService
 {
 public:
 	nsOSHelperAppService();
--- a/uriloader/exthandler/mac/nsOSHelperAppService.h
+++ b/uriloader/exthandler/mac/nsOSHelperAppService.h
@@ -43,16 +43,17 @@
 #define nsOSHelperAppService_h__
 
 // The OS helper app service is a subclass of nsExternalHelperAppService and is implemented on each
 // platform. It contains platform specific code for finding helper applications for a given mime type
 // in addition to launching those applications. This is the Mac version.
 
 #include "nsExternalHelperAppService.h"
 #include "nsCExternalHandlerService.h"
+#include "nsMIMEInfoImpl.h"
 #include "nsCOMPtr.h"
 
 class nsOSHelperAppService : public nsExternalHelperAppService
 {
 public:
   nsOSHelperAppService();
   virtual ~nsOSHelperAppService();
 
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -143,16 +143,20 @@
 #include "ContentChild.h"
 #include "nsXULAppAPI.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDocShellTreeItem.h"
 #include "ExternalHelperAppChild.h"
 #endif
 
+#ifdef ANDROID
+#include "AndroidBridge.h"
+#endif
+
 // Buffer file writes in 32kb chunks
 #define BUFFERED_OUTPUT_SIZE (1024 * 32)
 
 // Download Folder location constants
 #define NS_PREF_DOWNLOAD_DIR        "browser.download.dir"
 #define NS_PREF_DOWNLOAD_FOLDERLIST "browser.download.folderList"
 enum {
   NS_FOLDER_VALUE_DESKTOP = 0
--- a/uriloader/exthandler/nsExternalHelperAppService.h
+++ b/uriloader/exthandler/nsExternalHelperAppService.h
@@ -52,17 +52,16 @@
 #include "nsInt64.h"
 
 #include "nsIExternalHelperAppService.h"
 #include "nsIExternalProtocolService.h"
 #include "nsIWebProgressListener2.h"
 #include "nsIHelperAppLauncherDialog.h"
 
 #include "nsIMIMEInfo.h"
-#include "nsMIMEInfoImpl.h"
 #include "nsIMIMEService.h"
 #include "nsIStreamListener.h"
 #include "nsIFile.h"
 #include "nsIFileStreams.h"
 #include "nsIOutputStream.h"
 #include "nsString.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
new file mode 100644
--- /dev/null
+++ b/uriloader/exthandler/nsIExternalSharingAppService.idl
@@ -0,0 +1,62 @@
+/* ***** 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 browser.
+ *
+ * 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):
+ *   Brad Lassey <blassey@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 "nsIMIMEInfo.idl"
+
+%{C++
+#define NS_EXTERNALSHARINGAPPSERVICE_CONTRACTID    "@mozilla.org/uriloader/external-sharing-app-service;1"
+#define NS_IEXTERNALSHARINGAPPSERVICE_CLASSNAME "Mozilla Sharing App Service"
+%}
+
+
+[scriptable, uuid(7111f769-53ec-41fd-b314-613661d5b6ba)]
+interface nsISharingHandlerApp : nsIHandlerApp
+{
+  void share(in AString data, [optional] in AString title);
+};
+
+[scriptable, uuid(cf7d04e5-3892-482e-81bb-073dc1c83f76)]
+interface nsIExternalSharingAppService : nsISupports {
+  void shareWithDefault(in AString data, in AString mime, 
+			[optional] in AString title);
+  
+  void getSharingApps(in AString aMIMEType, 
+		      [optional] out unsigned long aLen,
+		      [array, size_is(aLen), retval] out nsISharingHandlerApp handlerApps);
+};
+
+
--- a/uriloader/exthandler/os2/nsOSHelperAppService.h
+++ b/uriloader/exthandler/os2/nsOSHelperAppService.h
@@ -42,16 +42,17 @@
 #define nsOSHelperAppService_h__
 
 // The OS helper app service is a subclass of nsExternalHelperAppService and is implemented on each
 // platform. It contains platform specific code for finding helper applications for a given mime type
 // in addition to launching those applications.
 
 #include "nsExternalHelperAppService.h"
 #include "nsCExternalHandlerService.h"
+#include "nsMIMEInfoImpl.h"
 #include "nsCOMPtr.h"
 
 #define LOG(args) PR_LOG(mLog, PR_LOG_DEBUG, args)
 #define LOG_ENABLED() PR_LOG_TEST(mLog, PR_LOG_DEBUG)
 
 class nsHashtable;
 class nsILineInputStream;
 class nsMIMEInfoOS2;
--- a/uriloader/exthandler/unix/nsOSHelperAppService.h
+++ b/uriloader/exthandler/unix/nsOSHelperAppService.h
@@ -42,16 +42,17 @@
 #define nsOSHelperAppService_h__
 
 // The OS helper app service is a subclass of nsExternalHelperAppService and is implemented on each
 // platform. It contains platform specific code for finding helper applications for a given mime type
 // in addition to launching those applications.
 
 #include "nsExternalHelperAppService.h"
 #include "nsCExternalHandlerService.h"
+#include "nsMIMEInfoImpl.h"
 #include "nsCOMPtr.h"
 
 class nsHashtable;
 class nsILineInputStream;
 
 class nsOSHelperAppService : public nsExternalHelperAppService
 {
 public:
--- a/uriloader/exthandler/win/nsOSHelperAppService.h
+++ b/uriloader/exthandler/win/nsOSHelperAppService.h
@@ -40,16 +40,17 @@
 #define nsOSHelperAppService_h__
 
 // The OS helper app service is a subclass of nsExternalHelperAppService and is implemented on each
 // platform. It contains platform specific code for finding helper applications for a given mime type
 // in addition to launching those applications.
 
 #include "nsExternalHelperAppService.h"
 #include "nsCExternalHandlerService.h"
+#include "nsMIMEInfoImpl.h"
 #include "nsCOMPtr.h"
 #include <windows.h>
 
 #ifdef _WIN32_WINNT
 #undef _WIN32_WINNT
 #endif
 #define _WIN32_WINNT 0x0600
 #define INITGUID
--- a/widget/src/android/AndroidBridge.cpp
+++ b/widget/src/android/AndroidBridge.cpp
@@ -41,16 +41,17 @@
 #include "nsXULAppAPI.h"
 #endif
 #include <pthread.h>
 #include <prthread.h>
 #include "nsXPCOMStrings.h"
 
 #include "AndroidBridge.h"
 #include "nsAppShell.h"
+#include "nsOSHelperAppService.h"
 
 using namespace mozilla;
 
 static PRUintn sJavaEnvThreadIndex = 0;
 
 AndroidBridge *AndroidBridge::sBridge = 0;
 
 static void
@@ -98,19 +99,19 @@ AndroidBridge::Init(JNIEnv *jEnv,
 
     jNotifyIME = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyIME", "(II)V");
     jNotifyIMEChange = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyIMEChange", "(Ljava/lang/String;III)V");
     jEnableAccelerometer = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableAccelerometer", "(Z)V");
     jEnableLocation = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableLocation", "(Z)V");
     jReturnIMEQueryResult = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "returnIMEQueryResult", "(Ljava/lang/String;II)V");
     jScheduleRestart = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "scheduleRestart", "()V");
     jNotifyXreExit = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "onXreExit", "()V");
-    jGetHandlersForMimeType = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getHandlersForMimeType", "(Ljava/lang/String;)[Ljava/lang/String;");
-    jGetHandlersForProtocol = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getHandlersForProtocol", "(Ljava/lang/String;)[Ljava/lang/String;");
-    jOpenUriExternal = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "openUriExternal", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z");
+    jGetHandlersForMimeType = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getHandlersForMimeType", "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;");
+    jGetHandlersForProtocol = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getHandlersForProtocol", "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;");
+    jOpenUriExternal = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "openUriExternal", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z");
     jGetMimeTypeFromExtension = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getMimeTypeFromExtension", "(Ljava/lang/String;)Ljava/lang/String;");
     jMoveTaskToBack = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "moveTaskToBack", "()V");
     jGetClipboardText = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getClipboardText", "()Ljava/lang/String;");
     jSetClipboardText = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setClipboardText", "(Ljava/lang/String;)V");
     jShowAlertNotification = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showAlertNotification", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
     jShowFilePicker = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showFilePicker", "()Ljava/lang/String;");
 
 
@@ -253,91 +254,130 @@ AndroidBridge::ScheduleRestart()
 
 void
 AndroidBridge::NotifyXreExit()
 {
     ALOG("xre exiting");
     mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jNotifyXreExit);
 }
 
+static void 
+getHandlersFromStringArray(JNIEnv *aJNIEnv, jobjectArray jArr, jsize aLen,
+                           nsIMutableArray *aHandlersArray,
+                           nsIHandlerApp **aDefaultApp,
+                           const nsAString& aAction = EmptyString(),
+                           const nsACString& aMimeType = EmptyCString())
+{
+    nsString empty = EmptyString();
+    for (jsize i = 0; i < aLen; i+=4) {
+        nsJNIString name( 
+            static_cast<jstring>(aJNIEnv->GetObjectArrayElement(jArr, i)));
+        nsJNIString isDefault(
+            static_cast<jstring>(aJNIEnv->GetObjectArrayElement(jArr, i + 1)));
+        nsJNIString packageName( 
+            static_cast<jstring>(aJNIEnv->GetObjectArrayElement(jArr, i + 2)));
+        nsJNIString className( 
+            static_cast<jstring>(aJNIEnv->GetObjectArrayElement(jArr, i + 3)));
+        nsIHandlerApp* app = nsOSHelperAppService::
+            CreateAndroidHandlerApp(name, className, packageName,
+                                    className, aMimeType, aAction);
+        
+        aHandlersArray->AppendElement(app, PR_FALSE);
+        if (aDefaultApp && isDefault.Length() > 0)
+            *aDefaultApp = app;
+    }
+}
+
 PRBool
-AndroidBridge::GetHandlersForMimeType(const char *aMimeType, nsStringArray* aStringArray)
+AndroidBridge::GetHandlersForMimeType(const char *aMimeType,
+                                      nsIMutableArray *aHandlersArray,
+                                      nsIHandlerApp **aDefaultApp,
+                                      const nsAString& aAction)
 {
-    NS_PRECONDITION(aStringArray != nsnull, "null array pointer passed in");
     AutoLocalJNIFrame jniFrame;
     NS_ConvertUTF8toUTF16 wMimeType(aMimeType);
-    jstring jstr = mJNIEnv->NewString(wMimeType.get(), wMimeType.Length());
+    jstring jstrMimeType =
+        mJNIEnv->NewString(wMimeType.get(), wMimeType.Length());
+    const PRUnichar* wAction;
+    PRUint32 actionLen = NS_StringGetData(aAction, &wAction);
+    jstring jstrAction = mJNIEnv->NewString(wAction, actionLen);
+
     jobject obj = mJNIEnv->CallStaticObjectMethod(mGeckoAppShellClass,
                                                   jGetHandlersForMimeType,
-                                                  jstr);
+                                                  jstrMimeType, jstrAction);
     jobjectArray arr = static_cast<jobjectArray>(obj);
     if (!arr)
         return PR_FALSE;
 
     jsize len = mJNIEnv->GetArrayLength(arr);
 
-    if (!aStringArray)
+    if (!aHandlersArray)
         return len > 0;
 
-    for (jsize i = 0; i < len; i++) {
-        jstring jstr = static_cast<jstring>(mJNIEnv->GetObjectArrayElement(arr, i));
-        nsJNIString jniStr(jstr);
-        aStringArray->InsertStringAt(jniStr, i);
-    }
-
+    getHandlersFromStringArray(mJNIEnv, arr, len, aHandlersArray, 
+                               aDefaultApp, aAction,
+                               nsDependentCString(aMimeType));
     return PR_TRUE;
 }
 
 PRBool
-AndroidBridge::GetHandlersForProtocol(const char *aScheme, nsStringArray* aStringArray)
+AndroidBridge::GetHandlersForProtocol(const char *aScheme,
+                                      nsIMutableArray* aHandlersArray,
+                                      nsIHandlerApp **aDefaultApp,
+                                      const nsAString& aAction)
 {
-    NS_PRECONDITION(aStringArray != nsnull, "null array pointer passed in");
     AutoLocalJNIFrame jniFrame;
     NS_ConvertUTF8toUTF16 wScheme(aScheme);
-    jstring jstr = mJNIEnv->NewString(wScheme.get(), wScheme.Length());
+    jstring jstrScheme = mJNIEnv->NewString(wScheme.get(), wScheme.Length());
+    const PRUnichar* wAction;
+    PRUint32 actionLen = NS_StringGetData(aAction, &wAction);
+    jstring jstrAction = mJNIEnv->NewString(wAction, actionLen);
+
     jobject obj = mJNIEnv->CallStaticObjectMethod(mGeckoAppShellClass,
                                                   jGetHandlersForProtocol,
-                                                  jstr);
+                                                  jstrScheme, jstrAction);
     jobjectArray arr = static_cast<jobjectArray>(obj);
     if (!arr)
         return PR_FALSE;
 
     jsize len = mJNIEnv->GetArrayLength(arr);
 
-    if (!aStringArray)
+    if (!aHandlersArray)
         return len > 0;
 
-    for (jsize i = 0; i < len; i++) {
-        jstring jstr = static_cast<jstring>(mJNIEnv->GetObjectArrayElement(arr, i));
-        nsJNIString jniStr(jstr);
-        aStringArray->InsertStringAt(jniStr, i);
-    }
-
+    getHandlersFromStringArray(mJNIEnv, arr, len, aHandlersArray, 
+                               aDefaultApp, aAction);
     return PR_TRUE;
 }
 
 PRBool
 AndroidBridge::OpenUriExternal(const nsACString& aUriSpec, const nsACString& aMimeType,
-                               const nsAString& aPackageName, const nsAString& aClassName)
+                               const nsAString& aPackageName, const nsAString& aClassName,
+                               const nsAString& aAction)
 {
     AutoLocalJNIFrame jniFrame;
     NS_ConvertUTF8toUTF16 wUriSpec(aUriSpec);
     NS_ConvertUTF8toUTF16 wMimeType(aMimeType);
     const PRUnichar* wPackageName;
     PRUint32 packageNameLen = NS_StringGetData(aPackageName, &wPackageName);
     const PRUnichar* wClassName;
     PRUint32 classNameLen = NS_StringGetData(aClassName, &wClassName);
+    const PRUnichar* wAction;
+    PRUint32 actionLen = NS_StringGetData(aAction, &wAction);
 
     jstring jstrUri = mJNIEnv->NewString(wUriSpec.get(), wUriSpec.Length());
     jstring jstrType = mJNIEnv->NewString(wMimeType.get(), wMimeType.Length());
     jstring jstrPackage = mJNIEnv->NewString(wPackageName, packageNameLen);
     jstring jstrClass = mJNIEnv->NewString(wClassName, classNameLen);
+    jstring jstrAction = mJNIEnv->NewString(wAction, actionLen);
+
     return mJNIEnv->CallStaticBooleanMethod(mGeckoAppShellClass,
                                             jOpenUriExternal,
-                                            jstrUri, jstrType, jstrPackage, jstrClass);
+                                            jstrUri, jstrType, jstrPackage, 
+                                            jstrClass, jstrAction);
 }
 
 void
 AndroidBridge::GetMimeTypeFromExtension(const nsACString& aFileExt, nsCString& aMimeType) {
     AutoLocalJNIFrame jniFrame;
     NS_ConvertUTF8toUTF16 wFileExt(aFileExt);
     jstring jstrExt = mJNIEnv->NewString(wFileExt.get(), wFileExt.Length());
     jstring jstrType =  static_cast<jstring>(mJNIEnv->CallStaticObjectMethod(mGeckoAppShellClass,
--- a/widget/src/android/AndroidBridge.h
+++ b/widget/src/android/AndroidBridge.h
@@ -42,17 +42,18 @@
 #include <android/log.h>
 
 #include "nsCOMPtr.h"
 #include "nsIRunnable.h"
 #include "nsIObserver.h"
 
 #include "AndroidJavaWrappers.h"
 
-#include "nsVoidArray.h"
+#include "nsIMutableArray.h"
+#include "nsIMIMEInfo.h"
 
 // Some debug #defines
 // #define ANDROID_DEBUG_EVENTS
 // #define ANDROID_DEBUG_WIDGET
 
 class nsWindow;
 
 namespace mozilla {
@@ -112,23 +113,30 @@ public:
 
     void NotifyXreExit();
 
     void ScheduleRestart();
 
     void SetSurfaceView(jobject jobj);
     AndroidGeckoSurfaceView& SurfaceView() { return mSurfaceView; }
 
-    PRBool GetHandlersForProtocol(const char *aScheme, nsStringArray* aStringArray = nsnull);
+    PRBool GetHandlersForProtocol(const char *aScheme, 
+                                  nsIMutableArray* handlersArray = nsnull,
+                                  nsIHandlerApp **aDefaultApp = nsnull,
+                                  const nsAString& aAction = EmptyString());
 
-    PRBool GetHandlersForMimeType(const char *aMimeType, nsStringArray* aStringArray = nsnull);
+    PRBool GetHandlersForMimeType(const char *aMimeType,
+                                  nsIMutableArray* handlersArray = nsnull,
+                                  nsIHandlerApp **aDefaultApp = nsnull,
+                                  const nsAString& aAction = EmptyString());
 
     PRBool OpenUriExternal(const nsACString& aUriSpec, const nsACString& aMimeType, 
                            const nsAString& aPackageName = EmptyString(), 
-                           const nsAString& aClassName = EmptyString());
+                           const nsAString& aClassName = EmptyString(),
+                           const nsAString& aAction = EmptyString());
 
     void GetMimeTypeFromExtension(const nsACString& aFileExt, nsCString& aMimeType);
 
     void MoveTaskToBack();
 
     bool GetClipboardText(nsAString& aText);
 
     void SetClipboardText(const nsAString& aText);