diff --git a/embedding/android/AndroidManifest.xml.in b/embedding/android/AndroidManifest.xml.in index e434976ef904..d655e0bd9887 100644 --- a/embedding/android/AndroidManifest.xml.in +++ b/embedding/android/AndroidManifest.xml.in @@ -20,7 +20,7 @@ android:label="@MOZ_APP_DISPLAYNAME@" android:configChanges="keyboard|keyboardHidden|orientation|mcc|mnc" android:windowSoftInputMode="stateUnspecified|adjustResize" - android:launchMode="singleInstance"> + android:launchMode="singleTop"> diff --git a/embedding/android/GeckoApp.java b/embedding/android/GeckoApp.java index ad948a7c7776..ded621c794c4 100644 --- a/embedding/android/GeckoApp.java +++ b/embedding/android/GeckoApp.java @@ -42,6 +42,7 @@ import java.util.*; import java.util.zip.*; import java.nio.*; import java.nio.channels.FileChannel; +import java.util.concurrent.*; import android.os.*; import android.app.*; @@ -54,6 +55,7 @@ import android.widget.*; import android.hardware.*; import android.util.*; +import android.net.*; abstract public class GeckoApp extends Activity @@ -543,4 +545,64 @@ abstract public class GeckoApp if (statusCode == 0) System.exit(0); } + + static final int FILE_PICKER_REQUEST = 1; + + private SynchronousQueue mFilePickerResult = new SynchronousQueue(); + public String showFilePicker() { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("*/*"); + GeckoApp.this. + startActivityForResult( + Intent.createChooser(intent,"choose a file"), + FILE_PICKER_REQUEST); + String filePickerResult = ""; + try { + filePickerResult = mFilePickerResult.take(); + } catch (InterruptedException e) { + Log.i("GeckoApp", "error: " + e); + } + + return filePickerResult; + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, + Intent data) { + String filePickerResult = ""; + if (data != null && resultCode == RESULT_OK) { + try { + ContentResolver cr = getContentResolver(); + Uri uri = data.getData(); + String mimeType = cr.getType(uri); + String fileExt = "." + + mimeType.substring(mimeType.lastIndexOf('/') + 1); + File file = + File.createTempFile("tmp_" + + (int)Math.floor(1000 * Math.random()), + fileExt, + new File("/data/data/org.mozilla." + + getAppName())); + + FileOutputStream fos = new FileOutputStream(file); + InputStream is = cr.openInputStream(uri); + byte[] buf = new byte[4096]; + int len = is.read(buf); + while (len != -1) { + fos.write(buf, 0, len); + len = is.read(buf); + } + fos.close(); + filePickerResult = file.getAbsolutePath(); + }catch (Exception e) { + Log.e("GeckoApp", "error : "+ e); + } + } + try { + mFilePickerResult.put(filePickerResult); + } catch (InterruptedException e) { + Log.i("GeckoApp", "error: " + e); + } + } } diff --git a/embedding/android/GeckoAppShell.java b/embedding/android/GeckoAppShell.java index 96248ac09e56..ff43b708becd 100644 --- a/embedding/android/GeckoAppShell.java +++ b/embedding/android/GeckoAppShell.java @@ -510,4 +510,7 @@ class GeckoAppShell callObserver(alertName, "alertfinished", alertCookie); removeObserver(alertName); } + public static String showFilePicker() { + return GeckoApp.mAppContext.showFilePicker(); + } } diff --git a/toolkit/components/filepicker/Makefile.in b/toolkit/components/filepicker/Makefile.in index 0c8867d77251..43e5d2de5e71 100644 --- a/toolkit/components/filepicker/Makefile.in +++ b/toolkit/components/filepicker/Makefile.in @@ -44,10 +44,9 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk ifdef MOZ_XUL -ifeq (,$(filter qt beos os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT))) +ifeq (,$(filter android qt beos os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT))) DIRS = public src endif endif include $(topsrcdir)/config/rules.mk - diff --git a/toolkit/library/libxul-config.mk b/toolkit/library/libxul-config.mk index 7f6631d24855..fe861a4e1271 100644 --- a/toolkit/library/libxul-config.mk +++ b/toolkit/library/libxul-config.mk @@ -243,7 +243,7 @@ COMPONENT_LIBS += \ $(NULL) endif -ifeq (,$(filter qt beos os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT))) +ifeq (,$(filter android qt beos os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT))) ifdef MOZ_XUL COMPONENT_LIBS += fileview DEFINES += -DMOZ_FILEVIEW diff --git a/widget/src/android/AndroidBridge.cpp b/widget/src/android/AndroidBridge.cpp index 8220b9499675..b597c861b1fa 100644 --- a/widget/src/android/AndroidBridge.cpp +++ b/widget/src/android/AndroidBridge.cpp @@ -111,6 +111,7 @@ AndroidBridge::Init(JNIEnv *jEnv, 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;"); jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext")); @@ -417,6 +418,14 @@ AndroidBridge::ShowAlertNotification(const nsAString& aImageUrl, mJNIEnv->CallStaticVoidMethodA(mGeckoAppShellClass, jShowAlertNotification, args); } +void +AndroidBridge::ShowFilePicker(nsAString& aFilePath) +{ + jstring jstr = static_cast(mJNIEnv->CallStaticObjectMethod( + mGeckoAppShellClass, jShowFilePicker)); + aFilePath.Assign(nsJNIString(jstr)); +} + void AndroidBridge::SetSurfaceView(jobject obj) { diff --git a/widget/src/android/AndroidBridge.h b/widget/src/android/AndroidBridge.h index b82d3ae727d8..0e3d3d42e10c 100644 --- a/widget/src/android/AndroidBridge.h +++ b/widget/src/android/AndroidBridge.h @@ -144,6 +144,8 @@ public: nsIObserver *aAlertListener, const nsAString& aAlertName); + void ShowFilePicker(nsAString& aFilePath); + struct AutoLocalJNIFrame { AutoLocalJNIFrame(int nEntries = 128) : mEntries(nEntries) { AndroidBridge::Bridge()->JNI()->PushLocalFrame(mEntries); @@ -204,6 +206,7 @@ protected: jmethodID jGetClipboardText; jmethodID jSetClipboardText; jmethodID jShowAlertNotification; + jmethodID jShowFilePicker; // stuff we need for CallEglCreateWindowSurface jclass jEGLSurfaceImplClass; diff --git a/widget/src/android/Makefile.in b/widget/src/android/Makefile.in index 5c1a655b2654..72b0a07d0fb0 100644 --- a/widget/src/android/Makefile.in +++ b/widget/src/android/Makefile.in @@ -63,6 +63,7 @@ CPPSRCS = \ nsScreenManagerAndroid.cpp \ nsIdleServiceAndroid.cpp \ nsClipboard.cpp \ + nsFilePicker.cpp \ $(NULL) NOT_THERE_YET_CPPSRCS = \ @@ -72,7 +73,6 @@ NOT_THERE_YET_CPPSRCS = \ nsNativeThemeQt.cpp \ mozqwidget.cpp \ nsSound.cpp \ - nsFilePicker.cpp \ $(NULL) SHARED_LIBRARY_LIBS = ../xpwidgets/libxpwidgets_s.a diff --git a/widget/src/android/nsClipboard.h b/widget/src/android/nsClipboard.h index a7097d36ca2b..24e1affe444d 100644 --- a/widget/src/android/nsClipboard.h +++ b/widget/src/android/nsClipboard.h @@ -1,4 +1,5 @@ -/* ***** BEGIN LICENSE BLOCK ***** +/* -*- 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 diff --git a/widget/src/android/nsFilePicker.cpp b/widget/src/android/nsFilePicker.cpp new file mode 100644 index 000000000000..34183cc2cb36 --- /dev/null +++ b/widget/src/android/nsFilePicker.cpp @@ -0,0 +1,146 @@ +/* -*- 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 Android 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): + * Brad Lassey + * + * 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 "nsFilePicker.h" +#include "AndroidBridge.h" +#include "nsNetUtil.h" +#include "nsIURI.h" + +NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker) + +NS_IMETHODIMP nsFilePicker::Init(nsIDOMWindow *parent, const nsAString& title, + PRInt16 mode) +{ + return nsIFilePicker::modeOpen == mode ? NS_OK : NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsFilePicker::AppendFilters(PRInt32 filterMask) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsFilePicker::AppendFilter(const nsAString & title, const nsAString & filter) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsFilePicker::GetDefaultString(nsAString & aDefaultString) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsFilePicker::SetDefaultString(const nsAString & aDefaultString) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsFilePicker::GetDefaultExtension(nsAString & aDefaultExtension) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const nsAString & aDefaultExtension) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsFilePicker::GetFilterIndex(PRInt32 *aFilterIndex) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsFilePicker::SetFilterIndex(PRInt32 aFilterIndex) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsFilePicker::GetDisplayDirectory(nsILocalFile **aDisplayDirectory) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsFilePicker::SetDisplayDirectory(nsILocalFile *aDisplayDirectory) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsFilePicker::GetFile(nsILocalFile **aFile) +{ + NS_ENSURE_ARG_POINTER(aFile); + + *aFile = nsnull; + if (mFilePath.IsEmpty()) { + return NS_OK; + } + + nsCOMPtr file(do_CreateInstance("@mozilla.org/file/local;1")); + NS_ENSURE_TRUE(file, NS_ERROR_FAILURE); + + file->InitWithPath(mFilePath); + + NS_ADDREF(*aFile = file); + + nsCString path; + (*aFile)->GetNativePath(path); + return NS_OK; +} + +NS_IMETHODIMP nsFilePicker::GetFileURL(nsIURI **aFileURL) +{ + nsCOMPtr file; + GetFile(getter_AddRefs(file)); + + nsCOMPtr uri; + NS_NewFileURI(getter_AddRefs(uri), file); + NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE); + + return CallQueryInterface(uri, aFileURL); +} + +NS_IMETHODIMP nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsFilePicker::Show(PRInt16 *_retval NS_OUTPARAM) +{ + if (!mozilla::AndroidBridge::Bridge()) + return NS_ERROR_NOT_IMPLEMENTED; + nsAutoString filePath; + mozilla::AndroidBridge::Bridge()->ShowFilePicker(filePath); + *_retval = EmptyString().Equals(filePath) ? + nsIFilePicker::returnCancel : nsIFilePicker::returnOK; + if (*_retval == nsIFilePicker::returnOK) + mFilePath.Assign(filePath); + return NS_OK; +} diff --git a/widget/src/android/nsFilePicker.h b/widget/src/android/nsFilePicker.h new file mode 100644 index 000000000000..32ae8938742d --- /dev/null +++ b/widget/src/android/nsFilePicker.h @@ -0,0 +1,53 @@ +/* -*- 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 Android 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): + * Brad Lassey + * + * 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 NSFILEPICKER_H +#define NSFILEPICKER_H + +#include "nsIFilePicker.h" +#include "nsString.h" + +class nsFilePicker : public nsIFilePicker +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIFILEPICKER + +private: + nsString mFilePath; +}; +#endif diff --git a/widget/src/android/nsWidgetFactory.cpp b/widget/src/android/nsWidgetFactory.cpp index a1604a41057b..5c61e5f4a4df 100644 --- a/widget/src/android/nsWidgetFactory.cpp +++ b/widget/src/android/nsWidgetFactory.cpp @@ -52,6 +52,7 @@ #include "nsClipboard.h" #include "nsClipboardHelper.h" #include "nsTransferable.h" +#include "nsFilePicker.h" #include "nsHTMLFormatConverter.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit) @@ -62,6 +63,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsIdleServiceAndroid) NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard) NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker) NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) NS_DEFINE_NAMED_CID(NS_TOOLKIT_CID); @@ -74,6 +76,7 @@ NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID); NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID); NS_DEFINE_NAMED_CID(NS_CLIPBOARDHELPER_CID); +NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID); NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID); static const mozilla::Module::CIDEntry kWidgetCIDs[] = { @@ -87,6 +90,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = { { &kNS_TRANSFERABLE_CID, false, NULL, nsTransferableConstructor }, { &kNS_CLIPBOARD_CID, false, NULL, nsClipboardConstructor }, { &kNS_CLIPBOARDHELPER_CID, false, NULL, nsClipboardHelperConstructor }, + { &kNS_FILEPICKER_CID, false, NULL, nsFilePickerConstructor }, { &kNS_HTMLFORMATCONVERTER_CID, false, NULL, nsHTMLFormatConverterConstructor }, { NULL } }; @@ -102,6 +106,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { { "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID }, { "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID }, { "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID }, + { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID }, { "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID }, { NULL } };