mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 575750 - Implement support for OS protocol handlers on Android [r=mwu,bzbarsky]
--HG-- extra : rebase_source : 00c00eff847686211b07798f8d837e7bde02b89d
This commit is contained in:
parent
0ac9763118
commit
3bcc160167
@ -57,7 +57,7 @@ import android.util.*;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
class GeckoAppShell
|
||||
{
|
||||
@ -362,14 +362,41 @@ class GeckoAppShell
|
||||
Intent intent = new Intent();
|
||||
intent.setType(aMimeType);
|
||||
List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
|
||||
int numAttr = 2;
|
||||
int numAttr = 4;
|
||||
String[] ret = new String[list.size() * numAttr];
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
ret[i * numAttr] = list.get(i).loadLabel(pm).toString();
|
||||
if (list.get(i).isDefault)
|
||||
ret[i * numAttr + 1] = "default";
|
||||
else
|
||||
ret[i * numAttr + 1] = "";
|
||||
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;
|
||||
}
|
||||
@ -378,10 +405,17 @@ class GeckoAppShell
|
||||
return android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(aFileExt);
|
||||
}
|
||||
|
||||
static boolean openUriExternal(String aUriSpec, String aMimeType) {
|
||||
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);
|
||||
intent.setDataAndType(android.net.Uri.parse(aUriSpec), aMimeType);
|
||||
if (aMimeType.length() > 0)
|
||||
intent.setDataAndType(Uri.parse(aUriSpec), aMimeType);
|
||||
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);
|
||||
|
@ -36,13 +36,19 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsAndroidHandlerApp.h"
|
||||
#include "AndroidBridge.h"
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsAndroidHandlerApp, nsIHandlerApp)
|
||||
|
||||
|
||||
nsAndroidHandlerApp::nsAndroidHandlerApp(nsAString& aName,
|
||||
nsAString& aDescription) :
|
||||
mName(aName), mDescription(aDescription)
|
||||
nsAndroidHandlerApp::nsAndroidHandlerApp(const nsAString& aName,
|
||||
const nsAString& aDescription,
|
||||
const nsAString& aPackageName,
|
||||
const nsAString& aClassName,
|
||||
const nsACString& aMimeType) :
|
||||
mName(aName), mDescription(aDescription), mPackageName(aPackageName),
|
||||
mClassName(aClassName), mMimeType(aMimeType)
|
||||
{
|
||||
}
|
||||
|
||||
@ -85,6 +91,10 @@ nsresult nsAndroidHandlerApp::Equals(nsIHandlerApp *aHandlerApp, PRBool *aRetval
|
||||
|
||||
nsresult nsAndroidHandlerApp::LaunchWithURI(nsIURI *aURI, nsIInterfaceRequestor *aWindowContext)
|
||||
{
|
||||
// XXX: need implementation
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
nsCString uriSpec;
|
||||
aURI->GetSpec(uriSpec);
|
||||
return mozilla::AndroidBridge::Bridge()->
|
||||
OpenUriExternal(uriSpec, mMimeType, mPackageName, mClassName) ?
|
||||
NS_OK : NS_ERROR_FAILURE;
|
||||
|
||||
}
|
||||
|
@ -45,12 +45,16 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIHANDLERAPP
|
||||
public:
|
||||
nsAndroidHandlerApp(nsAString& aName, nsAString& aDescription);
|
||||
nsAndroidHandlerApp(const nsAString& aName, const nsAString& aDescription,
|
||||
const nsAString& aPackageName, const nsAString& aClassName,
|
||||
const nsACString& aMimeType);
|
||||
virtual ~nsAndroidHandlerApp();
|
||||
|
||||
private:
|
||||
nsString mName;
|
||||
nsString mDescription;
|
||||
|
||||
nsCString mMimeType;
|
||||
nsString mClassName;
|
||||
nsString mPackageName;
|
||||
};
|
||||
#endif
|
||||
|
@ -76,8 +76,10 @@ nsMIMEInfoAndroid::GetMimeInfoForMimeType(const nsACString& aMimeType)
|
||||
if (len == 0)
|
||||
return nsnull;
|
||||
nsCOMPtr<nsMIMEInfoAndroid> info = new nsMIMEInfoAndroid(aMimeType);
|
||||
for (jsize i = 0; i < len; i+=2) {
|
||||
nsAndroidHandlerApp* app = new nsAndroidHandlerApp(*stringArray[i], empty);
|
||||
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;
|
||||
@ -95,6 +97,37 @@ nsMIMEInfoAndroid::GetMimeInfoForFileExt(const nsACString& aFileExt)
|
||||
return GetMimeInfoForMimeType(mimeType);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMIMEInfoAndroid::GetMimeInfoForProtocol(const nsACString &aScheme,
|
||||
PRBool *found,
|
||||
nsIHandlerInfo **info)
|
||||
{
|
||||
mozilla::AndroidBridge* bridge = mozilla::AndroidBridge::Bridge();
|
||||
nsStringArray stringArray;
|
||||
bridge->GetHandlersForProtocol(nsCAutoString(aScheme).get(), &stringArray);
|
||||
|
||||
const nsString &empty = EmptyString();
|
||||
const nsCString &emptyC = EmptyCString();
|
||||
PRInt32 len = stringArray.Count();
|
||||
if (len == 0) {
|
||||
*found = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
*found = PR_TRUE;
|
||||
nsMIMEInfoAndroid *mimeinfo = new nsMIMEInfoAndroid(emptyC);
|
||||
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;
|
||||
}
|
||||
}
|
||||
*info = mimeinfo;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMIMEInfoAndroid::GetType(nsACString& aType)
|
||||
{
|
||||
@ -197,7 +230,9 @@ nsMIMEInfoAndroid::SetPreferredAction(nsHandlerInfoAction aPrefAction)
|
||||
NS_IMETHODIMP
|
||||
nsMIMEInfoAndroid::GetAlwaysAskBeforeHandling(PRBool* aAlwaysAsk)
|
||||
{
|
||||
*aAlwaysAsk = mAlwaysAsk;
|
||||
// the chooser dialog currently causes a crash on Android, avoid this by returning false here
|
||||
// but be sure to return mAlwaysAsk when that gets fixed (bug 584896)
|
||||
*aAlwaysAsk = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -328,8 +363,8 @@ nsMIMEInfoAndroid::LaunchWithFile(nsIFile *aFile)
|
||||
}
|
||||
|
||||
nsMIMEInfoAndroid::nsMIMEInfoAndroid(const nsACString& aMIMEType) :
|
||||
mMimeType(aMIMEType), mAlwaysAsk(PR_TRUE),
|
||||
mPrefAction(nsIMIMEInfo::useHelperApp),
|
||||
mMimeType(aMIMEType), mAlwaysAsk(PR_TRUE),
|
||||
mPrefAction(nsIMIMEInfo::useHelperApp),
|
||||
mSystemChooser(this)
|
||||
{
|
||||
mPrefApp = &mSystemChooser;
|
||||
|
@ -46,6 +46,9 @@ class nsMIMEInfoAndroid : public nsIMIMEInfo
|
||||
public:
|
||||
static already_AddRefed<nsIMIMEInfo> GetMimeInfoForMimeType(const nsACString& aMimeType);
|
||||
static already_AddRefed<nsIMIMEInfo> GetMimeInfoForFileExt(const nsACString& aFileExt);
|
||||
static nsresult GetMimeInfoForProtocol(const nsACString &aScheme,
|
||||
PRBool *found,
|
||||
nsIHandlerInfo **info);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMIMEINFO
|
||||
|
@ -71,6 +71,14 @@ nsresult
|
||||
nsOSHelperAppService::OSProtocolHandlerExists(const char* aScheme,
|
||||
PRBool* aExists)
|
||||
{
|
||||
*aExists = PR_FALSE;
|
||||
*aExists = mozilla::AndroidBridge::Bridge()->GetHandlersForProtocol(aScheme);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsOSHelperAppService::GetProtocolHandlerInfoFromOS(const nsACString &aScheme,
|
||||
PRBool *found,
|
||||
nsIHandlerInfo **info)
|
||||
{
|
||||
return nsMIMEInfoAndroid::GetMimeInfoForProtocol(aScheme, found, info);
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,12 @@ public:
|
||||
virtual NS_HIDDEN_(nsresult)
|
||||
OSProtocolHandlerExists(const char* aScheme,
|
||||
PRBool* aExists);
|
||||
|
||||
NS_IMETHOD GetProtocolHandlerInfoFromOS(const nsACString &aScheme,
|
||||
PRBool *found,
|
||||
nsIHandlerInfo **_retval);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* nsOSHelperAppService_h */
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include <pthread.h>
|
||||
#include <prthread.h>
|
||||
#include "nsXPCOMStrings.h"
|
||||
|
||||
#include "AndroidBridge.h"
|
||||
|
||||
@ -100,7 +101,8 @@ AndroidBridge::Init(JNIEnv *jEnv,
|
||||
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;");
|
||||
jOpenUriExternal = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "openUriExternal", "(Ljava/lang/String;Ljava/lang/String;)Z");
|
||||
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");
|
||||
jGetMimeTypeFromExtension = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getMimeTypeFromExtension", "(Ljava/lang/String;)Ljava/lang/String;");
|
||||
jMoveTaskToBack = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "moveTaskToBack", "()V");
|
||||
|
||||
@ -254,38 +256,81 @@ AndroidBridge::NotifyXreExit()
|
||||
mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jNotifyXreExit);
|
||||
}
|
||||
|
||||
void
|
||||
PRBool
|
||||
AndroidBridge::GetHandlersForMimeType(const char *aMimeType, nsStringArray* aStringArray)
|
||||
{
|
||||
NS_PRECONDITION(aStringArray != nsnull, "null array pointer passed in");
|
||||
AutoLocalJNIFrame jniFrame;
|
||||
NS_ConvertUTF8toUTF16 wMimeType(aMimeType);
|
||||
jstring jstr = mJNIEnv->NewString(wMimeType.get(), wMimeType.Length());
|
||||
jobject obj = mJNIEnv->CallStaticObjectMethod(mGeckoAppShellClass,
|
||||
jGetHandlersForMimeType,
|
||||
jobject obj = mJNIEnv->CallStaticObjectMethod(mGeckoAppShellClass,
|
||||
jGetHandlersForMimeType,
|
||||
jstr);
|
||||
jobjectArray arr = static_cast<jobjectArray>(obj);
|
||||
if (!arr)
|
||||
return;
|
||||
return PR_FALSE;
|
||||
|
||||
jsize len = mJNIEnv->GetArrayLength(arr);
|
||||
for (jsize i = 0; i < len; i+=2) {
|
||||
|
||||
if (!aStringArray)
|
||||
return len > 0;
|
||||
|
||||
for (jsize i = 0; i < len; i++) {
|
||||
jstring jstr = static_cast<jstring>(mJNIEnv->GetObjectArrayElement(arr, i));
|
||||
nsJNIString jniStr(jstr);
|
||||
aStringArray->AppendString(jniStr);
|
||||
}
|
||||
aStringArray->InsertStringAt(jniStr, i);
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
AndroidBridge::OpenUriExternal(nsCString& aUriSpec, nsCString& aMimeType)
|
||||
AndroidBridge::GetHandlersForProtocol(const char *aScheme, nsStringArray* aStringArray)
|
||||
{
|
||||
NS_PRECONDITION(aStringArray != nsnull, "null array pointer passed in");
|
||||
AutoLocalJNIFrame jniFrame;
|
||||
NS_ConvertUTF8toUTF16 wScheme(aScheme);
|
||||
jstring jstr = mJNIEnv->NewString(wScheme.get(), wScheme.Length());
|
||||
jobject obj = mJNIEnv->CallStaticObjectMethod(mGeckoAppShellClass,
|
||||
jGetHandlersForProtocol,
|
||||
jstr);
|
||||
jobjectArray arr = static_cast<jobjectArray>(obj);
|
||||
if (!arr)
|
||||
return PR_FALSE;
|
||||
|
||||
jsize len = mJNIEnv->GetArrayLength(arr);
|
||||
|
||||
if (!aStringArray)
|
||||
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);
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
AndroidBridge::OpenUriExternal(const nsACString& aUriSpec, const nsACString& aMimeType,
|
||||
const nsAString& aPackageName, const nsAString& aClassName)
|
||||
{
|
||||
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);
|
||||
|
||||
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);
|
||||
return mJNIEnv->CallStaticBooleanMethod(mGeckoAppShellClass,
|
||||
jOpenUriExternal,
|
||||
jstrUri, jstrType);
|
||||
jstrUri, jstrType, jstrPackage, jstrClass);
|
||||
}
|
||||
|
||||
void
|
||||
@ -377,5 +422,5 @@ mozilla_AndroidBridge_AttachThread(PRBool asDaemon)
|
||||
|
||||
extern "C" JNIEnv * GetJNIForThread()
|
||||
{
|
||||
return mozilla::AndroidBridge::JNIForThread();
|
||||
return mozilla::AndroidBridge::JNIForThread();
|
||||
}
|
||||
|
@ -114,9 +114,13 @@ public:
|
||||
void SetSurfaceView(jobject jobj);
|
||||
AndroidGeckoSurfaceView& SurfaceView() { return mSurfaceView; }
|
||||
|
||||
void GetHandlersForMimeType(const char *aMimeType, nsStringArray* aStringArray);
|
||||
PRBool GetHandlersForProtocol(const char *aScheme, nsStringArray* aStringArray = nsnull);
|
||||
|
||||
PRBool OpenUriExternal(nsCString& aUriSpec, nsCString& aMimeType);
|
||||
PRBool GetHandlersForMimeType(const char *aMimeType, nsStringArray* aStringArray = nsnull);
|
||||
|
||||
PRBool OpenUriExternal(const nsACString& aUriSpec, const nsACString& aMimeType,
|
||||
const nsAString& aPackageName = EmptyString(),
|
||||
const nsAString& aClassName = EmptyString());
|
||||
|
||||
void GetMimeTypeFromExtension(const nsCString& aFileExt, nsCString& aMimeType);
|
||||
|
||||
@ -173,6 +177,7 @@ protected:
|
||||
jmethodID jScheduleRestart;
|
||||
jmethodID jGetOutstandingDrawEvents;
|
||||
jmethodID jGetHandlersForMimeType;
|
||||
jmethodID jGetHandlersForProtocol;
|
||||
jmethodID jOpenUriExternal;
|
||||
jmethodID jGetMimeTypeFromExtension;
|
||||
jmethodID jMoveTaskToBack;
|
||||
|
Loading…
Reference in New Issue
Block a user