Bug 1355389 - Added one extra parameter to the message from the emitted event, parameter which indicates if the input element has multiple attribute. r=mcomella
authorAndrei Lazar <andrei.a.lazar@softvision.ro>
Fri, 13 Apr 2018 18:09:23 +0300
changeset 467672 376bf7bbb8285b179c3279bc14ab8dd054cc758f
parent 467671 5b68f5f5ed00691f9cab9ca9a42cd406d29ea57e
child 467673 c92f6b8e882beb93b0f7eb3448aa8132d6cdb28e
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmcomella
bugs1355389
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1355389 - Added one extra parameter to the message from the emitted event, parameter which indicates if the input element has multiple attribute. r=mcomella 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;
       }