Bug 1206792 - Crash when launching the camera from the gallery app r=snorp
authorFabrice Desré <fabrice@mozilla.com>
Tue, 22 Sep 2015 08:05:24 -0700
changeset 284880 4740ebc51a92a7b32265503813992c157c5c5395
parent 284879 2241ffbb0f062bc55aa013a8778bcd487f5cc585
child 284881 e709854a42c46df2dd3a9cc12191d16c012f40f4
push id8654
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:48:40 +0000
treeherdermozilla-aurora@bc4551debe17 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1206792
milestone44.0a1
Bug 1206792 - Crash when launching the camera from the gallery app r=snorp
mobile/android/base/util/WebActivityMapper.java
--- a/mobile/android/base/util/WebActivityMapper.java
+++ b/mobile/android/base/util/WebActivityMapper.java
@@ -6,100 +6,121 @@
 package org.mozilla.gecko.util;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import android.content.Intent;
 import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore;
 import android.text.TextUtils;
+import android.util.Log;
 
+import java.io.File;
 import java.util.HashMap;
 import java.util.Map;
 
 public final class WebActivityMapper {
+    private static final String LOGTAG = "Gecko";
+
     private static final Map<String, WebActivityMapping> activityMap = new HashMap<String, WebActivityMapping>();
     static {
         activityMap.put("dial", new DialMapping());
         activityMap.put("open", new OpenMapping());
         activityMap.put("pick", new PickMapping());
         activityMap.put("send", new SendMapping());
         activityMap.put("view", new ViewMapping());
+        activityMap.put("record", new RecordMapping());
     };
 
     private static abstract class WebActivityMapping {
+        protected JSONObject mData;
+
+        public void setData(JSONObject data) {
+            mData = data;
+        }
+
         // Cannot return null
         public abstract String getAction();
 
-        public String getMime(JSONObject data) throws JSONException {
+        public String getMime() throws JSONException {
             return null;
         }
 
-        public String getUri(JSONObject data) throws JSONException {
+        public String getUri() throws JSONException {
             return null;
         }
 
-        public void putExtras(JSONObject data, Intent intent) throws JSONException {}
+        public void putExtras(Intent intent) throws JSONException {}
     }
 
     /**
      * Provides useful defaults for mime type and uri.
      */
     private static abstract class BaseMapping extends WebActivityMapping {
         /**
          * If 'type' is present in data object, uses the value as the MIME type.
          */
         @Override
-        public String getMime(JSONObject data) throws JSONException {
-            return data.optString("type", null);
+        public String getMime() throws JSONException {
+            return mData.optString("type", null);
         }
 
         /**
          * If 'uri' or 'url' is present in data object, uses the respective value as the Uri.
          */
         @Override
-        public String getUri(JSONObject data) throws JSONException {
+        public String getUri() throws JSONException {
             // Will return uri or url if present.
-            String uri = data.optString("uri", null);
-            return uri != null ? uri : data.optString("url", null);
+            String uri = mData.optString("uri", null);
+            return uri != null ? uri : mData.optString("url", null);
         }
     }
 
     public static Intent getIntentForWebActivity(JSONObject message) throws JSONException {
         final String name = message.getString("name").toLowerCase();
         final JSONObject data = message.getJSONObject("data");
 
+        Log.w(LOGTAG, "Activity is: " + name);
         final WebActivityMapping mapping = activityMap.get(name);
+        if (mapping == null) {
+            Log.w(LOGTAG, "No mapping found!");
+            return null;
+        }
+
+        mapping.setData(data);
+
         final Intent intent = new Intent(mapping.getAction());
 
-        final String mime = mapping.getMime(data);
+        final String mime = mapping.getMime();
         if (!TextUtils.isEmpty(mime)) {
             intent.setType(mime);
         }
 
-        final String uri = mapping.getUri(data);
+        final String uri = mapping.getUri();
         if (!TextUtils.isEmpty(uri)) {
             intent.setData(Uri.parse(uri));
         }
 
-        mapping.putExtras(data, intent);
+        mapping.putExtras(intent);
 
         return intent;
     }
 
     private static class DialMapping extends WebActivityMapping {
         @Override
         public String getAction() {
             return Intent.ACTION_DIAL;
         }
 
         @Override
-        public String getUri(JSONObject data) throws JSONException {
-            return "tel:" + data.getString("number");
+        public String getUri() throws JSONException {
+            return "tel:" + mData.getString("number");
         }
     }
 
     private static class OpenMapping extends BaseMapping {
         @Override
         public String getAction() {
             return Intent.ACTION_VIEW;
         }
@@ -107,54 +128,94 @@ public final class WebActivityMapper {
 
     private static class PickMapping extends BaseMapping {
         @Override
         public String getAction() {
             return Intent.ACTION_GET_CONTENT;
         }
 
         @Override
-        public String getMime(JSONObject data) throws JSONException {
+        public String getMime() throws JSONException {
             // bug 1007112 - pick action needs a mimetype to work
-            String mime = data.optString("type", null);
+            String mime = mData.optString("type", null);
             return !TextUtils.isEmpty(mime) ? mime : "*/*";
         }
     }
 
     private static class SendMapping extends BaseMapping {
         @Override
         public String getAction() {
             return Intent.ACTION_SEND;
         }
 
         @Override
-        public void putExtras(JSONObject data, Intent intent) throws JSONException {
-            optPutExtra("text", Intent.EXTRA_TEXT, data, intent);
-            optPutExtra("html_text", Intent.EXTRA_HTML_TEXT, data, intent);
-            optPutExtra("stream", Intent.EXTRA_STREAM, data, intent);
+        public void putExtras(Intent intent) throws JSONException {
+            optPutExtra("text", Intent.EXTRA_TEXT, intent);
+            optPutExtra("html_text", Intent.EXTRA_HTML_TEXT, intent);
+            optPutExtra("stream", Intent.EXTRA_STREAM, intent);
         }
 
-        private static void optPutExtra(String key, String extraName, JSONObject data, Intent intent) {
-            final String extraValue = data.optString(key);
+        private void optPutExtra(String key, String extraName, Intent intent) {
+            final String extraValue = mData.optString(key);
             if (!TextUtils.isEmpty(extraValue)) {
                 intent.putExtra(extraName, extraValue);
             }
         }
     }
 
     private static class ViewMapping extends BaseMapping {
         @Override
         public String getAction() {
             return Intent.ACTION_VIEW;
         }
 
         @Override
-        public String getMime(JSONObject data) {
+        public String getMime() {
             // MozActivity adds a type 'url' here, we don't want to set the MIME to 'url'.
-            String type = data.optString("type", null);
+            String type = mData.optString("type", null);
             if ("url".equals(type) || "uri".equals(type)) {
                 return null;
             } else {
                 return type;
             }
         }
     }
+
+    private static class RecordMapping extends WebActivityMapping {
+        @Override
+        public String getAction() {
+            String type = mData.optString("type", null);
+            if ("photos".equals(type)) {
+                return "android.media.action.IMAGE_CAPTURE";
+            } else if ("videos".equals(type)) {
+                return "android.media.action.VIDEO_CAPTURE";
+            }
+            return null;
+        }
+
+        // Add an extra to specify where to save the picture/video.
+        @Override
+        public void putExtras(Intent intent) {
+            final String action = getAction();
+
+            final String dirType = action == "android.media.action.IMAGE_CAPTURE"
+                ? Environment.DIRECTORY_PICTURES
+                : Environment.DIRECTORY_MOVIES;
+
+            final String ext = action == "android.media.action.IMAGE_CAPTURE"
+                ? ".jpg"
+                : ".mp4";
+
+            File destDir = Environment.getExternalStoragePublicDirectory(dirType);
+
+            try {
+                File dest = File.createTempFile(
+                    "capture", /* prefix */
+                    ext,       /* suffix */
+                    destDir    /* directory */
+                );
+                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(dest));
+            } catch(Exception e) {
+                Log.w(LOGTAG, "Failed to add extra for " + action + " : " + e);
+            }
+        }
+    }
 }