Backed out 2 changesets (bug 1406903) for causing bug 1502721. a=backout
authorSebastian Hengst <archaeopteryx@coole-files.de>
Thu, 08 Nov 2018 18:34:39 +0200
changeset 501122 194d3585f3d567c047245c842ac5ee6b6390b474
parent 501121 22b88f92d8d43a4327f177bf4f83acb968dfa954
child 501123 54bc3b67f80112dbd19242b388b1a93f503b19e1
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1406903, 1502721
milestone64.0
backs out8a510f2052d3e6be52a72dc045a2ce03a0a952ae
05d8e65ff651affb56489cce5910f57939926561
Backed out 2 changesets (bug 1406903) for causing bug 1502721. a=backout Backed out changeset 8a510f2052d3 (bug 1406903) Backed out changeset 05d8e65ff651 (bug 1406903)
mobile/android/base/AndroidManifest.xml.in
mobile/android/base/java/org/mozilla/gecko/IntentHelper.java
mobile/android/base/java/org/mozilla/gecko/LauncherActivity.java
mobile/android/components/ContentDispatchChooser.js
mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ContentUriUtils.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/FileUtils.java
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -94,17 +94,16 @@
             </intent-filter>
             <intent-filter>
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.BROWSABLE" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:scheme="file" />
                 <data android:scheme="http" />
                 <data android:scheme="https" />
-                <data android:scheme="content" />
                 <data android:mimeType="text/html"/>
                 <data android:mimeType="text/plain"/>
                 <data android:mimeType="application/xhtml+xml"/>
                 <data android:mimeType="image/svg+xml"/>
             </intent-filter>
 
             <meta-data android:name="com.sec.minimode.icon.portrait.normal"
                        android:resource="@drawable/icon"/>
--- a/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java
@@ -6,17 +6,16 @@
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.overlays.ui.ShareDialog;
 import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.util.ActivityResultHandler;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
-import org.mozilla.gecko.util.FileUtils;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.IntentUtils;
 import org.mozilla.gecko.util.StrictModeContext;
 import org.mozilla.gecko.widget.ExternalIntentDuringPrivateBrowsingPromptFragment;
 
 import android.app.Activity;
 import android.content.ClipData;
 import android.content.Context;
@@ -36,17 +35,16 @@ import android.webkit.MimeTypeMap;
 import java.io.File;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.List;
 import java.util.Locale;
 
 import static org.mozilla.gecko.Tabs.INTENT_EXTRA_SESSION_UUID;
 import static org.mozilla.gecko.Tabs.INTENT_EXTRA_TAB_ID;
-import static org.mozilla.gecko.util.FileUtils.getFilePathFromUri;
 
 public final class IntentHelper implements BundleEventListener {
 
     private static final String LOGTAG = "GeckoIntentHelper";
     private static final String[] GECKO_EVENTS = {
         // Need to be on Gecko thread for synchronous callback.
         "Intent:GetHandlers",
     };
@@ -506,23 +504,16 @@ public final class IntentHelper implemen
         } catch (final URISyntaxException e) {
             // Don't log the exception to prevent leaking URIs.
             Log.w(LOGTAG, "Unable to parse Intent URI - loading about:neterror");
             errorResponse.putBoolean("isFallback", false);
             callback.sendError(errorResponse);
             return;
         }
 
