Bug 1355389 - Added one extra parameter to the message from the emitted event, parameter which indicates if the input element has multiple attribute. r?sdaswani draft
authorAndrei Lazar <andrei.a.lazar@softvision.ro>
Fri, 13 Apr 2018 18:09:23 +0300
changeset 781740 0186709dc96793fc2b8acd959abcf1779638a626
parent 781727 8a94faa5cc60495da5d80d4b3c07bf5877d2e6d8
push id106405
push userbmo:andrei.a.lazar@softvision.ro
push dateFri, 13 Apr 2018 15:10:14 +0000
reviewerssdaswani
bugs1355389
milestone61.0a1
Bug 1355389 - Added one extra parameter to the message from the emitted event, parameter which indicates if the input element has multiple attribute. r?sdaswani MozReview-Commit-ID: CpRfgaYvV5y
mobile/android/base/java/org/mozilla/gecko/FilePicker.java
mobile/android/components/FilePicker.js
--- a/mobile/android/base/java/org/mozilla/gecko/FilePicker.java
+++ b/mobile/android/base/java/org/mozilla/gecko/FilePicker.java
@@ -1,49 +1,48 @@
 /* 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.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.permissions.PermissionBlock;
 import org.mozilla.gecko.permissions.Permissions;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
 
 import android.Manifest;
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.net.Uri;
 import android.os.Environment;
 import android.os.Parcelable;
-import android.provider.MediaStore;
 import android.support.annotation.NonNull;
 import android.text.TextUtils;
 import android.util.Log;
 
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 
 public class FilePicker implements BundleEventListener {
     private static final String LOGTAG = "GeckoFilePicker";
     private static FilePicker sFilePicker;
+    private static final int MODE_OPEN_MULTIPLE_ATTRIBUTE_VALUE = 3;
+    private static final int MODE_OPEN_SINGLE_ATTRIBUTE_VALUE = 0;
     private final Context context;
 
     public interface ResultHandler {
-        public void gotFile(String filename);
+        void gotFile(String filename);
     }
 
     public static void init(Context context) {
         if (sFilePicker == null) {
             sFilePicker = new FilePicker(context.getApplicationContext());
         }
     }
 
@@ -55,16 +54,18 @@ public class FilePicker implements Bundl
     @Override // BundleEventListener
     public void handleMessage(final String event, final GeckoBundle message,
                               final EventCallback callback) {
         if ("FilePicker:Show".equals(event)) {
             String mimeType = "*/*";
             final String mode = message.getString("mode", "");
             final int tabId = message.getInt("tabId", -1);
             final String title = message.getString("title", "");
+            final boolean isModeOpenMultiple = message.getInt("modeOpenAttribute", MODE_OPEN_SINGLE_ATTRIBUTE_VALUE)
+                    == MODE_OPEN_MULTIPLE_ATTRIBUTE_VALUE;
 
             if ("mimeType".equals(mode)) {
                 mimeType = message.getString("mimeType", "");
             } else if ("extension".equals(mode)) {
                 mimeType = GeckoAppShell.getMimeTypeFromExtensions(message.getString("extensions", ""));
             }
 
             final String[] requiredPermission = getPermissionsForMimeType(mimeType);
