Commit 0bc0701b authored by Peter E Conn's avatar Peter E Conn Committed by Commit Bot

🔁 Create tests for TrustedWebActivityClient.

Bug: 841178
Change-Id: I7aad6a4f8288941cb78231da010a972b4eafad06
Reviewed-on: https://chromium-review.googlesource.com/1059786Reviewed-by: default avatarBernhard Bauer <bauerb@chromium.org>
Commit-Queue: Peter Conn <peconn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#559488}
parent bbce11d4
...@@ -529,6 +529,7 @@ android_library("chrome_test_java") { ...@@ -529,6 +529,7 @@ android_library("chrome_test_java") {
"//chrome/android/webapk/libs/client:client_java", "//chrome/android/webapk/libs/client:client_java",
"//chrome/android/webapk/libs/common:common_java", "//chrome/android/webapk/libs/common:common_java",
"//chrome/test/android:chrome_java_test_support", "//chrome/test/android:chrome_java_test_support",
"//chrome/test/android/test_trusted_web_activity:test_trusted_web_activity_java",
"//components/autofill/android:autofill_java", "//components/autofill/android:autofill_java",
"//components/background_task_scheduler:background_task_scheduler_java", "//components/background_task_scheduler:background_task_scheduler_java",
"//components/background_task_scheduler:background_task_scheduler_javatests", "//components/background_task_scheduler:background_task_scheduler_javatests",
......
...@@ -1586,6 +1586,7 @@ chrome_test_java_sources = [ ...@@ -1586,6 +1586,7 @@ chrome_test_java_sources = [
"javatests/src/org/chromium/chrome/browser/browseractions/BrowserActionActivityTest.java", "javatests/src/org/chromium/chrome/browser/browseractions/BrowserActionActivityTest.java",
"javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java", "javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java",
"javatests/src/org/chromium/chrome/browser/browserservices/OriginTest.java", "javatests/src/org/chromium/chrome/browser/browserservices/OriginTest.java",
"javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java",
"javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java",
"javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java", "javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java",
"javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java", "javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java",
......
...@@ -50,6 +50,9 @@ ...@@ -50,6 +50,9 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="org.chromium.chrome.browser.browserservices.TestTrustedWebActivityService"
android:exported="true"/>
<activity android:name="org.chromium.test.broker.OnDeviceInstrumentationBroker" <activity android:name="org.chromium.test.broker.OnDeviceInstrumentationBroker"
android:exported="true"/> android:exported="true"/>
</application> </application>
......
// 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.browserservices;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.rule.ServiceTestRule;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.ThreadUtils;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.notifications.NotificationBuilderBase;
import org.chromium.chrome.browser.notifications.StandardNotificationBuilder;
import java.util.concurrent.TimeoutException;
/**
* Tests the TrustedWebActivityClient.
*
* The control flow in these tests is a bit complicated since attempting to connect to a
* test TrustedWebActivityService in the chrome_public_test results in a ClassLoader error (see
* https://crbug.com/841178#c1). Therefore we must put the test TrustedWebActivityService in
* chrome_public_test_support.
*
* We don't want to open up the TrustedWebActivityService API, so an additional Service (the
* MessengerService) was created in chrome_public_test_support. This service can freely talk with
* this test class.
*
* The general flow of these tests is as follows:
* 1. Call a method on TrustedWebActivityClient.
* 2. This calls through to TestTrustedWebActivityService.
* 3. This calls a method on MessengerService.
* 4. This sends a Message to ResponseHandler in this class.
*/
@RunWith(BaseJUnit4ClassRunner.class)
public class TrustedWebActivityClientTest {
private static final Uri SCOPE = Uri.parse("https://www.example.com/notifications");
private static final Origin ORIGIN = new Origin(SCOPE);
private static final String NOTIFICATION_TAG = "tag";
private static final int NOTIFICATION_ID = 123;
private static final String TEST_SUPPORT_PACKAGE =
"org.chromium.chrome.tests.support";
private static final String MESSENGER_SERVICE_NAME =
"org.chromium.chrome.browser.browserservices.MessengerService";
@Rule public final ServiceTestRule mServiceTestRule = new ServiceTestRule();
private ResponseHandler mResponseHandler;
private TrustedWebActivityClient mClient;
private Context mTargetContext;
/**
* A Handler that MessengerService will send messages to, reporting actions on
* TestTrustedWebActivityService.
*/
private static class ResponseHandler extends Handler {
final CallbackHelper mResponderRegistered = new CallbackHelper();
final CallbackHelper mGetSmallIconId = new CallbackHelper();
final CallbackHelper mNotifyNotification = new CallbackHelper();
final CallbackHelper mCancelNotification = new CallbackHelper();
String mNotificationTag;
int mNotificationId;
String mNotificationChannel;
public ResponseHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// For some messages these will be null/zero. It should be fine because the messages
// we care about these variables for will be called at the end of a sequence.
mNotificationTag = msg.getData().getString(MessengerService.TAG_KEY);
mNotificationId = msg.getData().getInt(MessengerService.ID_KEY);
mNotificationChannel = msg.getData().getString(MessengerService.CHANNEL_KEY);
switch (msg.what) {
case MessengerService.MSG_RESPONDER_REGISTERED:
mResponderRegistered.notifyCalled();
break;
case MessengerService.MSG_GET_SMALL_ICON_ID:
mGetSmallIconId.notifyCalled();
break;
case MessengerService.MSG_NOTIFY_NOTIFICATION:
mNotifyNotification.notifyCalled();
break;
case MessengerService.MSG_CANCEL_NOTIFICATION:
mCancelNotification.notifyCalled();
break;
default:
Assert.fail("Unexpected message: " + msg.what);
}
}
}
@Before
public void setUp() throws TimeoutException, RemoteException, InterruptedException {
mTargetContext = InstrumentationRegistry.getTargetContext();
mClient = new TrustedWebActivityClient(mTargetContext);
// TestTrustedWebActivityService is in the test support apk.
TrustedWebActivityClient.registerClient(mTargetContext, ORIGIN, TEST_SUPPORT_PACKAGE);
// The MessengerService lives in the same package as the TestTrustedWebActivityService.
// We use it as a side channel to verify what the TestTrustedWebActivityService does.
mResponseHandler = new ResponseHandler(ThreadUtils.getUiThreadLooper());
// Launch the MessengerService.
Intent intent = new Intent();
intent.setComponent(new ComponentName(TEST_SUPPORT_PACKAGE, MESSENGER_SERVICE_NAME));
// Create a Messenger to talk to the MessengerService.
Messenger messenger = new Messenger(mServiceTestRule.bindService(intent));
// Create a Messenger for the MessengerService to respond to us.
Messenger responseMessenger = new Messenger(mResponseHandler);
Message message = Message.obtain();
message.replyTo = responseMessenger;
messenger.send(message);
mResponseHandler.mResponderRegistered.waitForCallback(0);
}
/**
* Tests that #notifyNotification:
* - Gets the small icon id from the service (although it doesn't check that it's used).
* - Gets the service to show the notification.
* - Uses the provided tag and id and the default channel name.
*/
@Test
@SmallTest
public void testNotifyNotification() throws TimeoutException, InterruptedException {
Assert.assertEquals(0, mResponseHandler.mGetSmallIconId.getCallCount());
Assert.assertEquals(0, mResponseHandler.mNotifyNotification.getCallCount());
ThreadUtils.runOnUiThread(() -> {
NotificationBuilderBase builder = new StandardNotificationBuilder(mTargetContext);
mClient.notifyNotification(SCOPE, NOTIFICATION_TAG, NOTIFICATION_ID, builder);
});
mResponseHandler.mGetSmallIconId.waitForCallback(0);
mResponseHandler.mNotifyNotification.waitForCallback(0);
Assert.assertEquals(mResponseHandler.mNotificationTag, NOTIFICATION_TAG);
Assert.assertEquals(mResponseHandler.mNotificationId, NOTIFICATION_ID);
Assert.assertEquals(mResponseHandler.mNotificationChannel,
mTargetContext.getResources().getString(
R.string.notification_category_group_general));
}
/**
* Tests that #cancelNotification gets the service to cancel the notification, using the given
* id and tag.
*/
@Test
@SmallTest
public void testCancelNotification() throws TimeoutException, InterruptedException {
Assert.assertEquals(0, mResponseHandler.mCancelNotification.getCallCount());
ThreadUtils.runOnUiThread(() ->
mClient.cancelNotification(SCOPE, NOTIFICATION_TAG, NOTIFICATION_ID));
mResponseHandler.mCancelNotification.waitForCallback(0);
Assert.assertEquals(mResponseHandler.mNotificationTag, NOTIFICATION_TAG);
Assert.assertEquals(mResponseHandler.mNotificationId, NOTIFICATION_ID);
}
}
...@@ -16,5 +16,26 @@ ...@@ -16,5 +16,26 @@
<action android:name="android.media.MediaRouteProviderService" /> <action android:name="android.media.MediaRouteProviderService" />
</intent-filter> </intent-filter>
</service> </service>
<activity android:name="org.chromium.chrome.browser.browserservices.ActivityWithDeepLink">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="https"
android:host="www.example.com"
android:pathPrefix="/notifications"/>
</intent-filter>
</activity>
<service android:name="org.chromium.chrome.browser.browserservices.TestTrustedWebActivityService"
android:exported="true">
<intent-filter>
<action android:name="android.support.customtabs.trusted.TRUSTED_WEB_ACTIVITY_SERVICE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
<service android:name="org.chromium.chrome.browser.browserservices.MessengerService"
android:exported="true"/>
</application> </application>
</manifest> </manifest>
...@@ -10,6 +10,7 @@ android_apk("chrome_public_test_support_apk") { ...@@ -10,6 +10,7 @@ android_apk("chrome_public_test_support_apk") {
never_incremental = true never_incremental = true
deps = [ deps = [
"//chrome/test/android/cast_emulator:cast_emulator_java", "//chrome/test/android/cast_emulator:cast_emulator_java",
"//chrome/test/android/test_trusted_web_activity:test_trusted_web_activity_java",
] ]
apk_name = "ChromePublicTestSupport" apk_name = "ChromePublicTestSupport"
......
# Copyright 2015 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.
import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
android_library("test_trusted_web_activity_java") {
chromium_code = true
java_files = [
"src/org/chromium/chrome/browser/browserservices/ActivityWithDeepLink.java",
"src/org/chromium/chrome/browser/browserservices/MessengerService.java",
"src/org/chromium/chrome/browser/browserservices/TestTrustedWebActivityService.java",
]
deps = [
"//third_party/custom_tabs_client:custom_tabs_support_java",
]
}
// 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.browserservices;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
/**
* An Activity that accepts browsable intents to http://www.example.com/notifications. This is
* required for {@link TestTrustedWebActivityService} to be found.
*/
public class ActivityWithDeepLink extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
finish();
}
}
// 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.browserservices;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.annotation.Nullable;
/**
* The TrustedWebActivityClientTest tests need to test behaviour called on
* TestTrustedWebActivityService. We don't want to add general purpose methods on the
* TrustedWebActivityService API for testing so we use this class as a side-channel.
*/
public class MessengerService extends Service {
public static final int MSG_RESPONDER_REGISTERED = 0;
public static final int MSG_GET_SMALL_ICON_ID = 1;
public static final int MSG_NOTIFY_NOTIFICATION = 2;
public static final int MSG_CANCEL_NOTIFICATION = 3;
public static final String TAG_KEY = "tag";
public static final String ID_KEY = "id";
public static final String CHANNEL_KEY = "channel";
public static MessageHandler sMessageHandler;
private Messenger mMessenger;
@Override
public void onCreate() {
super.onCreate();
sMessageHandler = new MessageHandler();
mMessenger = new Messenger(sMessageHandler);
}
static class MessageHandler extends Handler {
@Nullable private Messenger mResponder;
@Override
public void handleMessage(Message msg) {
assert mResponder == null;
mResponder = msg.replyTo;
respond(MSG_RESPONDER_REGISTERED);
}
public void recordGetSmallIconId() {
respond(MSG_GET_SMALL_ICON_ID);
}
public void recordNotifyNotification(String tag, int id, String channelName) {
Bundle bundle = new Bundle();
bundle.putString(TAG_KEY, tag);
bundle.putInt(ID_KEY, id);
bundle.putString(CHANNEL_KEY, channelName);
respond(MSG_NOTIFY_NOTIFICATION, bundle);
}
public void recordCancelNotification(String tag, int id) {
Bundle bundle = new Bundle();
bundle.putString(TAG_KEY, tag);
bundle.putInt(ID_KEY, id);
respond(MSG_CANCEL_NOTIFICATION, bundle);
}
private void respond(int what) {
respond(what, null);
}
private void respond(int what, Bundle data) {
Message message = Message.obtain();
message.what = what;
if (data != null) message.setData(data);
try {
mResponder.send(message);
} catch (RemoteException ex) {
throw new RuntimeException(ex);
}
}
}
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
}
\ No newline at end of file
// 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.browserservices;
import android.app.Notification;
import android.support.customtabs.trusted.TrustedWebActivityService;
/**
* A TrustedWebActivityService to be used in TrustedWebActivityClientTest.
*/
public class TestTrustedWebActivityService extends TrustedWebActivityService {
// TODO(peconn): Add an image resource to chrome_public_test_support, supply that in
// getSmallIconId and verify it is used in notifyNotificationWithChannel.
private static final int RESOURCE_ID = -1;
@Override
public void onCreate() {
super.onCreate();
TrustedWebActivityService.setVerifiedProviderForTesting(this, "org.chromium.chrome");
}
@Override
protected boolean notifyNotificationWithChannel(String platformTag, int platformId,
Notification notification, String channelName) {
MessengerService.sMessageHandler
.recordNotifyNotification(platformTag, platformId, channelName);
return true;
}
@Override
protected void cancelNotification(String platformTag, int platformId) {
MessengerService.sMessageHandler.recordCancelNotification(platformTag, platformId);
}
@Override
protected int getSmallIconId() {
MessengerService.sMessageHandler.recordGetSmallIconId();
return RESOURCE_ID;
}
}
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