// Copyright 2016 The Chromium Authors
// 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.notifications;
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Criteria;
import org.chromium.base.test.util.CriteriaHelper;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.document.ChromeLauncherActivity;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.settings.SettingsActivity;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.util.ActivityTestUtils;
import org.chromium.components.browser_ui.site_settings.SingleCategorySettings;
import org.chromium.components.browser_ui.site_settings.SingleWebsiteSettings;
/**
* Instrumentation tests for the Notification Platform Bridge.
*
* <p>Exercises the handling of intents and explicitly does not do anything in startMainActivity so
* that the responsibility for correct initialization, e.g. loading the native library, lies with
* the code exercised by this test.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public class NotificationPlatformBridgeIntentTest {
/**
* Name of the Intent extra holding the notification id. This is set by the framework when a
* notification preferences intent has been triggered from there, which could be one of the
* setting gears in system UI.
*/
public static final String EXTRA_NOTIFICATION_ID = "notification_id";
/**
* Tests the scenario where the user clicks "App settings" in the Android App notifications
* screen. In this scenario the intent does not have the tag extra which holds the origin. This
* means that the preferences cannot be shown for a specific site, and Chrome falls back to
* showing the notification preferences for all sites.
*/
@Test
@MediumTest
@Feature({"Browser", "Notifications"})
public void testLaunchNotificationPreferencesForCategory() {
Assert.assertFalse(
"The native library should not be loaded yet",
LibraryLoader.getInstance().isInitialized());
final Context context =
InstrumentationRegistry.getInstrumentation()
.getTargetContext()
.getApplicationContext();
final Intent intent =
new Intent(Intent.ACTION_MAIN)
.addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
.setClassName(context, ChromeLauncherActivity.class.getName())
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
SettingsActivity activity =
ActivityTestUtils.waitForActivity(
InstrumentationRegistry.getInstrumentation(),
SettingsActivity.class,
new Runnable() {
@Override
public void run() {
context.startActivity(intent);
}
});
Assert.assertNotNull("Could not find the Settings activity", activity);
SingleCategorySettings fragment =
ActivityTestUtils.waitForFragmentToAttach(activity, SingleCategorySettings.class);
Assert.assertNotNull("Could not find the SingleCategorySettings fragment", fragment);
}
/**
* Tests the scenario where the user clicks the settings gear on a notification that was flipped
* through a long press. In this scenario the intent has the tag extra which holds the origin
* that created the notification. Chrome will show the preferences for this specific site.
*/
@Test
@MediumTest
@Feature({"Browser", "Notifications"})
public void testLaunchNotificationPreferencesForWebsite() {
Assert.assertFalse(
"The native library should not be loaded yet",
LibraryLoader.getInstance().isInitialized());
final Context context =
InstrumentationRegistry.getInstrumentation()
.getTargetContext()
.getApplicationContext();
final Intent intent =
new Intent(Intent.ACTION_MAIN)
.addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
.setClassName(context, ChromeLauncherActivity.class.getName())
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(EXTRA_NOTIFICATION_ID, NotificationPlatformBridge.PLATFORM_ID)
.putExtra(
NotificationConstants.EXTRA_NOTIFICATION_TAG,
/* notificationId= */ "p#https://example.com#0");
SettingsActivity activity =
ActivityTestUtils.waitForActivity(
InstrumentationRegistry.getInstrumentation(),
SettingsActivity.class,
new Runnable() {
@Override
public void run() {
context.startActivity(intent);
}
});
Assert.assertNotNull("Could not find the Settings activity", activity);
SingleWebsiteSettings fragment =
ActivityTestUtils.waitForFragmentToAttach(activity, SingleWebsiteSettings.class);
Assert.assertNotNull("Could not find the SingleWebsiteSettings fragment", fragment);
}
/**
* Tests the browser initialization code when a notification has been activated. This will be
* routed through the NotificationService which starts the browser process, which in turn will
* create an instance of the NotificationPlatformBridge.
*
* <p>The created intent does not carry significant data and is expected to fail, but has to be
* sufficient for the Java code to trigger start-up of the browser process.
*/
@Test
@MediumTest
@Feature({"Browser", "Notifications"})
@DisabledTest(message = "https://crbug.com/1420990")
public void testLaunchProcessForNotificationActivation() throws Exception {
Assert.assertFalse(
"The native library should not be loaded yet",
LibraryLoader.getInstance().isInitialized());
Assert.assertNull(NotificationPlatformBridge.getInstanceForTests());
Context context =
InstrumentationRegistry.getInstrumentation()
.getTargetContext()
.getApplicationContext();
Intent intent = new Intent(NotificationConstants.ACTION_CLICK_NOTIFICATION);
intent.setClass(context, NotificationServiceImpl.Receiver.class);
intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_ID, "42");
intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID, "Default");
intent.putExtra(
NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN, "https://example.com");
context.sendBroadcast(intent);
CriteriaHelper.pollUiThread(
() -> {
Criteria.checkThat(
"Browser process was never started.",
NotificationPlatformBridge.getInstanceForTests(),
Matchers.notNullValue());
});
Assert.assertTrue(
"The native library should be loaded now",
LibraryLoader.getInstance().isInitialized());
Assert.assertNotNull(NotificationPlatformBridge.getInstanceForTests());
}
}