blob: ca982875370cb5f045d1dd47b28ecbc1c74e7e2c [file] [log] [blame]
// Copyright 2018 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.firstrun;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserManager;
import android.support.customtabs.CustomTabsIntent;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.ShortcutHelper;
import org.chromium.chrome.browser.document.ChromeLauncherActivity;
import org.chromium.chrome.browser.searchwidget.SearchActivity;
import org.chromium.chrome.browser.webapps.WebappLauncherActivity;
import org.chromium.webapk.lib.client.WebApkValidator;
import org.chromium.webapk.lib.common.WebApkConstants;
import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
import org.chromium.webapk.test.WebApkTestHelper;
/** JUnit tests for first run triggering code. */
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public final class FirstRunIntegrationUnitTest {
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule();
private Context mContext;
private ShadowApplication mShadowApplication;
@Before
public void setUp() throws InterruptedException {
mContext = RuntimeEnvironment.application;
mShadowApplication = ShadowApplication.getInstance();
UserManager userManager = Mockito.mock(UserManager.class);
Mockito.when(userManager.isDemoUser()).thenReturn(false);
mShadowApplication.setSystemService(Context.USER_SERVICE, userManager);
FirstRunStatus.setFirstRunFlowComplete(false);
WebApkValidator.disableValidationForTesting();
}
/** Checks that the intent component is one of the provided classes. */
private boolean checkIntentComponentClassOneOf(Intent intent, Class[] componentClassOptions) {
if (intent == null || intent.getComponent() == null) return false;
String componentClassName = intent.getComponent().getClassName();
for (Class componentClassOption : componentClassOptions) {
if (componentClassOption.getName().equals(componentClassName)) return true;
}
return false;
}
/**
* Checks that intent is either for {@link FirstRunActivity} or
* {@link TabbedModeFirstRunActivity}.
*/
private boolean checkIntentIsForFre(Intent intent) {
return checkIntentComponentClassOneOf(
intent, new Class[] {FirstRunActivity.class, TabbedModeFirstRunActivity.class});
}
/** Builds activity using the component class name from the provided intent. */
@SuppressWarnings("unchecked")
private static void buildActivityWithClassNameFromIntent(Intent intent) {
Class<? extends Activity> activityClass = null;
try {
activityClass =
(Class<? extends Activity>) Class.forName(intent.getComponent().getClassName());
} catch (ClassNotFoundException e) {
Assert.fail();
}
Robolectric.buildActivity(activityClass, intent).create();
}
/**
* Checks that either {@link FirstRunActivity} or {@link TabbedModeFirstRunActivity}
* was launched.
*/
private void assertFirstRunActivityLaunched() {
Intent launchedIntent = mShadowApplication.getNextStartedActivity();
Assert.assertNotNull(launchedIntent);
Assert.assertTrue(checkIntentIsForFre(launchedIntent));
}
@Test
public void testGenericViewIntentGoesToFirstRun() {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://test.com"));
intent.setPackage(mContext.getPackageName());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Activity launcherActivity =
Robolectric.buildActivity(ChromeLauncherActivity.class, intent).create().get();
assertFirstRunActivityLaunched();
Assert.assertTrue(launcherActivity.isFinishing());
}
@Test
public void testRedirectCustomTabActivityToFirstRun() {
CustomTabsIntent customTabIntent = new CustomTabsIntent.Builder().build();
customTabIntent.intent.setPackage(mContext.getPackageName());
customTabIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
customTabIntent.launchUrl(mContext, Uri.parse("http://test.com"));
Intent launchedIntent = mShadowApplication.getNextStartedActivity();
Assert.assertNotNull(launchedIntent);
Activity launcherActivity =
Robolectric.buildActivity(ChromeLauncherActivity.class, launchedIntent)
.create()
.get();
assertFirstRunActivityLaunched();
Assert.assertTrue(launcherActivity.isFinishing());
}
@Test
public void testRedirectChromeTabbedActivityToFirstRun() {
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Activity tabbedActivity =
Robolectric.buildActivity(ChromeTabbedActivity.class, intent).create().get();
assertFirstRunActivityLaunched();
Assert.assertTrue(tabbedActivity.isFinishing());
}
@Test
public void testRedirectSearchActivityToFirstRun() {
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Activity searchActivity =
Robolectric.buildActivity(SearchActivity.class, intent).create().get();
assertFirstRunActivityLaunched();
Assert.assertTrue(searchActivity.isFinishing());
}
/**
* Tests that when the first run experience is shown by a WebAPK that the WebAPK is launched
* when the user finishes the first run experience. In the case where the WebAPK (as opposed
* to WebApkActivity) displays the splash screen this is necessary for correct behaviour when
* the user taps the app icon and the WebAPK is still running.
*/
@Test
public void testFreRelaunchesWebApkNotWebApkActivity() {
String webApkPackageName = "org.chromium.webapk.name";
String startUrl = "https://pwa.rocks/";
Bundle bundle = new Bundle();
bundle.putString(WebApkMetaDataKeys.START_URL, startUrl);
WebApkTestHelper.registerWebApkWithMetaData(
webApkPackageName, bundle, null /* shareTargetMetaData */);
WebApkTestHelper.addIntentFilterForUrl(webApkPackageName, startUrl);
Intent intent = new Intent();
intent.putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, webApkPackageName);
intent.putExtra(ShortcutHelper.EXTRA_URL, startUrl);
intent.putExtra(WebApkConstants.EXTRA_SPLASH_PROVIDED_BY_WEBAPK, true);
Robolectric.buildActivity(WebappLauncherActivity.class, intent).create();
Intent launchedIntent = mShadowApplication.getNextStartedActivity();
while (checkIntentComponentClassOneOf(
launchedIntent, new Class[] {WebappLauncherActivity.class})) {
buildActivityWithClassNameFromIntent(launchedIntent);
launchedIntent = mShadowApplication.getNextStartedActivity();
}
Assert.assertTrue(checkIntentIsForFre(launchedIntent));
PendingIntent freCompleteLaunchIntent = launchedIntent.getParcelableExtra(
FirstRunActivityBase.EXTRA_FRE_COMPLETE_LAUNCH_INTENT);
Assert.assertNotNull(freCompleteLaunchIntent);
Assert.assertEquals(webApkPackageName,
Shadows.shadowOf(freCompleteLaunchIntent).getSavedIntent().getPackage());
}
}