Bug 990642 - Reinsert code to share images instead of just urls. r=mfinkle, a=lsblakk
authorWes Johnston <wjohnston@mozilla.com>
Mon, 12 May 2014 10:13:44 -0700
changeset 193408 f3247e4fa37d49188b9ebb7ba07a58dfe144aeb2
parent 193407 6879a3064321d58e52642db1e3adba2098605f29
child 193409 4fa8558dd82750f605d043a902305e92c6fde717
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle, lsblakk
bugs990642
milestone30.0
Bug 990642 - Reinsert code to share images instead of just urls. r=mfinkle, a=lsblakk
mobile/android/base/GeckoAppShell.java
mobile/android/base/prompts/PromptListItem.java
mobile/android/base/widget/GeckoActionProvider.java
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -2621,9 +2621,66 @@ public class GeckoAppShell
                 return "PROXY " + proxy.address().toString();
             case SOCKS:
                 return "SOCKS " + proxy.address().toString();
         }
 
         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 = intent.getStringExtra(Intent.EXTRA_TEXT);
+        final File dir = GeckoApp.getTempDirectory();
+
+        if (dir == null) {
+            showImageShareFailureToast();
+            return;
+        }
+
+        GeckoApp.deleteTempFiles();
+
+        OutputStream os = null;
+        try {
+            // Create a temporary file for the image
+            final String type = intent.getType().replace("image/", "");
+            final File imageFile = File.createTempFile("image", "." + type, dir);
+            os = new FileOutputStream(imageFile);
+
+            if (src.startsWith("data:")) {
+                int dataStart = src.indexOf(",");
+                byte[] buf = Base64.decode(src.substring(dataStart + 1), Base64.DEFAULT);
+                os.write(buf);
+
+                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);
+                    is = url.openStream();
+
+                    int length;
+                    while ((length = is.read(buf)) != -1) {
+                        os.write(buf, 0, length);
+                    }
+
+                    intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(imageFile));
+                } finally {
+                    safeStreamClose(is);
+                }
+            }
+        } catch(IOException ex) {
+        } finally {
+            safeStreamClose(os);
+        }
+    }
+
+    // Don't fail silently, tell the user that we weren't able to share the image
+    private static final void showImageShareFailureToast() {
+        Toast toast = Toast.makeText(getContext(),
+                                     getContext().getResources().getString(R.string.share_image_failed),
+                                     Toast.LENGTH_SHORT);
+        toast.show();
+    }
+
 }
--- a/mobile/android/base/prompts/PromptListItem.java
+++ b/mobile/android/base/prompts/PromptListItem.java
@@ -3,16 +3,17 @@ package org.mozilla.gecko.prompts;
 import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.widget.GeckoActionProvider;
 
 import org.json.JSONArray;
 import org.json.JSONObject;
 import org.json.JSONException;
 
+import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
 import android.util.Log;
 
 import java.util.List;
 import java.util.ArrayList;
 
 // This class should die and be replaced with normal menu items
@@ -26,39 +27,41 @@ public class PromptListItem {
     public final boolean showAsActions;
     public final boolean isParent;
 
     public Intent mIntent;
     public boolean mSelected;
     public Drawable mIcon;
 
     PromptListItem(JSONObject aObject) {
+        Context context = GeckoAppShell.getContext();
         label = aObject.isNull("label") ? "" : aObject.optString("label");
         isGroup = aObject.optBoolean("isGroup");
         inGroup = aObject.optBoolean("inGroup");
         disabled = aObject.optBoolean("disabled");
         id = aObject.optInt("id");
         mSelected = aObject.optBoolean("selected");
 
         JSONObject obj = aObject.optJSONObject("showAsActions");
         if (obj != null) {
             showAsActions = true;
             String uri = obj.isNull("uri") ? "" : obj.optString("uri");
             String type = obj.isNull("type") ? GeckoActionProvider.DEFAULT_MIME_TYPE :
                                                obj.optString("type", GeckoActionProvider.DEFAULT_MIME_TYPE);
-            mIntent = GeckoAppShell.getShareIntent(GeckoAppShell.getContext(), uri, type, "");
+
+            mIntent = GeckoAppShell.getShareIntent(context, uri, type, "");
             isParent = true;
         } else {
             mIntent = null;
             showAsActions = false;
             // Support both "isParent" (backwards compat for older consumers), and "menu" for the new Tabbed prompt ui.
             isParent = aObject.optBoolean("isParent") || aObject.optBoolean("menu");
         }
 
-        BitmapUtils.getDrawable(GeckoAppShell.getContext(), aObject.optString("icon"), new BitmapUtils.BitmapLoader() {
+        BitmapUtils.getDrawable(context, aObject.optString("icon"), new BitmapUtils.BitmapLoader() {
             @Override
             public void onBitmapFound(Drawable d) {
                 mIcon = d;
             }
         });
     }
 
     public void setIntent(Intent i) {
--- a/mobile/android/base/widget/GeckoActionProvider.java
+++ b/mobile/android/base/widget/GeckoActionProvider.java
@@ -177,16 +177,22 @@ public class GeckoActionProvider {
      * Listener for handling default activity / menu item clicks.
      */
     private class Callbacks implements OnMenuItemClickListener,
                                        OnClickListener {
         private void chooseActivity(int index) { 
             ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mHistoryFileName);
             Intent launchIntent = dataModel.chooseActivity(index);
             if (launchIntent != null) {
+                // Share image syncrhonously 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);
+                }
+
                 launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
                 mContext.startActivity(launchIntent);
             }
 
             if (mOnTargetListener != null) {
                 mOnTargetListener.onTargetSelected();
             }
         }