Commit 83e34be9 authored by Clark DuVall's avatar Clark DuVall Committed by Commit Bot

[WebLayer] Fix flaky WebLayer camera permission test

Actually granting and revoking permissions caused a lot of problems,
instead this modifies the WebLayer implementation context to return the
permission we want.

Bug: 1021050
Change-Id: Ibd8dc3d42fc420b86060d8d8647df528aa0cef0e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1898626Reviewed-by: default avatarBo <boliu@chromium.org>
Commit-Queue: Clark DuVall <cduvall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712664}
parent 1de09a31
...@@ -30,8 +30,10 @@ import org.junit.runner.RunWith; ...@@ -30,8 +30,10 @@ import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.InMemorySharedPreferencesContext;
import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.MinAndroidSdkLevel;
import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.net.test.EmbeddedTestServer; import org.chromium.net.test.EmbeddedTestServer;
import org.chromium.weblayer.shell.InstrumentationActivity; import org.chromium.weblayer.shell.InstrumentationActivity;
...@@ -49,6 +51,7 @@ public class InputTypesTest { ...@@ -49,6 +51,7 @@ public class InputTypesTest {
private EmbeddedTestServer mTestServer; private EmbeddedTestServer mTestServer;
private File mTempFile; private File mTempFile;
private int mCameraPermission = PackageManager.PERMISSION_GRANTED;
private class FileIntentInterceptor implements InstrumentationActivity.IntentInterceptor { private class FileIntentInterceptor implements InstrumentationActivity.IntentInterceptor {
public Intent mLastIntent; public Intent mLastIntent;
...@@ -94,9 +97,7 @@ public class InputTypesTest { ...@@ -94,9 +97,7 @@ public class InputTypesTest {
new Handler().post(() -> { new Handler().post(() -> {
int[] results = new int[permissions.length]; int[] results = new int[permissions.length];
Arrays.fill(results, mResult); Arrays.fill(results, mResult);
if (mResult == PackageManager.PERMISSION_GRANTED) { mCameraPermission = mResult;
grantCameraPermission();
}
activity.onRequestPermissionsResult(requestCode, permissions, results); activity.onRequestPermissionsResult(requestCode, permissions, results);
mCallbackHelper.notifyCalled(); mCallbackHelper.notifyCalled();
}); });
...@@ -132,8 +133,22 @@ public class InputTypesTest { ...@@ -132,8 +133,22 @@ public class InputTypesTest {
mTestServer.addDefaultHandlers("weblayer/test/data"); mTestServer.addDefaultHandlers("weblayer/test/data");
Assert.assertTrue(mTestServer.start(0)); Assert.assertTrue(mTestServer.start(0));
InstrumentationActivity activity = InstrumentationActivity activity = mActivityTestRule.launchShell(new Bundle());
mActivityTestRule.launchShellWithUrl(mTestServer.getURL("/input_types.html")); TestThreadUtils.runOnUiThreadBlocking(() -> {
activity.createWebLayer(
new InMemorySharedPreferencesContext(activity.getApplication()) {
@Override
public int checkPermission(String permission, int pid, int uid) {
if (permission.equals(Manifest.permission.CAMERA)) {
return mCameraPermission;
}
return getBaseContext().checkPermission(permission, pid, uid);
}
},
null)
.get();
});
mActivityTestRule.navigateAndWait(mTestServer.getURL("/input_types.html"));
mTempFile = File.createTempFile("file", null); mTempFile = File.createTempFile("file", null);
activity.setIntentInterceptor(mIntentInterceptor); activity.setIntentInterceptor(mIntentInterceptor);
ActivityCompat.setPermissionCompatDelegate(mPermissionCompatDelegate); ActivityCompat.setPermissionCompatDelegate(mPermissionCompatDelegate);
...@@ -146,8 +161,6 @@ public class InputTypesTest { ...@@ -146,8 +161,6 @@ public class InputTypesTest {
@After @After
public void tearDown() { public void tearDown() {
mTempFile.delete(); mTempFile.delete();
// The test may have revoked camera permission, so grant it back now.
grantCameraPermission();
ActivityCompat.setPermissionCompatDelegate(null); ActivityCompat.setPermissionCompatDelegate(null);
} }
...@@ -165,9 +178,9 @@ public class InputTypesTest { ...@@ -165,9 +178,9 @@ public class InputTypesTest {
@Test @Test
@SmallTest @SmallTest
@MinAndroidSdkLevel(Build.VERSION_CODES.P) @MinAndroidSdkLevel(Build.VERSION_CODES.M)
public void testFileInputCameraPermissionGranted() { public void testFileInputCameraPermissionGranted() throws Exception {
revokeCameraPermission(); mCameraPermission = PackageManager.PERMISSION_DENIED;
mPermissionCompatDelegate.setResult(PackageManager.PERMISSION_GRANTED); mPermissionCompatDelegate.setResult(PackageManager.PERMISSION_GRANTED);
String id = "input_file"; String id = "input_file";
...@@ -184,9 +197,9 @@ public class InputTypesTest { ...@@ -184,9 +197,9 @@ public class InputTypesTest {
@Test @Test
@SmallTest @SmallTest
@MinAndroidSdkLevel(Build.VERSION_CODES.P) @MinAndroidSdkLevel(Build.VERSION_CODES.M)
public void testFileInputCameraPermissionDenied() { public void testFileInputCameraPermissionDenied() throws Exception {
revokeCameraPermission(); mCameraPermission = PackageManager.PERMISSION_DENIED;
mPermissionCompatDelegate.setResult(PackageManager.PERMISSION_DENIED); mPermissionCompatDelegate.setResult(PackageManager.PERMISSION_DENIED);
String id = "input_file"; String id = "input_file";
...@@ -326,20 +339,4 @@ public class InputTypesTest { ...@@ -326,20 +339,4 @@ public class InputTypesTest {
Assert.assertNotNull(contentIntent); Assert.assertNotNull(contentIntent);
return contentIntent; return contentIntent;
} }
@TargetApi(Build.VERSION_CODES.P)
private void revokeCameraPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) return;
String packageName = InstrumentationRegistry.getTargetContext().getPackageName();
InstrumentationRegistry.getInstrumentation().getUiAutomation().revokeRuntimePermission(
packageName, Manifest.permission.CAMERA);
}
@TargetApi(Build.VERSION_CODES.P)
private void grantCameraPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) return;
String packageName = InstrumentationRegistry.getTargetContext().getPackageName();
InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
packageName, Manifest.permission.CAMERA);
}
} }
...@@ -125,10 +125,10 @@ public class InstrumentationActivityTestRule extends ActivityTestRule<Instrument ...@@ -125,10 +125,10 @@ public class InstrumentationActivityTestRule extends ActivityTestRule<Instrument
} }
/** /**
* Starts the WebLayer activity with the given extras Bundle and completely loads the given URL * Starts the WebLayer activity with the given extras Bundle. This does not create and load
* (this calls navigateAndWait()). * WebLayer.
*/ */
public InstrumentationActivity launchShellWithUrl(String url, Bundle extras) { public InstrumentationActivity launchShell(Bundle extras) {
Intent intent = new Intent(Intent.ACTION_MAIN); Intent intent = new Intent(Intent.ACTION_MAIN);
intent.putExtras(extras); intent.putExtras(extras);
intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.addCategory(Intent.CATEGORY_LAUNCHER);
...@@ -136,8 +136,18 @@ public class InstrumentationActivityTestRule extends ActivityTestRule<Instrument ...@@ -136,8 +136,18 @@ public class InstrumentationActivityTestRule extends ActivityTestRule<Instrument
intent.setComponent( intent.setComponent(
new ComponentName(InstrumentationRegistry.getInstrumentation().getTargetContext(), new ComponentName(InstrumentationRegistry.getInstrumentation().getTargetContext(),
InstrumentationActivity.class)); InstrumentationActivity.class));
InstrumentationActivity activity = launchActivity(intent); return launchActivity(intent);
}
/**
* Starts the WebLayer activity with the given extras Bundle and completely loads the given URL
* (this calls navigateAndWait()).
*/
public InstrumentationActivity launchShellWithUrl(String url, Bundle extras) {
InstrumentationActivity activity = launchShell(extras);
Assert.assertNotNull(activity); Assert.assertNotNull(activity);
TestThreadUtils.runOnUiThreadBlocking(
() -> { activity.createWebLayer(activity.getApplication(), null).get(); });
if (url != null) navigateAndWait(url); if (url != null) navigateAndWait(url);
return activity; return activity;
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.weblayer.shell; package org.chromium.weblayer.shell;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
...@@ -24,6 +25,7 @@ import android.widget.RelativeLayout; ...@@ -24,6 +25,7 @@ import android.widget.RelativeLayout;
import org.chromium.weblayer.BrowserCallback; import org.chromium.weblayer.BrowserCallback;
import org.chromium.weblayer.BrowserController; import org.chromium.weblayer.BrowserController;
import org.chromium.weblayer.BrowserFragmentController; import org.chromium.weblayer.BrowserFragmentController;
import org.chromium.weblayer.ListenableFuture;
import org.chromium.weblayer.Profile; import org.chromium.weblayer.Profile;
import org.chromium.weblayer.UnsupportedVersionException; import org.chromium.weblayer.UnsupportedVersionException;
import org.chromium.weblayer.WebLayer; import org.chromium.weblayer.WebLayer;
...@@ -102,14 +104,20 @@ public class InstrumentationActivity extends FragmentActivity { ...@@ -102,14 +104,20 @@ public class InstrumentationActivity extends FragmentActivity {
mTopContentsContainer.addView(mUrlView, mTopContentsContainer.addView(mUrlView,
new RelativeLayout.LayoutParams( new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
if (savedInstanceState != null) {
try {
// This ensures asynchronous initialization of WebLayer on first start of activity.
// If activity is re-created during process restart, FragmentManager attaches // If activity is re-created during process restart, FragmentManager attaches
// BrowserFragment immediately, resulting in synchronous init. By the time this line // BrowserFragment immediately, resulting in synchronous init. By the time this line
// executes, the synchronous init has already happened. // executes, the synchronous init has already happened.
WebLayer.create(getApplication()) createWebLayer(getApplication(), savedInstanceState);
.addCallback(webLayer -> onWebLayerReady(savedInstanceState)); }
}
public ListenableFuture<WebLayer> createWebLayer(
Context appContext, Bundle savedInstanceState) {
try {
ListenableFuture<WebLayer> future = WebLayer.create(appContext);
future.addCallback(webLayer -> onWebLayerReady(savedInstanceState));
return future;
} catch (UnsupportedVersionException e) { } catch (UnsupportedVersionException e) {
throw new RuntimeException("Failed to initialize WebLayer", e); throw new RuntimeException("Failed to initialize WebLayer", e);
} }
......
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