Bug 1070086 - Move download integration code to its own class. r=bnicholson

This commit is contained in:
Wes Johnston 2014-10-20 12:24:49 -07:00
parent bcbd60500a
commit 887c937308
8 changed files with 158 additions and 106 deletions

View File

@ -0,0 +1,110 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import android.app.DownloadManager;
import android.content.Context;
import android.database.Cursor;
import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
public class DownloadsIntegration
{
private static final String LOGTAG = "GeckoDownloadsIntegration";
@SuppressWarnings("serial")
private static final List<String> UNKNOWN_MIME_TYPES = new ArrayList<String>(3) {{
add("unknown/unknown"); // This will be used as a default mime type for unknown files
add("application/unknown");
add("application/octet-stream"); // Github uses this for APK files
}};
@WrapElementForJNI
public static void scanMedia(final String aFile, String aMimeType) {
String mimeType = aMimeType;
if (UNKNOWN_MIME_TYPES.contains(mimeType)) {
// If this is a generic undefined mimetype, erase it so that we can try to determine
// one from the file extension below.
mimeType = "";
}
// If the platform didn't give us a mimetype, try to guess one from the filename
if (TextUtils.isEmpty(mimeType)) {
final int extPosition = aFile.lastIndexOf(".");
if (extPosition > 0 && extPosition < aFile.length() - 1) {
mimeType = GeckoAppShell.getMimeTypeFromExtension(aFile.substring(extPosition+1));
}
}
// addCompletedDownload will throw if it received any null parameters. Use aMimeType or a default
// if we still don't have one.
if (TextUtils.isEmpty(mimeType)) {
if (TextUtils.isEmpty(aMimeType)) {
mimeType = UNKNOWN_MIME_TYPES.get(0);
} else {
mimeType = aMimeType;
}
}
if (AppConstants.ANDROID_DOWNLOADS_INTEGRATION) {
final File f = new File(aFile);
final DownloadManager dm = (DownloadManager) GeckoAppShell.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
dm.addCompletedDownload(f.getName(),
f.getName(),
true, // Media scanner should scan this
mimeType,
f.getAbsolutePath(),
Math.max(1, f.length()), // Some versions of Android require downloads to be at least length 1
false); // Don't show a notification.
} else {
final Context context = GeckoAppShell.getContext();
final GeckoMediaScannerClient client = new GeckoMediaScannerClient(context, aFile, mimeType);
client.connect();
}
}
private static final class GeckoMediaScannerClient implements MediaScannerConnectionClient {
private final String mFile;
private final String mMimeType;
private MediaScannerConnection mScanner;
public GeckoMediaScannerClient(Context context, String file, String mimeType) {
mFile = file;
mMimeType = mimeType;
mScanner = new MediaScannerConnection(context, this);
}
public void connect() {
mScanner.connect();
}
@Override
public void onMediaScannerConnected() {
mScanner.scanFile(mFile, mMimeType);
}
@Override
public void onScanCompleted(String path, Uri uri) {
if(path.equals(mFile)) {
mScanner.disconnect();
mScanner = null;
}
}
}
}

View File

