| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.notifications; | 5 package org.chromium.chrome.browser.notifications; |
| 6 | 6 |
| 7 import android.app.Notification; | 7 import android.app.Notification; |
| 8 import android.graphics.Bitmap; | 8 import android.graphics.Bitmap; |
| 9 import android.os.Build; | 9 import android.os.Build; |
| 10 import android.test.suitebuilder.annotation.LargeTest; |
| 10 import android.test.suitebuilder.annotation.MediumTest; | 11 import android.test.suitebuilder.annotation.MediumTest; |
| 11 import android.util.SparseArray; | 12 import android.util.SparseArray; |
| 12 | 13 |
| 13 import org.chromium.base.ThreadUtils; | 14 import org.chromium.base.ThreadUtils; |
| 14 import org.chromium.base.test.util.Feature; | 15 import org.chromium.base.test.util.Feature; |
| 15 import org.chromium.base.test.util.MinAndroidSdkLevel; | 16 import org.chromium.base.test.util.MinAndroidSdkLevel; |
| 16 import org.chromium.chrome.browser.preferences.website.ContentSetting; | 17 import org.chromium.chrome.browser.preferences.website.ContentSetting; |
| 17 import org.chromium.chrome.browser.preferences.website.PushNotificationInfo; | 18 import org.chromium.chrome.browser.preferences.website.PushNotificationInfo; |
| 18 import org.chromium.chrome.browser.widget.RoundedIconGenerator; | 19 import org.chromium.chrome.browser.widget.RoundedIconGenerator; |
| 19 import org.chromium.chrome.shell.ChromeShellTestBase; | 20 import org.chromium.chrome.shell.ChromeShellTestBase; |
| 20 import org.chromium.chrome.test.util.TestHttpServerClient; | 21 import org.chromium.chrome.test.util.TestHttpServerClient; |
| 21 import org.chromium.chrome.test.util.browser.notifications.MockNotificationManag
erProxy; | 22 import org.chromium.chrome.test.util.browser.notifications.MockNotificationManag
erProxy; |
| 22 import org.chromium.content.browser.test.util.Criteria; | 23 import org.chromium.content.browser.test.util.Criteria; |
| 23 import org.chromium.content.browser.test.util.CriteriaHelper; | 24 import org.chromium.content.browser.test.util.CriteriaHelper; |
| 24 import org.chromium.content.browser.test.util.JavaScriptUtils; | 25 import org.chromium.content.browser.test.util.JavaScriptUtils; |
| 25 | 26 |
| 26 import java.util.concurrent.TimeoutException; | 27 import java.util.concurrent.TimeoutException; |
| 27 | 28 |
| 28 /** | 29 /** |
| 29 * Instrumentation tests for the Notification UI Manager implementation on Andro
id. | 30 * Instrumentation tests for the Notification UI Manager implementation on Andro
id. |
| 30 * | 31 * |
| 31 * Web Notifications are only supported on Android JellyBean and beyond. | 32 * Web Notifications are only supported on Android JellyBean and beyond. |
| 32 */ | 33 */ |
| 33 @MinAndroidSdkLevel(Build.VERSION_CODES.JELLY_BEAN) | 34 @MinAndroidSdkLevel(Build.VERSION_CODES.JELLY_BEAN) |
| 34 public class NotificationUIManagerTest extends ChromeShellTestBase { | 35 public class NotificationUIManagerTest extends ChromeShellTestBase { |
| 35 private static final String NOTIFICATION_TEST_PAGE = | 36 private static final String NOTIFICATION_TEST_PAGE = |
| 36 TestHttpServerClient.getUrl("chrome/test/data/notifications/android_
test.html"); | 37 TestHttpServerClient.getUrl("chrome/test/data/notifications/android_
test.html"); |
| 37 private static final String PERMISSION_GRANTED = "\"granted\""; | |
| 38 | 38 |
| 39 private MockNotificationManagerProxy mMockNotificationManager; | 39 private MockNotificationManagerProxy mMockNotificationManager; |
| 40 | 40 |
| 41 /** | 41 /** |
| 42 * Returns the origin of the HTTP server the test is being ran on. | 42 * Returns the origin of the HTTP server the test is being ran on. |
| 43 */ | 43 */ |
| 44 private static String getOrigin() { | 44 private static String getOrigin() { |
| 45 return TestHttpServerClient.getUrl(""); | 45 return TestHttpServerClient.getUrl(""); |
| 46 } | 46 } |
| 47 | 47 |
| 48 /** | 48 /** |
| 49 * Sets the permission to use Web Notifications for the test HTTP server's o
rigin to |setting|. | 49 * Sets the permission to use Web Notifications for the test HTTP server's o
rigin to |setting|. |
| 50 */ | 50 */ |
| 51 private void setNotificationContentSettingForCurrentOrigin(final ContentSett
ing setting) { | 51 private void setNotificationContentSettingForCurrentOrigin(final ContentSett
ing setting) |
| 52 throws InterruptedException, TimeoutException { |
| 52 final String origin = getOrigin(); | 53 final String origin = getOrigin(); |
| 53 | 54 |
| 54 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | 55 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 55 @Override | 56 @Override |
| 56 public void run() { | 57 public void run() { |
| 57 // The notification content setting does not consider the embedd
er origin. | 58 // The notification content setting does not consider the embedd
er origin. |
| 58 PushNotificationInfo pushNotificationInfo = new PushNotification
Info(origin, ""); | 59 PushNotificationInfo pushNotificationInfo = new PushNotification
Info(origin, ""); |
| 59 pushNotificationInfo.setContentSetting(setting); | 60 pushNotificationInfo.setContentSetting(setting); |
| 60 } | 61 } |
| 61 }); | 62 }); |
| 63 |
| 64 String permission = runJavaScriptCodeInCurrentTab("Notification.permissi
on"); |
| 65 if (setting == ContentSetting.ALLOW) { |
| 66 assertEquals("\"granted\"", permission); |
| 67 } else if (setting == ContentSetting.BLOCK) { |
| 68 assertEquals("\"denied\"", permission); |
| 69 } else { |
| 70 assertEquals("\"default\"", permission); |
| 71 } |
| 62 } | 72 } |
| 63 | 73 |
| 64 /** | 74 /** |
| 65 * Runs the Javascript |code| in the current tab, and waits for the result t
o be available. | 75 * Runs the Javascript |code| in the current tab, and waits for the result t
o be available. |
| 66 * | 76 * |
| 67 * @param code The JavaScript code to execute in the current tab. | 77 * @param code The JavaScript code to execute in the current tab. |
| 68 * @return A JSON-formatted string with the result of executing the |code|. | 78 * @return A JSON-formatted string with the result of executing the |code|. |
| 69 */ | 79 */ |
| 70 private String runJavaScriptCodeInCurrentTab(String code) throws Interrupted
Exception, | 80 private String runJavaScriptCodeInCurrentTab(String code) throws Interrupted
Exception, |
| 71 TimeoutExce
ption { | 81 TimeoutExce
ption { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 } | 136 } |
| 127 | 137 |
| 128 /** | 138 /** |
| 129 * Verifies that the intended default properties of a notification will inde
ed be set on the | 139 * Verifies that the intended default properties of a notification will inde
ed be set on the |
| 130 * Notification object that will be send to Android. | 140 * Notification object that will be send to Android. |
| 131 */ | 141 */ |
| 132 @MediumTest | 142 @MediumTest |
| 133 @Feature({"Browser", "Notifications"}) | 143 @Feature({"Browser", "Notifications"}) |
| 134 public void testDefaultNotificationProperties() throws Exception { | 144 public void testDefaultNotificationProperties() throws Exception { |
| 135 setNotificationContentSettingForCurrentOrigin(ContentSetting.ALLOW); | 145 setNotificationContentSettingForCurrentOrigin(ContentSetting.ALLOW); |
| 136 assertEquals(PERMISSION_GRANTED, runJavaScriptCodeInCurrentTab("Notifica
tion.permission")); | |
| 137 | 146 |
| 138 Notification notification = showAndGetNotification("MyNotification", "{
body: 'Hello' }"); | 147 Notification notification = showAndGetNotification("MyNotification", "{
body: 'Hello' }"); |
| 139 assertNotNull(notification); | |
| 140 | 148 |
| 141 // Validate the contents of the notification. | 149 // Validate the contents of the notification. |
| 142 assertEquals("MyNotification", notification.extras.getString(Notificatio
n.EXTRA_TITLE)); | 150 assertEquals("MyNotification", notification.extras.getString(Notificatio
n.EXTRA_TITLE)); |
| 143 assertEquals("Hello", notification.extras.getString(Notification.EXTRA_T
EXT)); | 151 assertEquals("Hello", notification.extras.getString(Notification.EXTRA_T
EXT)); |
| 144 assertEquals(getOrigin(), notification.extras.getString(Notification.EXT
RA_SUB_TEXT)); | 152 assertEquals(getOrigin(), notification.extras.getString(Notification.EXT
RA_SUB_TEXT)); |
| 145 | 153 |
| 146 // Validate the appearance style of the notification. The EXTRA_TEMPLATE
was inroduced | 154 // Validate the appearance style of the notification. The EXTRA_TEMPLATE
was inroduced |
| 147 // in Android Lollipop, we cannot verify this in earlier versions. | 155 // in Android Lollipop, we cannot verify this in earlier versions. |
| 148 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | 156 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { |
| 149 assertEquals("android.app.Notification$BigTextStyle", | 157 assertEquals("android.app.Notification$BigTextStyle", |
| 150 notification.extras.getString(Notification.EXTRA_TEMPLATE)); | 158 notification.extras.getString(Notification.EXTRA_TEMPLATE)); |
| 151 } | 159 } |
| 152 | 160 |
| 153 assertNotNull(notification.largeIcon); | 161 assertNotNull(notification.largeIcon); |
| 154 | 162 |
| 155 // Validate the notification's behavior. | 163 // Validate the notification's behavior. |
| 156 assertEquals(Notification.DEFAULT_ALL, notification.defaults); | 164 assertEquals(Notification.DEFAULT_ALL, notification.defaults); |
| 157 assertEquals(Notification.PRIORITY_DEFAULT, notification.priority); | 165 assertEquals(Notification.PRIORITY_DEFAULT, notification.priority); |
| 158 } | 166 } |
| 159 | 167 |
| 160 /** | 168 /** |
| 161 * Verifies that notifications which specify an icon will have that icon fet
ched, converted into | 169 * Verifies that notifications which specify an icon will have that icon fet
ched, converted into |
| 162 * a Bitmap and included as the large icon in the notification. | 170 * a Bitmap and included as the large icon in the notification. |
| 163 */ | 171 */ |
| 164 @MediumTest | 172 @MediumTest |
| 165 @Feature({"Browser", "Notifications"}) | 173 @Feature({"Browser", "Notifications"}) |
| 166 public void testShowNotificationWithIcon() throws Exception { | 174 public void testShowNotificationWithIcon() throws Exception { |
| 167 setNotificationContentSettingForCurrentOrigin(ContentSetting.ALLOW); | 175 setNotificationContentSettingForCurrentOrigin(ContentSetting.ALLOW); |
| 168 assertEquals(PERMISSION_GRANTED, runJavaScriptCodeInCurrentTab("Notifica
tion.permission")); | |
| 169 | 176 |
| 170 Notification notification = showAndGetNotification("MyNotification", "{i
con: 'icon.png'}"); | 177 Notification notification = showAndGetNotification("MyNotification", "{i
con: 'icon.png'}"); |
| 171 assertNotNull(notification); | |
| 172 | 178 |
| 173 assertEquals("MyNotification", notification.extras.getString(Notificatio
n.EXTRA_TITLE)); | 179 assertEquals("MyNotification", notification.extras.getString(Notificatio
n.EXTRA_TITLE)); |
| 174 assertNotNull(notification.largeIcon); | 180 assertNotNull(notification.largeIcon); |
| 175 | 181 |
| 176 // These are the dimensions of //chrome/test/data/notifications/icon.png
at 1x scale. | 182 // These are the dimensions of //chrome/test/data/notifications/icon.png
at 1x scale. |
| 177 assertEquals(100, notification.largeIcon.getWidth()); | 183 assertEquals(100, notification.largeIcon.getWidth()); |
| 178 assertEquals(100, notification.largeIcon.getHeight()); | 184 assertEquals(100, notification.largeIcon.getHeight()); |
| 179 } | 185 } |
| 180 | 186 |
| 181 /** | 187 /** |
| 182 * Verifies that notifications which don't specify an icon will get an autom
atically generated | 188 * Verifies that notifications which don't specify an icon will get an autom
atically generated |
| 183 * icon based on their origin. The size of these icons are dependent on the
resolution of the | 189 * icon based on their origin. The size of these icons are dependent on the
resolution of the |
| 184 * device the test is being ran on, so we create it again in order to compar
e. | 190 * device the test is being ran on, so we create it again in order to compar
e. |
| 185 */ | 191 */ |
| 186 @MediumTest | 192 @MediumTest |
| 187 @Feature({"Browser", "Notifications"}) | 193 @Feature({"Browser", "Notifications"}) |
| 188 public void testShowNotificationWithoutIcon() throws Exception { | 194 public void testShowNotificationWithoutIcon() throws Exception { |
| 189 setNotificationContentSettingForCurrentOrigin(ContentSetting.ALLOW); | 195 setNotificationContentSettingForCurrentOrigin(ContentSetting.ALLOW); |
| 190 assertEquals(PERMISSION_GRANTED, runJavaScriptCodeInCurrentTab("Notifica
tion.permission")); | |
| 191 | 196 |
| 192 Notification notification = showAndGetNotification("NoIconNotification",
"{}"); | 197 Notification notification = showAndGetNotification("NoIconNotification",
"{}"); |
| 193 assertNotNull(notification); | |
| 194 | 198 |
| 195 assertEquals("NoIconNotification", notification.extras.getString(Notific
ation.EXTRA_TITLE)); | 199 assertEquals("NoIconNotification", notification.extras.getString(Notific
ation.EXTRA_TITLE)); |
| 196 assertNotNull(notification.largeIcon); | 200 assertNotNull(notification.largeIcon); |
| 197 | 201 |
| 198 // Create a second rounded icon for the test's origin, and compare its d
imensions against | 202 // Create a second rounded icon for the test's origin, and compare its d
imensions against |
| 199 // those of the icon associated to the notification itself. | 203 // those of the icon associated to the notification itself. |
| 200 RoundedIconGenerator generator = NotificationUIManager.createRoundedIcon
Generator( | 204 RoundedIconGenerator generator = NotificationUIManager.createRoundedIcon
Generator( |
| 201 getActivity().getApplicationContext()); | 205 getActivity().getApplicationContext()); |
| 202 assertNotNull(generator); | 206 assertNotNull(generator); |
| 203 | 207 |
| 204 Bitmap generatedIcon = generator.generateIconForUrl(getOrigin()); | 208 Bitmap generatedIcon = generator.generateIconForUrl(getOrigin()); |
| 205 assertNotNull(generatedIcon); | 209 assertNotNull(generatedIcon); |
| 206 | 210 |
| 207 assertEquals(generatedIcon.getWidth(), notification.largeIcon.getWidth()
); | 211 assertEquals(generatedIcon.getWidth(), notification.largeIcon.getWidth()
); |
| 208 assertEquals(generatedIcon.getHeight(), notification.largeIcon.getHeight
()); | 212 assertEquals(generatedIcon.getHeight(), notification.largeIcon.getHeight
()); |
| 209 } | 213 } |
| 214 |
| 215 /* |
| 216 * Verifies that starting the PendingIntent stored as the notification's con
tent intent will |
| 217 * start up the associated Service Worker, where the JavaScript code will cl
ose the notification |
| 218 * by calling event.notification.close(). |
| 219 */ |
| 220 @LargeTest |
| 221 @Feature({"Browser", "Notifications"}) |
| 222 public void testNotificationContentIntentClosesNotification() throws Excepti
on { |
| 223 setNotificationContentSettingForCurrentOrigin(ContentSetting.ALLOW); |
| 224 |
| 225 Notification notification = showAndGetNotification("MyNotification", "{}
"); |
| 226 |
| 227 // Sending the PendingIntent resembles activating the notification. |
| 228 assertNotNull(notification.contentIntent); |
| 229 notification.contentIntent.send(); |
| 230 |
| 231 // The Service Worker will close the notification upon receiving the not
ificationclick |
| 232 // event. This will eventually bubble up to a call to cancel() in the No
tificationManager. |
| 233 assertTrue(waitForNotificationManagerMutation()); |
| 234 |
| 235 SparseArray<Notification> notifications = mMockNotificationManager.getNo
tifications(); |
| 236 assertEquals(0, notifications.size()); |
| 237 } |
| 238 |
| 239 /** |
| 240 * Verifies that creating a notification with an associated "tag" will cause
any previous |
| 241 * notification with the same tag to be dismissed prior to being shown. |
| 242 */ |
| 243 @MediumTest |
| 244 @Feature({"Browser", "Notifications"}) |
| 245 public void testNotificationTagReplacement() throws Exception { |
| 246 setNotificationContentSettingForCurrentOrigin(ContentSetting.ALLOW); |
| 247 |
| 248 Notification notification = showAndGetNotification("MyNotification", "{t
ag: 'myTag'}"); |
| 249 |
| 250 // Show the second notification with the same tag. We can't use showAndG
etNotification for |
| 251 // this purpose since a second notification would be shown. |
| 252 runJavaScriptCodeInCurrentTab("showNotification('SecondNotification', {t
ag: 'myTag'});"); |
| 253 assertTrue(waitForNotificationManagerMutation()); |
| 254 |
| 255 // Verify that the notification was successfully replaced. |
| 256 SparseArray<Notification> notifications = mMockNotificationManager.getNo
tifications(); |
| 257 assertEquals(1, notifications.size()); |
| 258 assertEquals("SecondNotification", |
| 259 notifications.valueAt(0).extras.getString(Notification.EXTRA_TIT
LE)); |
| 260 } |
| 210 } | 261 } |
| OLD | NEW |