-        if (FileUtils.isContentUri(uri)) {
-            errorResponse.putString("uri", getFilePathFromUri(getContext(), intent.getData()));
-            errorResponse.putBoolean("isFallback", true);
-            callback.sendError(errorResponse);
-            return;
-        }
-
         // For this flow, we follow Chrome's lead:
         //   https://developer.chrome.com/multidevice/android/intents
         final String fallbackUrl = intent.getStringExtra(EXTRA_BROWSER_FALLBACK_URL);
         if (isFallbackUrlValid(fallbackUrl)) {
             errorResponse.putString("uri", fallbackUrl);
             errorResponse.putBoolean("isFallback", true);
             // Opens the page in JS.
             callback.sendError(errorResponse);
--- a/mobile/android/base/java/org/mozilla/gecko/LauncherActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/LauncherActivity.java
@@ -12,17 +12,16 @@ import android.net.Uri;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.customtabs.CustomTabsIntent;
 import android.util.Log;
 
 import org.mozilla.gecko.home.HomeConfig;
 import org.mozilla.gecko.mma.MmaDelegate;
 import org.mozilla.gecko.switchboard.SwitchBoard;
-import org.mozilla.gecko.util.FileUtils;
 import org.mozilla.gecko.webapps.WebAppActivity;
 import org.mozilla.gecko.webapps.WebAppIndexer;
 import org.mozilla.gecko.customtabs.CustomTabsActivity;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.mozglue.SafeIntent;
 import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.tabqueue.TabQueueHelper;
 import org.mozilla.gecko.tabqueue.TabQueueService;
@@ -38,17 +37,16 @@ import static org.mozilla.gecko.deeplink
 import static org.mozilla.gecko.deeplink.DeepLinkContract.LINK_PREFERENCES_GENERAL;
 import static org.mozilla.gecko.deeplink.DeepLinkContract.LINK_PREFERENCES_NOTIFICATIONS;
 import static org.mozilla.gecko.deeplink.DeepLinkContract.LINK_PREFERENCES_PRIAVACY;
 import static org.mozilla.gecko.deeplink.DeepLinkContract.LINK_PREFERENCES_SEARCH;
 import static org.mozilla.gecko.deeplink.DeepLinkContract.LINK_SAVE_AS_PDF;
 import static org.mozilla.gecko.deeplink.DeepLinkContract.LINK_SIGN_UP;
 import static org.mozilla.gecko.deeplink.DeepLinkContract.SUMO_DEFAULT_BROWSER;
 import static org.mozilla.gecko.deeplink.DeepLinkContract.LINK_FXA_SIGNIN;
-import static org.mozilla.gecko.util.FileUtils.isContentUri;
 
 import org.mozilla.gecko.deeplink.DeepLinkContract;
 
 /**
  * Activity that receives incoming Intents and dispatches them to the appropriate activities (e.g. browser, custom tabs, web app).
  */
 public class LauncherActivity extends Activity {
     private static final String TAG = LauncherActivity.class.getSimpleName();
@@ -64,19 +62,18 @@ public class LauncherActivity extends Ac
             dispatchDeepLink(safeIntent);
 
         } else if (isShutdownIntent(safeIntent)) {
             dispatchShutdownIntent();
         // Is this web app?
         } else if (isWebAppIntent(safeIntent)) {
             dispatchWebAppIntent();
 
-        // If it's not a view intent, it won't be a custom tabs intent either, and for content URI
-        // let's handle only with normal tabs for the moment
-        } else if (!isViewIntentWithURL(safeIntent) || isContentUri(safeIntent.getData())) {
+        // If it's not a view intent, it won't be a custom tabs intent either. Just launch!
+        } else if (!isViewIntentWithURL(safeIntent)) {
             dispatchNormalIntent();
 
         } else if (isCustomTabsIntent(safeIntent) && isCustomTabsEnabled(this) ) {
             dispatchCustomTabsIntent();
 
         // Can we dispatch this VIEW action intent to the tab queue service?
         } else if (!safeIntent.getBooleanExtra(BrowserContract.SKIP_TAB_QUEUE_FLAG, false)
                 && TabQueueHelper.TAB_QUEUE_ENABLED
--- a/mobile/android/components/ContentDispatchChooser.js
+++ b/mobile/android/components/ContentDispatchChooser.js
@@ -40,62 +40,59 @@ ContentDispatchChooser.prototype =
 
   ask: function ask(aHandler, aWindowContext, aURI, aReason) {
     let window = null;
     try {
       if (aWindowContext)
         window = aWindowContext.getInterface(Ci.nsIDOMWindow);
     } catch (e) { /* it's OK to not have a window */ }
 
-    if (!aURI.schemeIs("content")) {
-
-      // The current list is based purely on the scheme. Redo the query using the url to get more
-      // specific results.
-      aHandler = this.protoSvc.getProtocolHandlerInfoFromOS(aURI.spec, {});
-
-      if (aHandler.possibleApplicationHandlers.length > 1) {
+    // The current list is based purely on the scheme. Redo the query using the url to get more
+    // specific results.
+    aHandler = this.protoSvc.getProtocolHandlerInfoFromOS(aURI.spec, {});
 
-        // The first handler in the set is the Android Application Chooser (which will fall back to a default if one is set)
-        // If we have more than one option, let the OS handle showing a list (if needed).
-        aHandler.launchWithURI(aURI, aWindowContext);
-        this._closeBlankWindow(window);
-        return;
-      }
-    }
-    // xpcshell tests do not have an Android Bridge but we require Android
-    // Bridge when using Messaging so we guard against this case. xpcshell
-    // tests also do not have a window, so we use this state to guard.
-    let win = this._getChromeWin();
-    if (!win) {
-      return;
-    }
-
-    let msg = {
-      type: "Intent:OpenNoHandler",
-      uri: aURI.spec,
-    };
-
-    EventDispatcher.instance.sendRequestForResult(msg).then(() => {
-      // Java opens an app on success: take no action.
+    // The first handler in the set is the Android Application Chooser (which will fall back to a default if one is set)
+    // If we have more than one option, let the OS handle showing a list (if needed).
+    if (aHandler.possibleApplicationHandlers.length > 1) {
+      aHandler.launchWithURI(aURI, aWindowContext);
       this._closeBlankWindow(window);
 
-    }, (data) => {
-      if (data.isFallback) {
-        // We always want to open a fallback url
-        window.location.href = data.uri;
+    } else {
+      // xpcshell tests do not have an Android Bridge but we require Android
+      // Bridge when using Messaging so we guard against this case. xpcshell
+      // tests also do not have a window, so we use this state to guard.
+      let win = this._getChromeWin();
+      if (!win) {
         return;
       }
 
-      // We couldn't open this. If this was from a click, it's likely that we just
-      // want this to fail silently. If the user entered this on the address bar, though,
-      // we want to show the neterror page.
-      let dwu = window.windowUtils;
-      let millis = dwu.millisSinceLastUserInput;
-      if (millis < 0 || millis >= 1000) {
-        window.docShell.displayLoadError(Cr.NS_ERROR_UNKNOWN_PROTOCOL, aURI, null);
-      } else {
+      let msg = {
+        type: "Intent:OpenNoHandler",
+        uri: aURI.spec,
+      };
+
+      EventDispatcher.instance.sendRequestForResult(msg).then(() => {
+        // Java opens an app on success: take no action.
         this._closeBlankWindow(window);
-      }
-    });
+
+      }, (data) => {
+        if (data.isFallback) {
+          // We always want to open a fallback url
+          window.location.href = data.uri;
+          return;
+        }
+
+        // We couldn't open this. If this was from a click, it's likely that we just
+        // want this to fail silently. If the user entered this on the address bar, though,
+        // we want to show the neterror page.
+        let dwu = window.windowUtils;
+        let millis = dwu.millisSinceLastUserInput;
+        if (millis < 0 || millis >= 1000) {
+          window.docShell.displayLoadError(Cr.NS_ERROR_UNKNOWN_PROTOCOL, aURI, null);
+        } else {
+          this._closeBlankWindow(window);
+        }
+      });
+    }
   },
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentDispatchChooser]);
deleted file mode 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/ContentUriUtils.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2007-2008 OpenIntents.org
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.mozilla.gecko.util;
-
-import android.content.ContentUris;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Environment;
-import android.provider.DocumentsContract;
-import android.provider.MediaStore;
-
-/**
- * Based on https://github.com/iPaulPro/aFileChooser/blob/48d65e6649d4201407702b0390326ec9d5c9d17c/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java
- */
-public class ContentUriUtils {
-    /**
-     * Get a file path from a Uri. This will get the the path for Storage Access
-     * Framework Documents, as well as the _data field for the MediaStore and
-     * other file-based ContentProviders.<br>
-     * <br>
-     * Callers should check whether the path is local before assuming it
-     * represents a local file.
-     *
-     * @param context The context.
-     * @param uri The Uri to query.
-     * @author paulburke
-     */
-    public static String getPath(final Context context, final Uri uri) {
-
-        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
-
-        // DocumentProvider
-        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
-            // ExternalStorageProvider
-            if (isExternalStorageDocument(uri)) {
-                final String docId = DocumentsContract.getDocumentId(uri);
-                final String[] split = docId.split(":");
-                final String type = split[0];
-
-                if ("primary".equalsIgnoreCase(type)) {
-                    return Environment.getExternalStorageDirectory() + "/" + split[1];
-                }
-
-                // TODO handle non-primary volumes
-            }
-            // DownloadsProvider
-            else if (isDownloadsDocument(uri)) {
-
-                final String id = DocumentsContract.getDocumentId(uri);
-                final Uri contentUri = ContentUris.withAppendedId(
-                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
-
-                return getDataColumn(context, contentUri, null, null);
-            }
-            // MediaProvider
-            else if (isMediaDocument(uri)) {
-                final String docId = DocumentsContract.getDocumentId(uri);
-                final String[] split = docId.split(":");
-                final String type = split[0];
-
-                Uri contentUri = null;
-                if ("image".equals(type)) {
-                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
-                } else if ("video".equals(type)) {
-                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
-                } else if ("audio".equals(type)) {
-                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
-                }
-
-                final String selection = "_id=?";
-                final String[] selectionArgs = new String[] {
-                        split[1]
-                };
-
-                return getDataColumn(context, contentUri, selection, selectionArgs);
-            }
-        }
-        // MediaStore (and general)
-        else if ("content".equalsIgnoreCase(uri.getScheme())) {
-
-            // Return the remote address
-            if (isGooglePhotosUri(uri))
-                return uri.getLastPathSegment();
-
-            return getDataColumn(context, uri, null, null);
-        }
-        // File
-        else if ("file".equalsIgnoreCase(uri.getScheme())) {
-            return uri.getPath();
-        }
-
-        return null;
-    }
-
-    /**
-     * Get the value of the data column for this Uri. This is useful for
-     * MediaStore Uris, and other file-based ContentProviders.
-     *
-     * @param context The context.
-     * @param uri The Uri to query.
-     * @param selection (Optional) Filter used in the query.
-     * @param selectionArgs (Optional) Selection arguments used in the query.
-     * @return The value of the _data column, which is typically a file path.
-     * @author paulburke
-     */
-    private static String getDataColumn(Context context, Uri uri, String selection,
-                                        String[] selectionArgs) {
-
-        Cursor cursor = null;
-        final String column = "_data";
-        final String[] projection = {
-                column
-        };
-
-        try {
-            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
-                    null);
-            if (cursor != null && cursor.moveToFirst()) {
-                final int column_index = cursor.getColumnIndexOrThrow(column);
-                return cursor.getString(column_index);
-            }
-        } finally {
-            if (cursor != null)
-                cursor.close();
-        }
-        return null;
-    }
-
-    /**
-     * @param uri The Uri to check.
-     * @return Whether the Uri authority is ExternalStorageProvider.
-     * @author paulburke
-     */
-    public static boolean isExternalStorageDocument(Uri uri) {
-        return "com.android.externalstorage.documents".equals(uri.getAuthority());
-    }
-
-    /**
-     * @param uri The Uri to check.
-     * @return Whether the Uri authority is DownloadsProvider.
-     * @author paulburke
-     */
-    public static boolean isDownloadsDocument(Uri uri) {
-        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
-    }
-
-    /**
-     * @param uri The Uri to check.
-     * @return Whether the Uri authority is MediaProvider.
-     * @author paulburke
-     */
-    public static boolean isMediaDocument(Uri uri) {
-        return "com.android.providers.media.documents".equals(uri.getAuthority());
-    }
-
-    /**
-     * @param uri The Uri to check.
-     * @return Whether the Uri authority is Google Photos.
-     */
-    public static boolean isGooglePhotosUri(Uri uri) {
-        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
-    }
-}
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/FileUtils.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/FileUtils.java
@@ -1,16 +1,14 @@
 /* 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.util;
 
-import android.content.Context;
-import android.net.Uri;
 import android.util.Log;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.FilenameFilter;
@@ -24,23 +22,18 @@ import java.util.Random;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.mozilla.gecko.annotation.RobocopTarget;
 
-import static org.mozilla.gecko.util.ContentUriUtils.getPath;
-
 public class FileUtils {
     private static final String LOGTAG = "GeckoFileUtils";
-    private static final String FILE_SCHEME = "file";
-    private static final String CONTENT_SCHEME = "content";
-    private static final String FILE_ABSOLUTE_URI = FILE_SCHEME + "://%s";
 
     /*
     * A basic Filter for checking a filename and age.
     **/
     static public class NameAndAgeFilter implements FilenameFilter {
         final private String mName;
         final private double mMaxAge;
 
@@ -281,21 +274,9 @@ public class FileUtils {
         }
         File result;
         Random random = new Random();
         do {
             result = new File(directory, prefix + random.nextInt());
         } while (!result.mkdirs());
         return result;
     }
-
-    public static String getFilePathFromUri(final Context context, final Uri uri) {
-        return String.format(FILE_ABSOLUTE_URI, getPath(context, uri));
-    }
-
-    public static boolean isContentUri(Uri uri) {
-        return uri != null && uri.getScheme() != null && CONTENT_SCHEME.equals(uri.getScheme());
-    }
-
-    public static boolean isContentUri(String sUri) {
-        return sUri != null && sUri.startsWith(CONTENT_SCHEME);
-    }
 }