@ -60,7 +60,6 @@ import org.mozilla.gecko.util.ThreadUtils;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.DownloadManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.Context;
@ -93,8 +92,6 @@ import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
@ -139,13 +136,6 @@ public class GeckoAppShell
private static final Queue<GeckoEvent> PENDING_EVENTS = new ConcurrentLinkedQueue<GeckoEvent>();
private static final Map<String, String> ALERT_COOKIES = new ConcurrentHashMap<String, String>();
@SuppressWarnings("serial")
private static final List<String> UNKNOWN_MIME_TYPES = new ArrayList<String>(3) {{
add("unknown/unknown"); // This will be used as a default mime type for unknown files
add("application/unknown");
add("application/octet-stream"); // Github uses this for APK files
}};
private static volatile boolean locationHighAccuracyEnabled;
// Accessed by NotificationHelper. This should be encapsulated.
@ -276,36 +266,6 @@ public class GeckoAppShell
}
}
private static final class GeckoMediaScannerClient implements MediaScannerConnectionClient {
private final String mFile;
private final String mMimeType;
private MediaScannerConnection mScanner;
public static void startScan(Context context, String file, String mimeType) {
new GeckoMediaScannerClient(context, file, mimeType);
}
private GeckoMediaScannerClient(Context context, String file, String mimeType) {
mFile = file;
mMimeType = mimeType;
mScanner = new MediaScannerConnection(context, this);
mScanner.connect();
}
@Override
public void onMediaScannerConnected() {
mScanner.scanFile(mFile, mMimeType);
}
@Override
public void onScanCompleted(String path, Uri uri) {
if(path.equals(mFile)) {
mScanner.disconnect();
mScanner = null;
}
}
}
private static LayerView sLayerView;
public static void setLayerView(LayerView lv) {
@ -1800,49 +1760,6 @@ public class GeckoAppShell
} catch (Exception e) { }
}
@WrapElementForJNI
public static void scanMedia(final String aFile, String aMimeType) {
String mimeType = aMimeType;
if (UNKNOWN_MIME_TYPES.contains(mimeType)) {
// If this is a generic undefined mimetype, erase it so that we can try to determine
// one from the file extension below.
mimeType = "";
}
// If the platform didn't give us a mimetype, try to guess one from the filename
if (TextUtils.isEmpty(mimeType)) {
int extPosition = aFile.lastIndexOf(".");
if (extPosition > 0 && extPosition < aFile.length() - 1) {
mimeType = getMimeTypeFromExtension(aFile.substring(extPosition+1));
}
}
// addCompletedDownload will throw if it received any null parameters. Use aMimeType or a default
// if we still don't have one.
if (TextUtils.isEmpty(mimeType)) {
if (TextUtils.isEmpty(aMimeType)) {
mimeType = UNKNOWN_MIME_TYPES.get(0);
} else {
mimeType = aMimeType;
}
}
if (AppConstants.ANDROID_DOWNLOADS_INTEGRATION) {
final File f = new File(aFile);
final DownloadManager dm = (DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE);
dm.addCompletedDownload(f.getName(),
f.getName(),
true, // Media scanner should scan this
mimeType,
f.getAbsolutePath(),
Math.max(1, f.length()), // Some versions of Android require downloads to be at least length 1
false); // Don't show a notification.
} else {
Context context = getContext();
GeckoMediaScannerClient.startScan(context, aFile, mimeType);
}
}
@WrapElementForJNI(stubName = "GetIconForExtensionWrapper")
public static byte[] getIconForExtension(String aExt, int iconSize) {
try {
@ -1874,7 +1791,7 @@ public class GeckoAppShell
}
}
private static String getMimeTypeFromExtension(String ext) {
public static String getMimeTypeFromExtension(String ext) {
final MimeTypeMap mtm = MimeTypeMap.getSingleton();
return mtm.getMimeTypeFromExtension(ext);
}

View File

@ -162,6 +162,7 @@ gbjar.sources += [
'distribution/ReferrerDescriptor.java',
'distribution/ReferrerReceiver.java',
'DoorHangerPopup.java',
'DownloadsIntegration.java',
'DynamicToolbar.java',
'EditBookmarkDialog.java',
'EventDispatcher.java',

View File

@ -9,6 +9,6 @@
# project structure.
# Project target.
target=android-@ANDROID_TARGET_SDK@
target=android-L
@IDE_PROJECT_LIBRARY_SETTING@
@IDE_PROJECT_LIBRARY_REFERENCES@

View File

@ -2794,7 +2794,7 @@ nsDownload::SetState(DownloadState aState)
if (mimeInfo)
mimeInfo->GetMIMEType(contentType);
mozilla::widget::android::GeckoAppShell::ScanMedia(path, NS_ConvertUTF8toUTF16(contentType));
mozilla::widget::android::DownloadsIntegration::ScanMedia(path, NS_ConvertUTF8toUTF16(contentType));
#endif
}
#ifdef MOZ_ENABLE_GIO

View File

@ -95,7 +95,7 @@ nsresult DownloadPlatform::DownloadDone(nsIURI* aSource, nsIFile* aTarget,
g_free(uri);
}
#elif MOZ_WIDGET_ANDROID
mozilla::widget::android::GeckoAppShell::ScanMedia(path, NS_ConvertUTF8toUTF16(aContentType));
mozilla::widget::android::DownloadsIntegration::ScanMedia(path, NS_ConvertUTF8toUTF16(aContentType));
#endif
}
#ifdef MOZ_ENABLE_GIO

View File

