Bug 646550 - Tell Android to scan media items downloaded by Fennec r=blassey
authorWes Johnston <wjohnston@mozilla.com>
Fri, 08 Apr 2011 10:52:13 -0700
changeset 67623 760c50e2239a82bac1ca7bc43f3b5c17459b5295
parent 67622 ecb9212d635ff9672a3b9e53d95ee868482f9c89
child 67624 8adbca2b3518bb5ee2c22940a51a89f0dcb1968c
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey
bugs646550
milestone2.2a1pre
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 646550 - Tell Android to scan media items downloaded by Fennec r=blassey
embedding/android/GeckoAppShell.java
toolkit/components/downloads/nsDownloadManager.cpp
widget/src/android/AndroidBridge.cpp
widget/src/android/AndroidBridge.h
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -54,16 +54,18 @@ import android.view.inputmethod.*;
 import android.content.*;
 import android.content.res.*;
 import android.content.pm.*;
 import android.graphics.*;
 import android.widget.*;
 import android.hardware.*;
 import android.location.*;
 import android.webkit.MimeTypeMap;
+import android.media.MediaScannerConnection;
+import android.media.MediaScannerConnection.MediaScannerConnectionClient;
 
 import android.util.*;
 import android.net.Uri;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 
 public class GeckoAppShell
 {
@@ -114,16 +116,41 @@ public class GeckoAppShell
             Looper.prepare();
             try {
                 mHandlerQueue.put(new Handler());
             } catch (InterruptedException ie) {}
             Looper.loop();
         }
     }
 
+    private static class GeckoMediaScannerClient implements MediaScannerConnectionClient {
+        private String mFile = "";
+        private String mMimeType = "";
+        private MediaScannerConnection mScanner = null;
+
+        public GeckoMediaScannerClient(Context aContext, String aFile, String aMimeType) {
+            mFile = aFile;
+            mMimeType = aMimeType;
+            mScanner = new MediaScannerConnection(aContext, this);
+            if (mScanner != null)
+                mScanner.connect();
+        }
+
+        public void onMediaScannerConnected() {
+            mScanner.scanFile(mFile, mMimeType);
+        }
+
+        public void onScanCompleted(String path, Uri uri) {
+            if(path.equals(mFile)) {
+                mScanner.disconnect();
+                mScanner = null;
+            }
+        }
+    }
+
     // Get a Handler for the main java thread
     public static Handler getMainHandler() {
         return GeckoApp.mAppContext.mMainHandler;
     }
 
     private static Handler sHandler = null;
 
     // Get a Handler for a looper thread, or create one if it doesn't exist yet
@@ -1060,9 +1087,14 @@ public class GeckoAppShell
     public static void waitForAnotherGeckoProc(){
         int countdown = 40;
         while (!checkForGeckoProcs() &&  --countdown > 0) {
             try {
                 Thread.currentThread().sleep(100);
             } catch (InterruptedException ie) {}
         }
     }
+
+    public static void scanMedia(String aFile, String aMimeType) {
+        Context context = GeckoApp.surfaceView.getContext();
+        GeckoMediaScannerClient client = new GeckoMediaScannerClient(context, aFile, aMimeType);
+    }
 }
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
@@ -75,16 +75,20 @@
 #include "nsDownloadScanner.h"
 #endif
 #endif
 
 #ifdef XP_MACOSX
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
+#ifdef ANDROID
+#include "AndroidBridge.h"
+#endif
+
 #define DOWNLOAD_MANAGER_BUNDLE "chrome://mozapps/locale/downloads/downloads.properties"
 #define DOWNLOAD_MANAGER_ALERT_ICON "chrome://mozapps/skin/downloads/downloadIcon.png"
 #define PREF_BDM_SHOWALERTONCOMPLETE "browser.download.manager.showAlertOnComplete"
 #define PREF_BDM_SHOWALERTINTERVAL "browser.download.manager.showAlertInterval"
 #define PREF_BDM_RETENTION "browser.download.manager.retention"
 #define PREF_BDM_QUITBEHAVIOR "browser.download.manager.quitBehavior"
 #define PREF_BDM_ADDTORECENTDOCS "browser.download.manager.addToRecentDocs"
 #define PREF_BDM_SCANWHENDONE "browser.download.manager.scanWhenDone"
@@ -2234,17 +2238,17 @@ nsDownload::SetState(DownloadState aStat
               alerts->ShowAlertNotification(
                   NS_LITERAL_STRING(DOWNLOAD_MANAGER_ALERT_ICON), title,
                   message, !removeWhenDone, EmptyString(), mDownloadManager,
                   EmptyString());
             }
         }
       }
 
