Add support for the camera as a source for the file picker.

Determine whether to show the camera based on the accept type associated with
the input element.

Change-Id: I48fea76fbd7a1f3df3c87288f28e01a32d9e955e
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index 6af45f4..23a086a 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -2794,15 +2794,85 @@
      * The Object used to inform the WebView of the file to upload.
      */
     private ValueCallback<Uri> mUploadMessage;
+    private String mCameraFilePath;
 
-    void openFileChooser(ValueCallback<Uri> uploadMsg) {
+    void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
+
+        final String imageMimeType = "image/*";
+        final String imageSourceKey = "source";
+        final String imageSourceValueCamera = "camera";
+        final String imageSourceValueGallery = "gallery";
+
+        // image source can be 'gallery' or 'camera'.
+        String imageSource = "";
+
+        // We add the camera intent if there was no accept type (or '*/*') or 'image/*'.
+        boolean addCameraIntent = true;
+
         if (mUploadMessage != null) return;
         mUploadMessage = uploadMsg;
+
+        // Parse the accept type.
+        String params[] = acceptType.split(";");
+        String mimeType = params[0];
+
+        for (String p : params) {
+            String[] keyValue = p.split("=");
+            if (keyValue.length == 2) {
+                // Process key=value parameters.
+                if (imageSourceKey.equals(keyValue[0])) {
+                    imageSource = keyValue[1];
+                }
+            }
+        }
+
+        // This intent will display the standard OPENABLE file picker.
         Intent i = new Intent(Intent.ACTION_GET_CONTENT);
         i.addCategory(Intent.CATEGORY_OPENABLE);
-        i.setType("*/*");
-        BrowserActivity.this.startActivityForResult(Intent.createChooser(i,
-                getString(R.string.choose_upload)), FILE_SELECTED);
+
+        // Create an intent to add to the standard file picker that will
+        // capture an image from the camera. We'll combine this intent with
+        // the standard OPENABLE picker unless the web developer specifically
+        // requested the camera or gallery be opened by passing a parameter
+        // in the accept type.
+        Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+        File externalDataDir = Environment.getExternalStoragePublicDirectory(
+                Environment.DIRECTORY_DCIM);
+        File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
+                File.separator + "browser-photos");
+        cameraDataDir.mkdirs();
+        mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
+                System.currentTimeMillis() + ".jpg";
+        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
+
+        if (mimeType.equals(imageMimeType)) {
+            i.setType(imageMimeType);
+            if (imageSource.equals(imageSourceValueCamera)) {
+                // Specified 'image/*' and requested the camera, so go ahead and launch the camera
+                // directly.
+                BrowserActivity.this.startActivityForResult(cameraIntent, FILE_SELECTED);
+                return;
+            } else if (imageSource.equals(imageSourceValueGallery)) {
+                // Specified gallery as the source, so don't want to consider the camera.
+                addCameraIntent = false;
+            }
+        } else {
+            i.setType("*/*");
+        }
+
+        // Combine the chooser and the extra choices (like camera)
+        Intent chooser = new Intent(Intent.ACTION_CHOOSER);
+        chooser.putExtra(Intent.EXTRA_INTENT, i);
+
+        if (addCameraIntent) {
+            // Add the camera Intent
+            Intent[] choices = new Intent[1];
+            choices[0] = cameraIntent;
+            chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, choices);
+        }
+
+        chooser.putExtra(Intent.EXTRA_TITLE, getString(R.string.choose_upload));
+        BrowserActivity.this.startActivityForResult(chooser, FILE_SELECTED);
     }
 
     // -------------------------------------------------------------------------
@@ -3521,8 +3591,23 @@
                 if (null == mUploadMessage) break;
                 Uri result = intent == null || resultCode != RESULT_OK ? null
                         : intent.getData();
+
+                // As we ask the camera to save the result of the user taking
+                // a picture, the camera application does not return anything other
+                // than RESULT_OK. So we need to check whether the file we expected
+                // was written to disk in the in the case that we
+                // did not get an intent returned but did get a RESULT_OK. If it was,
+                // we assume that this result has came back from the camera.
+                if (result == null && intent == null && resultCode == RESULT_OK) {
+                    File cameraFile = new File(mCameraFilePath);
+                    if (cameraFile.exists()) {
+                        result = Uri.fromFile(cameraFile);
+                    }
+                }
+
                 mUploadMessage.onReceiveValue(result);
                 mUploadMessage = null;
+                mCameraFilePath = null;
                 break;
             default:
                 break;
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index b9942c0..79c4574 100644
--- a/src/com/android/browser/Tab.java
+++ b/src/com/android/browser/Tab.java
@@ -1173,9 +1173,9 @@
         }
 
         @Override
-        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
+        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
             if (mInForeground) {
-                mActivity.openFileChooser(uploadMsg);
+                mActivity.openFileChooser(uploadMsg, acceptType);
             } else {
                 uploadMsg.onReceiveValue(null);
             }