Bug 1258450 - Move references to SnackbarHelper out of GeckoAppShell. r=snorp,sebastian

The existing code assumes an Activity, not just a Context, but doesn't
statically guarantee it.  This patch is safe because it dynamically
type-checks, but it would be better to declare the member to be an
Activity.

MozReview-Commit-ID: 9AigV055I5j

--HG--
extra : rebase_source : e2d273221767735504a93855623961fc171ae413
extra : source : 0476a0d0575b4b07c404eb15bc5a943ae04d0289
This commit is contained in:
Nick Alexander 2016-03-30 10:21:29 -07:00
parent f23b50bd14
commit 69ad3a1408
2 changed files with 94 additions and 88 deletions

View File

@ -7,18 +7,15 @@ package org.mozilla.gecko;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@ -38,14 +35,12 @@ import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.gfx.BitmapUtils;
import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.gfx.PanZoomController;
import org.mozilla.gecko.mozglue.ContextUtils;
import org.mozilla.gecko.overlays.ui.ShareDialog;
import org.mozilla.gecko.permissions.Permissions;
import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.GeckoRequest;
import org.mozilla.gecko.util.HardwareCodecCapabilityUtils;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.IOUtils;
import org.mozilla.gecko.util.NativeEventListener;
import org.mozilla.gecko.util.NativeJSContainer;
import org.mozilla.gecko.util.NativeJSObject;
@ -96,11 +91,9 @@ import android.os.SystemClock;
import android.os.Vibrator;
import android.provider.Browser;
import android.provider.Settings;
import android.support.design.widget.Snackbar;
import android.support.v4.app.FragmentActivity;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.ContextThemeWrapper;
@ -113,7 +106,6 @@ import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.webkit.MimeTypeMap;
import android.webkit.URLUtil;
import android.widget.AbsoluteLayout;
public class GeckoAppShell
@ -2537,84 +2529,6 @@ public class GeckoAppShell
return "DIRECT";
}
/* Downloads the URI pointed to by a share intent, and alters the intent to point to the locally stored file.
*/
public static void downloadImageForIntent(final Intent intent) {
final String src = ContextUtils.getStringExtra(intent, Intent.EXTRA_TEXT);
if (src == null) {
showImageShareFailureSnackbar();
return;
}
final File dir = GeckoApp.getTempDirectory();
if (dir == null) {
showImageShareFailureSnackbar();
return;
}
GeckoApp.deleteTempFiles();
String type = intent.getType();
OutputStream os = null;
try {
// Create a temporary file for the image
if (src.startsWith("data:")) {
final int dataStart = src.indexOf(",");
String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(type);
// If we weren't given an explicit mimetype, try to dig one out of the data uri.
if (TextUtils.isEmpty(extension) && dataStart > 5) {
type = src.substring(5, dataStart).replace(";base64", "");
extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(type);
}
final File imageFile = File.createTempFile("image", "." + extension, dir);
os = new FileOutputStream(imageFile);
byte[] buf = Base64.decode(src.substring(dataStart + 1), Base64.DEFAULT);
os.write(buf);
// Only alter the intent when we're sure everything has worked
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(imageFile));
} else {
InputStream is = null;
try {
final byte[] buf = new byte[2048];
final URL url = new URL(src);
final String filename = URLUtil.guessFileName(src, null, type);
is = url.openStream();
final File imageFile = new File(dir, filename);
os = new FileOutputStream(imageFile);
int length;
while ((length = is.read(buf)) != -1) {
os.write(buf, 0, length);
}
// Only alter the intent when we're sure everything has worked
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(imageFile));
} finally {
IOUtils.safeStreamClose(is);
}
}
} catch(IOException ex) {
// If something went wrong, we'll just leave the intent un-changed
} finally {
IOUtils.safeStreamClose(os);
}
}
// Don't fail silently, tell the user that we weren't able to share the image
private static final void showImageShareFailureSnackbar() {
SnackbarHelper.showSnackbar((Activity) getContext(),
getApplicationContext().getString(R.string.share_image_failed),
Snackbar.LENGTH_LONG
);
}
@WrapForJNI(allowMultithread = true)
static InputStream createInputStream(URLConnection connection) throws IOException {
return connection.getInputStream();

View File

@ -5,14 +5,22 @@
package org.mozilla.gecko.widget;
import android.app.Activity;
import android.net.Uri;
import android.support.design.widget.Snackbar;
import android.util.Base64;
import android.view.Menu;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.GeckoApp;
import org.mozilla.gecko.R;
import org.mozilla.gecko.SnackbarHelper;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import org.mozilla.gecko.menu.QuickShareBarActionView;
import org.mozilla.gecko.mozglue.ContextUtils;
import org.mozilla.gecko.overlays.ui.ShareDialog;
import org.mozilla.gecko.menu.MenuItemSwitcherLayout;
import org.mozilla.gecko.util.IOUtils;
import org.mozilla.gecko.util.ThreadUtils;
import android.content.Context;
@ -25,7 +33,15 @@ import android.view.SubMenu;
import android.view.View;
import android.view.View.OnClickListener;
import android.text.TextUtils;
import android.webkit.MimeTypeMap;
import android.webkit.URLUtil;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
@ -232,7 +248,7 @@ public class GeckoActionProvider {
// Share image downloads the image before sharing it.
String type = launchIntent.getType();
if (Intent.ACTION_SEND.equals(launchIntent.getAction()) && type != null && type.startsWith("image/")) {
GeckoAppShell.downloadImageForIntent(launchIntent);
downloadImageForIntent(launchIntent);
}
launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
@ -270,4 +286,80 @@ public class GeckoActionProvider {
QUICK_SHARE_ICON,
CONTEXT_MENU,
}
/**
* Downloads the URI pointed to by a share intent, and alters the intent to point to the
* locally stored file.
*
* @param intent share intent to alter in place.
*/
public void downloadImageForIntent(final Intent intent) {
final String src = ContextUtils.getStringExtra(intent, Intent.EXTRA_TEXT);
final File dir = GeckoApp.getTempDirectory();
if (src == null || dir == null) {
// We should be, but currently aren't, statically guaranteed an Activity context.
// Try our best.
if (mContext instanceof Activity) {
SnackbarHelper.showSnackbar((Activity) mContext,
mContext.getApplicationContext().getString(R.string.share_image_failed),
Snackbar.LENGTH_LONG);
}
return;
}
GeckoApp.deleteTempFiles();
String type = intent.getType();
OutputStream os = null;
try {
// Create a temporary file for the image
if (src.startsWith("data:")) {
final int dataStart = src.indexOf(",");
String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(type);
// If we weren't given an explicit mimetype, try to dig one out of the data uri.
if (TextUtils.isEmpty(extension) && dataStart > 5) {
type = src.substring(5, dataStart).replace(";base64", "");
extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(type);
}
final File imageFile = File.createTempFile("image", "." + extension, dir);
os = new FileOutputStream(imageFile);
byte[] buf = Base64.decode(src.substring(dataStart + 1), Base64.DEFAULT);
os.write(buf);
// Only alter the intent when we're sure everything has worked
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(imageFile));
} else {
InputStream is = null;
try {
final byte[] buf = new byte[2048];
final URL url = new URL(src);
final String filename = URLUtil.guessFileName(src, null, type);
is = url.openStream();
final File imageFile = new File(dir, filename);
os = new FileOutputStream(imageFile);
int length;
while ((length = is.read(buf)) != -1) {
os.write(buf, 0, length);
}
// Only alter the intent when we're sure everything has worked
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(imageFile));
} finally {
IOUtils.safeStreamClose(is);
}
}
} catch(IOException ex) {
// If something went wrong, we'll just leave the intent un-changed
} finally {
IOUtils.safeStreamClose(os);
}
}
}