@ -11,6 +11,36 @@
namespace mozilla {
namespace widget {
namespace android {
jclass DownloadsIntegration::mDownloadsIntegrationClass = 0;
jmethodID DownloadsIntegration::jScanMedia = 0;
void DownloadsIntegration::InitStubs(JNIEnv *jEnv) {
initInit();
mDownloadsIntegrationClass = getClassGlobalRef("org/mozilla/gecko/DownloadsIntegration");
jScanMedia = getStaticMethod("scanMedia", "(Ljava/lang/String;Ljava/lang/String;)V");
}
DownloadsIntegration* DownloadsIntegration::Wrap(jobject obj) {
JNIEnv *env = GetJNIForThread();
DownloadsIntegration* ret = new DownloadsIntegration(obj, env);
env->DeleteLocalRef(obj);
return ret;
}
void DownloadsIntegration::ScanMedia(const nsAString& a0, const nsAString& a1) {
JNIEnv *env = AndroidBridge::GetJNIEnv();
if (env->PushLocalFrame(2) != 0) {
AndroidBridge::HandleUncaughtException(env);
MOZ_CRASH("Exception should have caused crash.");
}
jstring j0 = AndroidBridge::NewJavaString(env, a0);
jstring j1 = AndroidBridge::NewJavaString(env, a1);
env->CallStaticVoidMethod(mDownloadsIntegrationClass, jScanMedia, j0, j1);
AndroidBridge::HandleUncaughtException(env);
env->PopLocalFrame(nullptr);
}
jclass GeckoAppShell::mGeckoAppShellClass = 0;
jmethodID GeckoAppShell::jAcknowledgeEvent = 0;
jmethodID GeckoAppShell::jAddPluginViewWrapper = 0;
@ -80,7 +110,6 @@ jmethodID GeckoAppShell::jPumpMessageLoop = 0;
jmethodID GeckoAppShell::jRegisterSurfaceTextureFrameListener = 0;
jmethodID GeckoAppShell::jRemovePluginView = 0;
jmethodID GeckoAppShell::jRequestUiThreadCallback = 0;
jmethodID GeckoAppShell::jScanMedia = 0;
jmethodID GeckoAppShell::jScheduleRestart = 0;
jmethodID GeckoAppShell::jSendMessageWrapper = 0;
jmethodID GeckoAppShell::jSetFullScreen = 0;
@ -167,7 +196,6 @@ void GeckoAppShell::InitStubs(JNIEnv *jEnv) {
jRegisterSurfaceTextureFrameListener = getStaticMethod("registerSurfaceTextureFrameListener", "(Ljava/lang/Object;I)V");
jRemovePluginView = getStaticMethod("removePluginView", "(Landroid/view/View;Z)V");
jRequestUiThreadCallback = getStaticMethod("requestUiThreadCallback", "(J)V");
jScanMedia = getStaticMethod("scanMedia", "(Ljava/lang/String;Ljava/lang/String;)V");
jScheduleRestart = getStaticMethod("scheduleRestart", "()V");
jSendMessageWrapper = getStaticMethod("sendMessage", "(Ljava/lang/String;Ljava/lang/String;I)V");
jSetFullScreen = getStaticMethod("setFullScreen", "(Z)V");
@ -1123,21 +1151,6 @@ void GeckoAppShell::RequestUiThreadCallback(int64_t a0) {
env->PopLocalFrame(nullptr);
}
void GeckoAppShell::ScanMedia(const nsAString& a0, const nsAString& a1) {
JNIEnv *env = AndroidBridge::GetJNIEnv();
if (env->PushLocalFrame(2) != 0) {
AndroidBridge::HandleUncaughtException(env);
MOZ_CRASH("Exception should have caused crash.");
}
jstring j0 = AndroidBridge::NewJavaString(env, a0);
jstring j1 = AndroidBridge::NewJavaString(env, a1);
env->CallStaticVoidMethod(mGeckoAppShellClass, jScanMedia, j0, j1);
AndroidBridge::HandleUncaughtException(env);
env->PopLocalFrame(nullptr);
}
void GeckoAppShell::ScheduleRestart() {
JNIEnv *env = AndroidBridge::GetJNIEnv();
if (env->PushLocalFrame(0) != 0) {
@ -2478,6 +2491,7 @@ void Clipboard::SetClipboardText(const nsAString& a0) {
}
void InitStubs(JNIEnv *jEnv) {
DownloadsIntegration::InitStubs(jEnv);
GeckoAppShell::InitStubs(jEnv);
GeckoJavaSampler::InitStubs(jEnv);
RestrictedProfiles::InitStubs(jEnv);

View File

@ -14,6 +14,18 @@ namespace widget {
namespace android {
void InitStubs(JNIEnv *jEnv);
class DownloadsIntegration : public AutoGlobalWrappedJavaObject {
public:
static void InitStubs(JNIEnv *jEnv);
static DownloadsIntegration* Wrap(jobject obj);
DownloadsIntegration(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {};
static void ScanMedia(const nsAString& a0, const nsAString& a1);
DownloadsIntegration() : AutoGlobalWrappedJavaObject() {};
protected:
static jclass mDownloadsIntegrationClass;
static jmethodID jScanMedia;
};
class GeckoAppShell : public AutoGlobalWrappedJavaObject {
public:
static void InitStubs(JNIEnv *jEnv);
@ -87,7 +99,6 @@ public:
static void RegisterSurfaceTextureFrameListener(jobject a0, int32_t a1);
static void RemovePluginView(jobject a0, bool a1);
static void RequestUiThreadCallback(int64_t a0);
static void ScanMedia(const nsAString& a0, const nsAString& a1);
static void ScheduleRestart();
static void SendMessageWrapper(const nsAString& a0, const nsAString& a1, int32_t a2);
static void SetFullScreen(bool a0);
@ -173,7 +184,6 @@ protected:
static jmethodID jRegisterSurfaceTextureFrameListener;
static jmethodID jRemovePluginView;
static jmethodID jRequestUiThreadCallback;
static jmethodID jScanMedia;
static jmethodID jScheduleRestart;
static jmethodID jSendMessageWrapper;
static jmethodID jSetFullScreen;