@@ -84,28 +85,28 @@ public class FilePicker implements Bundl
                 .andFallback(new Runnable() {
                     @Override
                     public void run() {
                         // In the fallback case, we still show the picker, just
                         // with the default file list.
                         // TODO: Figure out which permissions have been denied and use that
                         // knowledge for availPermissions. For now we assume we don't have any
                         // permissions at all (bug 1411014).
-                        showFilePickerAsync(title, "*/*", new String[0], new ResultHandler() {
+                        showFilePickerAsync(title, "*/*", new String[0], isModeOpenMultiple, new ResultHandler() {
                             @Override
                             public void gotFile(final String filename) {
                                 callback.sendSuccess(filename);
                             }
                         }, tabId);
                     }
                 })
                 .run(new Runnable() {
                     @Override
                     public void run() {
-                        showFilePickerAsync(title, finalMimeType, requiredPermission, new ResultHandler() {
+                        showFilePickerAsync(title, finalMimeType, requiredPermission, isModeOpenMultiple, new ResultHandler() {
                             @Override
                             public void gotFile(final String filename) {
                                 callback.sendSuccess(filename);
                             }
                         }, tabId);
                     }
                 });
         }
@@ -144,60 +145,63 @@ public class FilePicker implements Bundl
         Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
         intent.setType(mimeType);
         intent.addCategory(Intent.CATEGORY_OPENABLE);
         return intent;
     }
 
     private List<Intent> getIntentsForFilePicker(final @NonNull String mimeType,
                                                  final @NonNull String[] availPermissions,
+                                                 final boolean isModeOpenMultiple,
                                                  final FilePickerResultHandler fileHandler) {
         // The base intent to use for the file picker. Even if this is an implicit intent, Android will
         // still show a list of Activities that match this action/type.
         Intent baseIntent;
         // A HashMap of Activities the base intent will show in the chooser. This is used
         // to filter activities from other intents so that we don't show duplicates.
         HashMap<String, Intent> baseIntents = new HashMap<String, Intent>();
         // A list of other activities to show in the picker (and the intents to launch them).
         HashMap<String, Intent> intents = new HashMap<String, Intent> ();
 
+        baseIntent = getIntent(mimeType);
+        if (isModeOpenMultiple) {
+            baseIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+        }
+
         if (mimeType.startsWith("audio/")) {
-            baseIntent = getIntent(mimeType);
             addActivities(baseIntent, baseIntents, null);
-
             if (mimeType.equals("audio/*") &&
                     hasPermissionsForMimeType(mimeType, availPermissions)) {
                 // We also add a capture intent
                 Intent intent = IntentHelper.getAudioCaptureIntent();
                 addActivities(intent, intents, baseIntents);
             }
-        } else if (mimeType.startsWith("image/")) {
-            baseIntent = getIntent(mimeType);
+        } else if (mimeType.startsWith("image/") ) {
             addActivities(baseIntent, baseIntents, null);
-
             if (mimeType.equals("image/*") &&
                     hasPermissionsForMimeType(mimeType, availPermissions)) {
                 // We also add a capture intent
                 Intent intent = IntentHelper.getImageCaptureIntent(
                         new File(Environment.getExternalStorageDirectory(),
                                 fileHandler.generateImageName()));
                 addActivities(intent, intents, baseIntents);
             }
         } else if (mimeType.startsWith("video/")) {
-            baseIntent = getIntent(mimeType);
             addActivities(baseIntent, baseIntents, null);
-
             if (mimeType.equals("video/*") &&
                     hasPermissionsForMimeType(mimeType, availPermissions)) {
                 // We also add a capture intent
                 Intent intent = IntentHelper.getVideoCaptureIntent();
                 addActivities(intent, intents, baseIntents);
             }
         } else {
             baseIntent = getIntent("*/*");
+            if (isModeOpenMultiple) {
+                baseIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+            }
             addActivities(baseIntent, baseIntents, null);
 
             Intent intent;
             if (hasPermissionsForMimeType("audio/*", availPermissions)) {
                 intent = IntentHelper.getAudioCaptureIntent();
                 addActivities(intent, intents, baseIntents);
             }
             if (hasPermissionsForMimeType("image/*", availPermissions)) {
@@ -240,18 +244,19 @@ public class FilePicker implements Bundl
     /* Gets an intent that can open a particular mimetype. Will show a prompt with a list
      * of Activities that can handle the mietype. Asynchronously calls the handler when
      * one of the intents is selected. If the caller passes in null for the handler, will still
      * prompt for the activity, but will throw away the result.
      */
     private Intent getFilePickerIntent(String title,
                                        final @NonNull String mimeType,
                                        final @NonNull String[] availPermissions,
+                                       final boolean isModeOpenMultiple,
                                        final FilePickerResultHandler fileHandler) {
-        final List<Intent> intents = getIntentsForFilePicker(mimeType, availPermissions, fileHandler);
+        final List<Intent> intents = getIntentsForFilePicker(mimeType, availPermissions, isModeOpenMultiple, fileHandler);
 
         if (intents.size() == 0) {
             Log.i(LOGTAG, "no activities for the file picker!");
             return null;
         }
 
         final Intent base = intents.remove(0);
 
@@ -269,20 +274,21 @@ public class FilePicker implements Bundl
     }
 
     /* Allows the user to pick an activity to load files from using a list prompt. Then opens the activity and
      * sends the file returned to the passed in handler. If a null handler is passed in, will still
      * pick and launch the file picker, but will throw away the result.
      */
     protected void showFilePickerAsync(final String title, final @NonNull String mimeType,
                                        final @NonNull String[] availPermissions,
+                                       final boolean isModeOpenMultiple,
                                        final ResultHandler handler, final int tabId) {
         final FilePickerResultHandler fileHandler =
                 new FilePickerResultHandler(handler, context, tabId);
-        final Intent intent = getFilePickerIntent(title, mimeType, availPermissions, fileHandler);
+        final Intent intent = getFilePickerIntent(title, mimeType, availPermissions, isModeOpenMultiple, fileHandler);
         final Activity currentActivity =
                 GeckoActivityMonitor.getInstance().getCurrentActivity();
 
         if (intent == null || currentActivity == null) {
             handler.gotFile("");
             return;
         }
 
--- a/mobile/android/components/FilePicker.js
+++ b/mobile/android/components/FilePicker.js
@@ -217,16 +217,19 @@ FilePicker.prototype = {
       msg.mimeType = "*/*";
     } else if (this._extensionsFilter) {
       msg.mode = "extension";
       msg.extensions = this._extensionsFilter;
     } else {
       msg.mode = "mimeType";
       msg.mimeType = this._mimeTypeFilter;
     }
+    if (this._mode) {
+        msg.modeOpenAttribute = this._mode;
+    }
 
     EventDispatcher.instance.sendRequestForResult(msg).then(file => {
       this._filePath = file || null;
       this._promptActive = false;
 
       if (!file) {
         return;
       }