-#if (defined(XP_WIN) && !defined(WINCE)) || defined(XP_MACOSX)
+#if (defined(XP_WIN) && !defined(WINCE)) || defined(XP_MACOSX) || defined(ANDROID)
       nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mTarget);
       nsCOMPtr<nsIFile> file;
       nsAutoString path;
 
       if (fileURL &&
           NS_SUCCEEDED(fileURL->GetFile(getter_AddRefs(file))) &&
           file &&
           NS_SUCCEEDED(file->GetPath(path))) {
@@ -2268,16 +2272,26 @@ nsDownload::SetState(DownloadState aStat
         CFStringRef observedObject = ::CFStringCreateWithCString(kCFAllocatorDefault,
                                                  NS_ConvertUTF16toUTF8(path).get(),
                                                  kCFStringEncodingUTF8);
         CFNotificationCenterRef center = ::CFNotificationCenterGetDistributedCenter();
         ::CFNotificationCenterPostNotification(center, CFSTR("com.apple.DownloadFileFinished"),
                                                observedObject, NULL, TRUE);
         ::CFRelease(observedObject);
 #endif
+#ifdef ANDROID
+        nsCOMPtr<nsIMIMEInfo> mimeInfo;
+        nsCAutoString contentType;
+        GetMIMEInfo(getter_AddRefs(mimeInfo));
+
+        if (mimeInfo)
+          mimeInfo->GetMIMEType(contentType);
+
+        mozilla::AndroidBridge::Bridge()->ScanMedia(path, contentType);
+#endif
       }
 
 #ifdef XP_WIN
       // Adjust file attributes so that by default, new files are indexed
       // by desktop search services. Skip off those that land in the temp
       // folder.
       nsCOMPtr<nsIFile> tempDir, fileDir;
       rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tempDir));
--- a/widget/src/android/AndroidBridge.cpp
+++ b/widget/src/android/AndroidBridge.cpp
@@ -129,16 +129,17 @@ AndroidBridge::Init(JNIEnv *jEnv,
     jSetFullScreen = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setFullScreen", "(Z)V");
     jShowInputMethodPicker = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showInputMethodPicker", "()V");
     jHideProgressDialog = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "hideProgressDialog", "()V");
     jPerformHapticFeedback = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "performHapticFeedback", "(Z)V");
     jSetKeepScreenOn = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setKeepScreenOn", "(Z)V");
     jIsNetworkLinkUp = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "isNetworkLinkUp", "()Z");
     jIsNetworkLinkKnown = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "isNetworkLinkKnown", "()Z");
     jSetSelectedLocale = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setSelectedLocale", "(Ljava/lang/String;)V");
+    jScanMedia = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "scanMedia", "(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"));
 
@@ -779,8 +780,21 @@ extern "C" JNIEnv * GetJNIForThread()
 {
     return mozilla::AndroidBridge::JNIForThread();
 }
 
 jclass GetGeckoAppShellClass()
 {
     return mozilla::AndroidBridge::GetGeckoAppShellClass();
 }
+
+void
+AndroidBridge::ScanMedia(const nsAString& aFile, const nsACString& aMimeType)
+{
+    jstring jstrFile = mJNIEnv->NewString(nsPromiseFlatString(aFile).get(), aFile.Length());
+
+    nsString mimeType2;
+    CopyUTF8toUTF16(aMimeType, mimeType2);
+    jstring jstrMimeTypes = mJNIEnv->NewString(nsPromiseFlatString(mimeType2).get(), mimeType2.Length());
+
+    mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jScanMedia, jstrFile, jstrMimeTypes);
+}
+
--- a/widget/src/android/AndroidBridge.h
+++ b/widget/src/android/AndroidBridge.h
@@ -219,16 +219,18 @@ public:
     void *CallEglCreateWindowSurface(void *dpy, void *config, AndroidGeckoSurfaceView& surfaceView);
 
     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);
+
 protected:
     static AndroidBridge *sBridge;
 
     // the global JavaVM
     JavaVM *mJavaVM;
 
     // the JNIEnv for the main thread
     JNIEnv *mJNIEnv;
@@ -273,16 +275,17 @@ protected:
     jmethodID jSetFullScreen;
     jmethodID jShowInputMethodPicker;
     jmethodID jHideProgressDialog;
     jmethodID jPerformHapticFeedback;
     jmethodID jSetKeepScreenOn;
     jmethodID jIsNetworkLinkUp;
     jmethodID jIsNetworkLinkKnown;
     jmethodID jSetSelectedLocale;
+    jmethodID jScanMedia;
 
     // stuff we need for CallEglCreateWindowSurface
     jclass jEGLSurfaceImplClass;
     jclass jEGLContextImplClass;
     jclass jEGLConfigImplClass;
     jclass jEGLDisplayImplClass;
     jclass jEGLContextClass;
     jclass jEGL10Class;