Commit f10e7b2e authored by Michael Thiessen's avatar Michael Thiessen Committed by Commit Bot

Remove BROWSABLE category from content URI intent filters

Chrome does not allow sites to navigate to content URIs, but the Google
Search app parses and re-sends URIs, including content URIs, sent to it.
This allows intents sent to GSA to bypass this content URI restriction.

In order to prevent this bypass, we can simply remove the BROWSABLE
category from our intent filters that handle content URIs, as we don't
need to handle content URIs coming from other browsers.

This change also adds tests for our Intent Filters, which, as far as I
can tell, were untested before this change. I also fixed a few edge
cases with the intent filters I modified as revealed by the tests.

Note that for some intent filters I removed the content scheme
altogether. In these cases the filter wasn't useful because a file
extension was specified, making it impossible for the content scheme to
be matched.

I also suppressed some AppLinkUrlErrors: "Error: Activity supporting
ACTION_VIEW is not set as BROWSABLE". This isn't an error. I don't know
why lint flags it other than to make sure you know what you're doing and
don't accidentally prevent browsers from launching your View intent
Activity.

Bug: 1092453
Change-Id: I167d2e41c0d9c75c0b80a5a1778817b42016e21b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2321522
Commit-Queue: Michael Thiessen <mthiesse@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarMin Qin <qinmin@chromium.org>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796040}
parent 6c41c128
...@@ -18,6 +18,7 @@ chrome_test_java_sources = [ ...@@ -18,6 +18,7 @@ chrome_test_java_sources = [
"javatests/src/org/chromium/chrome/browser/FocusedEditableTextFieldZoomTest.java", "javatests/src/org/chromium/chrome/browser/FocusedEditableTextFieldZoomTest.java",
"javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java", "javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java",
"javatests/src/org/chromium/chrome/browser/InstalledAppTest.java", "javatests/src/org/chromium/chrome/browser/InstalledAppTest.java",
"javatests/src/org/chromium/chrome/browser/IntentFilterUnitTest.java",
"javatests/src/org/chromium/chrome/browser/IntentHandlerTest.java", "javatests/src/org/chromium/chrome/browser/IntentHandlerTest.java",
"javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java", "javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java",
"javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java", "javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java",
......
...@@ -210,17 +210,17 @@ by a child template that "extends" this file. ...@@ -210,17 +210,17 @@ by a child template that "extends" this file.
{% block common_view_intent_shared_filter_body %} {% block common_view_intent_shared_filter_body %}
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
{% if channel in ['stable', 'default'] %}<data android:scheme="googlechrome" />{% endif %} {% if channel in ['stable', 'default'] %}<data android:scheme="googlechrome" />{% endif %}
<data android:scheme="http" /> <data android:scheme="http" />
<data android:scheme="https" /> <data android:scheme="https" />
<data android:scheme="about" /> <data android:scheme="about" />
<data android:scheme="javascript" /> <data android:scheme="javascript" />
{% endblock %} {% endblock %}
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter> </intent-filter>
<!-- Same filter as above but with MIME types. Intents that <!-- Same filter as above but with MIME types. Intents that
do not specify a MIME type won't match. --> do not specify a MIME type won't match. -->
<intent-filter> <intent-filter tools:ignore="AppLinkUrlError">
{{ self.common_view_intent_shared_filter_body() }} {{ self.common_view_intent_shared_filter_body() }}
<data android:scheme="content" /> <data android:scheme="content" />
<data android:mimeType="text/html"/> <data android:mimeType="text/html"/>
...@@ -231,7 +231,13 @@ by a child template that "extends" this file. ...@@ -231,7 +231,13 @@ by a child template that "extends" this file.
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file"/> <data android:scheme="file"/>
<data android:mimeType="multipart/related"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content"/> <data android:scheme="content"/>
<data android:mimeType="multipart/related"/> <data android:mimeType="multipart/related"/>
</intent-filter> </intent-filter>
...@@ -248,10 +254,11 @@ by a child template that "extends" this file. ...@@ -248,10 +254,11 @@ by a child template that "extends" this file.
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file"/> <data android:scheme="file"/>
<data android:scheme="content"/>
<data android:host="*" /> <data android:host="*" />
<data android:pathPattern="/.*\\.mhtml"/> {% for i in range(10) %}
<data android:pathPattern="/.*\\.mht"/> <data android:pathPattern="/.*{{ '\\\\..*' * i }}\\.mhtml" />
<data android:pathPattern="/.*{{ '\\\\..*' * i }}\\.mht" />
{% endfor %}
{% endblock %} {% endblock %}
</intent-filter> </intent-filter>
<!-- Same filter as above but with mimeType="*/*". Used for <!-- Same filter as above but with mimeType="*/*". Used for
...@@ -263,21 +270,24 @@ by a child template that "extends" this file. ...@@ -263,21 +270,24 @@ by a child template that "extends" this file.
<!-- Web Bundles (.wbn) support --> <!-- Web Bundles (.wbn) support -->
{% if channel in ['dev', 'canary', 'default'] %} {% if channel in ['dev', 'canary', 'default'] %}
<intent-filter> <intent-filter>
{% block wbn_view_intent_shared_filter_body %}
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" /> <data android:scheme="file" />
<data android:scheme="content" />
<data android:mimeType="*/*" />
<data android:host="*" /> <data android:host="*" />
{% for i in range(10) %} {% for i in range(10) %}
<data android:pathPattern="/.*{{ '\\\\..*' * i }}\\.wbn" /> <data android:pathPattern="/.*{{ '\\\\..*' * i }}\\.wbn" />
{% endfor %} {% endfor %}
{% endblock %}
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
{{ self.wbn_view_intent_shared_filter_body() }}
<data android:mimeType="*/*"/>
</intent-filter>
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="content" /> <data android:scheme="content" />
<data android:mimeType="application/webbundle" /> <data android:mimeType="application/webbundle" />
</intent-filter> </intent-filter>
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import androidx.test.filters.SmallTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.ContextUtils;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Batch;
/**
* Unit tests for Intent Filters in chrome/android/java/AndroidManifest.xml
*/
@RunWith(BaseJUnit4ClassRunner.class)
@Batch(Batch.UNIT_TESTS)
public class IntentFilterUnitTest {
private static final Uri HTTPS_URI = Uri.parse("https://www.example.com/index.html");
private static final Uri CONTENT_URI = Uri.parse("content://package/path/id");
private static final Uri HTML_URI = Uri.parse("file:///path/filename.html");
private static final Uri MHTML_URI = Uri.parse("file:///path/to/.file/site.mhtml");
private static final Uri WBN_URI = Uri.parse("file:///path/to/.file/site.wbn");
// Some apps (like ShareIt) specify a file URI along with a mime type. We don't care what
// this mime type is and trust the file extension.
private static final String ANY_MIME = "bad/mime";
private Intent mIntent;
private PackageManager mPm;
@Before
public void setUp() {
mPm = ContextUtils.getApplicationContext().getPackageManager();
mIntent = new Intent();
mIntent.setPackage(ContextUtils.getApplicationContext().getPackageName());
}
private void verifyIntent(boolean supported) {
ComponentName component = mIntent.resolveActivity(mPm);
if (supported) {
Assert.assertNotNull(component);
} else {
Assert.assertNull(component);
}
}
@Test
@SmallTest
public void testIgnoredMimeType() {
mIntent.setDataAndType(CONTENT_URI, "application/octet-stream");
verifyIntent(false);
mIntent.addCategory(Intent.CATEGORY_BROWSABLE);
verifyIntent(false);
}
@Test
@SmallTest
public void testHttpsUri() {
mIntent.setData(HTTPS_URI);
verifyIntent(true);
mIntent.addCategory(Intent.CATEGORY_BROWSABLE);
verifyIntent(true);
}
@Test
@SmallTest
public void testHtmlFileUri() {
mIntent.setData(HTML_URI);
verifyIntent(false);
mIntent.setType("text/html");
verifyIntent(false);
mIntent.addCategory(Intent.CATEGORY_BROWSABLE);
verifyIntent(false);
}
@Test
@SmallTest
public void testHtmlContentUri() {
mIntent.setDataAndType(CONTENT_URI, "text/html");
verifyIntent(true);
mIntent.addCategory(Intent.CATEGORY_BROWSABLE);
verifyIntent(false);
}
@Test
@SmallTest
public void testMhtmlUri() {
mIntent.setData(MHTML_URI);
verifyIntent(true);
// Note that calling setType() would clear the Data...
mIntent.setDataAndType(MHTML_URI, ANY_MIME);
verifyIntent(true);
mIntent.addCategory(Intent.CATEGORY_BROWSABLE);
verifyIntent(true);
}
@Test
@SmallTest
public void testContentMhtmlUri() {
mIntent.setDataAndType(CONTENT_URI, "multipart/related");
verifyIntent(true);
mIntent.addCategory(Intent.CATEGORY_BROWSABLE);
verifyIntent(false);
}
@Test
@SmallTest
public void testWbnUri() {
mIntent.setData(WBN_URI);
verifyIntent(true);
// Note that calling setType() would clear the Data...
mIntent.setDataAndType(WBN_URI, ANY_MIME);
verifyIntent(true);
mIntent.addCategory(Intent.CATEGORY_BROWSABLE);
verifyIntent(true);
}
@Test
@SmallTest
public void testContentWbnUri() {
mIntent.setDataAndType(CONTENT_URI, "application/webbundle");
verifyIntent(true);
mIntent.addCategory(Intent.CATEGORY_BROWSABLE);
verifyIntent(false);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment