OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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; | 5 package org.chromium.chrome.browser; |
6 | 6 |
7 import android.Manifest; | 7 import android.Manifest; |
8 import android.app.Dialog; | 8 import android.app.Dialog; |
| 9 import android.content.Context; |
| 10 import android.content.Intent; |
9 import android.content.pm.PackageManager; | 11 import android.content.pm.PackageManager; |
| 12 import android.location.LocationManager; |
10 import android.test.MoreAsserts; | 13 import android.test.MoreAsserts; |
11 import android.test.suitebuilder.annotation.SmallTest; | 14 import android.test.suitebuilder.annotation.SmallTest; |
12 import android.view.View; | 15 import android.view.View; |
13 import android.widget.Button; | 16 import android.widget.Button; |
14 import android.widget.ListView; | 17 import android.widget.ListView; |
15 | 18 |
16 import org.chromium.base.ThreadUtils; | 19 import org.chromium.base.ThreadUtils; |
17 import org.chromium.chrome.R; | 20 import org.chromium.chrome.R; |
| 21 import org.chromium.chrome.browser.preferences.LocationSettings; |
18 import org.chromium.chrome.test.ChromeActivityTestCaseBase; | 22 import org.chromium.chrome.test.ChromeActivityTestCaseBase; |
19 import org.chromium.components.security_state.ConnectionSecurityLevel; | 23 import org.chromium.components.security_state.ConnectionSecurityLevel; |
20 import org.chromium.content.browser.test.util.Criteria; | 24 import org.chromium.content.browser.test.util.Criteria; |
21 import org.chromium.content.browser.test.util.CriteriaHelper; | 25 import org.chromium.content.browser.test.util.CriteriaHelper; |
22 import org.chromium.content.browser.test.util.TouchCommon; | 26 import org.chromium.content.browser.test.util.TouchCommon; |
23 import org.chromium.ui.base.ActivityWindowAndroid; | 27 import org.chromium.ui.base.ActivityWindowAndroid; |
24 import org.chromium.ui.base.AndroidPermissionDelegate; | 28 import org.chromium.ui.base.AndroidPermissionDelegate; |
25 import org.chromium.ui.base.WindowAndroid; | 29 import org.chromium.ui.base.WindowAndroid; |
26 import org.chromium.ui.base.WindowAndroid.PermissionCallback; | 30 import org.chromium.ui.base.WindowAndroid.PermissionCallback; |
27 import org.chromium.ui.widget.TextViewWithClickableSpans; | 31 import org.chromium.ui.widget.TextViewWithClickableSpans; |
28 | 32 |
29 import java.util.concurrent.Callable; | 33 import java.util.concurrent.Callable; |
30 | 34 |
31 /** | 35 /** |
32 * Tests for the BluetoothChooserDialog class. | 36 * Tests for the BluetoothChooserDialog class. |
33 */ | 37 */ |
34 public class BluetoothChooserDialogTest extends ChromeActivityTestCaseBase<Chrom
eActivity> { | 38 public class BluetoothChooserDialogTest extends ChromeActivityTestCaseBase<Chrom
eActivity> { |
35 /** | 39 /** |
36 * Works like the BluetoothChooserDialog class, but records calls to native
methods instead of | 40 * Works like the BluetoothChooserDialog class, but records calls to native
methods instead of |
37 * calling back to C++. | 41 * calling back to C++. |
38 */ | 42 */ |
39 static class BluetoothChooserDialogWithFakeNatives extends BluetoothChooserD
ialog { | 43 static class BluetoothChooserDialogWithFakeNatives extends BluetoothChooserD
ialog { |
40 int mFinishedEventType = -1; | 44 int mFinishedEventType = -1; |
41 String mFinishedDeviceId; | 45 String mFinishedDeviceId; |
| 46 int mRestartSearchCount = 0; |
42 | 47 |
43 BluetoothChooserDialogWithFakeNatives(WindowAndroid windowAndroid, Strin
g origin, | 48 BluetoothChooserDialogWithFakeNatives(WindowAndroid windowAndroid, Strin
g origin, |
44 int securityLevel, long nativeBluetoothChooserDialogPtr) { | 49 int securityLevel, long nativeBluetoothChooserDialogPtr) { |
45 super(windowAndroid, origin, securityLevel, nativeBluetoothChooserDi
alogPtr); | 50 super(windowAndroid, origin, securityLevel, nativeBluetoothChooserDi
alogPtr); |
46 } | 51 } |
47 | 52 |
48 @Override | 53 @Override |
49 void nativeOnDialogFinished( | 54 void nativeOnDialogFinished( |
50 long nativeBluetoothChooserAndroid, int eventType, String device
Id) { | 55 long nativeBluetoothChooserAndroid, int eventType, String device
Id) { |
51 assertEquals(nativeBluetoothChooserAndroid, mNativeBluetoothChooserD
ialogPtr); | 56 assertEquals(nativeBluetoothChooserAndroid, mNativeBluetoothChooserD
ialogPtr); |
52 assertEquals(mFinishedEventType, -1); | 57 assertEquals(mFinishedEventType, -1); |
53 mFinishedEventType = eventType; | 58 mFinishedEventType = eventType; |
54 mFinishedDeviceId = deviceId; | 59 mFinishedDeviceId = deviceId; |
55 } | 60 } |
56 | 61 |
57 @Override | 62 @Override |
58 void nativeRestartSearch(long nativeBluetoothChooserAndroid) {} | 63 void nativeRestartSearch(long nativeBluetoothChooserAndroid) { |
| 64 mRestartSearchCount++; |
| 65 } |
59 | 66 |
60 @Override | 67 @Override |
61 void nativeShowBluetoothOverviewLink(long nativeBluetoothChooserAndroid)
{} | 68 void nativeShowBluetoothOverviewLink(long nativeBluetoothChooserAndroid)
{} |
62 | 69 |
63 @Override | 70 @Override |
64 void nativeShowBluetoothAdapterOffLink(long nativeBluetoothChooserAndroi
d) {} | 71 void nativeShowBluetoothAdapterOffLink(long nativeBluetoothChooserAndroi
d) {} |
65 | 72 |
66 @Override | 73 @Override |
67 void nativeShowNeedLocationPermissionLink(long nativeBluetoothChooserAnd
roid) {} | 74 void nativeShowNeedLocationPermissionLink(long nativeBluetoothChooserAnd
roid) {} |
68 } | 75 } |
69 | 76 |
70 private ActivityWindowAndroid mWindowAndroid; | 77 private ActivityWindowAndroid mWindowAndroid; |
| 78 private TestLocationSettings mLocationSettings; |
71 private BluetoothChooserDialogWithFakeNatives mChooserDialog; | 79 private BluetoothChooserDialogWithFakeNatives mChooserDialog; |
72 | 80 |
73 public BluetoothChooserDialogTest() { | 81 public BluetoothChooserDialogTest() { |
74 super(ChromeActivity.class); | 82 super(ChromeActivity.class); |
75 } | 83 } |
76 | 84 |
77 // ChromeActivityTestCaseBase: | 85 // ChromeActivityTestCaseBase: |
78 | 86 |
79 @Override | 87 @Override |
80 protected void setUp() throws Exception { | 88 protected void setUp() throws Exception { |
81 super.setUp(); | 89 super.setUp(); |
| 90 mLocationSettings = new TestLocationSettings(getActivity()); |
| 91 LocationSettings.setInstanceForTesting(mLocationSettings); |
82 mChooserDialog = createDialog(); | 92 mChooserDialog = createDialog(); |
83 } | 93 } |
84 | 94 |
85 @Override | 95 @Override |
| 96 protected void tearDown() throws Exception { |
| 97 LocationSettings.setInstanceForTesting(null); |
| 98 super.tearDown(); |
| 99 } |
| 100 |
| 101 @Override |
86 public void startMainActivity() throws InterruptedException { | 102 public void startMainActivity() throws InterruptedException { |
87 startMainActivityOnBlankPage(); | 103 startMainActivityOnBlankPage(); |
88 } | 104 } |
89 | 105 |
90 private BluetoothChooserDialogWithFakeNatives createDialog() { | 106 private BluetoothChooserDialogWithFakeNatives createDialog() { |
91 return ThreadUtils.runOnUiThreadBlockingNoException( | 107 return ThreadUtils.runOnUiThreadBlockingNoException( |
92 new Callable<BluetoothChooserDialogWithFakeNatives>() { | 108 new Callable<BluetoothChooserDialogWithFakeNatives>() { |
93 @Override | 109 @Override |
94 public BluetoothChooserDialogWithFakeNatives call() { | 110 public BluetoothChooserDialogWithFakeNatives call() { |
95 mWindowAndroid = new ActivityWindowAndroid(getActivity()
); | 111 mWindowAndroid = new ActivityWindowAndroid(getActivity()
); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 | 149 |
134 CriteriaHelper.pollUiThread(new Criteria() { | 150 CriteriaHelper.pollUiThread(new Criteria() { |
135 @Override | 151 @Override |
136 public boolean isSatisfied() { | 152 public boolean isSatisfied() { |
137 return chooserDialog.mFinishedEventType != -1; | 153 return chooserDialog.mFinishedEventType != -1; |
138 } | 154 } |
139 }); | 155 }); |
140 } | 156 } |
141 | 157 |
142 /** | 158 /** |
143 * The messages include <link> ... </link> or <link1> ... </link1>, <link2>
... </link2> | 159 * The messages include <*link*> ... </*link*> sections that are used to cre
ate clickable spans. |
144 * sections that are used to create clickable spans. For testing the message
s, this function | 160 * For testing the messages, this function returns the raw string without th
e tags. |
145 * returns the raw string without the tags. | |
146 */ | 161 */ |
147 private static String removeLinkTags(String message) { | 162 private static String removeLinkTags(String message) { |
148 return message.replaceAll("</?link1>", "").replaceAll( | 163 return message.replaceAll("</?[^>]*link[^>]*>", ""); |
149 "</?link2>", "").replaceAll("</?link>", ""); | |
150 } | 164 } |
151 | 165 |
152 @SmallTest | 166 @SmallTest |
153 public void testCancel() throws InterruptedException { | 167 public void testCancel() throws InterruptedException { |
154 ItemChooserDialog itemChooser = mChooserDialog.mItemChooserDialog; | 168 ItemChooserDialog itemChooser = mChooserDialog.mItemChooserDialog; |
155 Dialog dialog = itemChooser.getDialogForTesting(); | 169 Dialog dialog = itemChooser.getDialogForTesting(); |
156 assertTrue(dialog.isShowing()); | 170 assertTrue(dialog.isShowing()); |
157 | 171 |
158 TextViewWithClickableSpans statusView = | 172 TextViewWithClickableSpans statusView = |
159 (TextViewWithClickableSpans) dialog.findViewById(R.id.status); | 173 (TextViewWithClickableSpans) dialog.findViewById(R.id.status); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 // Permission was requested. | 277 // Permission was requested. |
264 MoreAsserts.assertEquals(permissionDelegate.mPermissionsRequested, | 278 MoreAsserts.assertEquals(permissionDelegate.mPermissionsRequested, |
265 new String[] {Manifest.permission.ACCESS_COARSE_LOCATION}); | 279 new String[] {Manifest.permission.ACCESS_COARSE_LOCATION}); |
266 assertNotNull(permissionDelegate.mCallback); | 280 assertNotNull(permissionDelegate.mCallback); |
267 // Grant permission. | 281 // Grant permission. |
268 permissionDelegate.mLocationGranted = true; | 282 permissionDelegate.mLocationGranted = true; |
269 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | 283 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
270 @Override | 284 @Override |
271 public void run() { | 285 public void run() { |
272 permissionDelegate.mCallback.onRequestPermissionsResult( | 286 permissionDelegate.mCallback.onRequestPermissionsResult( |
273 new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, | 287 new String[] {Manifest.permission.ACCESS_COARSE_LOCATION
}, |
274 new int[] {PackageManager.PERMISSION_GRANTED}); | 288 new int[] {PackageManager.PERMISSION_GRANTED}); |
275 } | 289 } |
276 }); | 290 }); |
277 | 291 |
278 assertEquals(removeLinkTags(getActivity().getString(R.string.bluetooth_a
dapter_off_help)), | 292 assertEquals(1, mChooserDialog.mRestartSearchCount); |
| 293 assertEquals(removeLinkTags(getActivity().getString(R.string.bluetooth_s
earching)), |
279 statusView.getText().toString()); | 294 statusView.getText().toString()); |
280 | 295 |
281 mChooserDialog.closeDialog(); | 296 mChooserDialog.closeDialog(); |
| 297 } |
| 298 |
| 299 @SmallTest |
| 300 public void testNoLocationServices() throws InterruptedException { |
| 301 ItemChooserDialog itemChooser = mChooserDialog.mItemChooserDialog; |
| 302 Dialog dialog = itemChooser.getDialogForTesting(); |
| 303 assertTrue(dialog.isShowing()); |
| 304 |
| 305 final TextViewWithClickableSpans statusView = |
| 306 (TextViewWithClickableSpans) dialog.findViewById(R.id.status); |
| 307 final TextViewWithClickableSpans errorView = |
| 308 (TextViewWithClickableSpans) dialog.findViewById(R.id.not_found_
message); |
| 309 final View items = dialog.findViewById(R.id.items); |
| 310 final Button button = (Button) dialog.findViewById(R.id.positive); |
| 311 final View progress = dialog.findViewById(R.id.progress); |
| 312 |
| 313 final TestAndroidPermissionDelegate permissionDelegate = |
| 314 new TestAndroidPermissionDelegate(); |
| 315 mWindowAndroid.setAndroidPermissionDelegate(permissionDelegate); |
| 316 |
| 317 // Grant permissions, and turn off location services. |
| 318 permissionDelegate.mLocationGranted = true; |
| 319 mLocationSettings.mSystemLocationSettingsEnabled = false; |
| 320 |
| 321 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 322 @Override |
| 323 public void run() { |
| 324 mChooserDialog.notifyDiscoveryState( |
| 325 BluetoothChooserDialog.DISCOVERY_FAILED_TO_START); |
| 326 } |
| 327 }); |
| 328 |
| 329 assertEquals(removeLinkTags( |
| 330 getActivity().getString(R.string.bluetooth_need_loc
ation_services_on)), |
| 331 errorView.getText().toString()); |
| 332 assertEquals(removeLinkTags(getActivity().getString( |
| 333 R.string.bluetooth_need_location_permission_help)), |
| 334 statusView.getText().toString()); |
| 335 assertFalse(button.isEnabled()); |
| 336 assertEquals(View.VISIBLE, errorView.getVisibility()); |
| 337 assertEquals(View.GONE, items.getVisibility()); |
| 338 assertEquals(View.GONE, progress.getVisibility()); |
| 339 |
| 340 // Turn on Location Services. |
| 341 mLocationSettings.mSystemLocationSettingsEnabled = true; |
| 342 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 343 @Override |
| 344 public void run() { |
| 345 mChooserDialog.mLocationModeBroadcastReceiver.onReceive( |
| 346 getActivity(), new Intent(LocationManager.MODE_CHANGED_A
CTION)); |
| 347 } |
| 348 }); |
| 349 |
| 350 assertEquals(1, mChooserDialog.mRestartSearchCount); |
| 351 assertEquals(removeLinkTags(getActivity().getString(R.string.bluetooth_s
earching)), |
| 352 statusView.getText().toString()); |
| 353 |
| 354 mChooserDialog.closeDialog(); |
282 } | 355 } |
283 | 356 |
284 // TODO(jyasskin): Test when the user denies Chrome the ability to ask for p
ermission. | 357 // TODO(jyasskin): Test when the user denies Chrome the ability to ask for p
ermission. |
285 | 358 |
286 private static class TestAndroidPermissionDelegate implements AndroidPermiss
ionDelegate { | 359 private static class TestAndroidPermissionDelegate implements AndroidPermiss
ionDelegate { |
287 boolean mLocationGranted = false; | 360 boolean mLocationGranted = false; |
288 PermissionCallback mCallback = null; | 361 PermissionCallback mCallback = null; |
289 String[] mPermissionsRequested = null; | 362 String[] mPermissionsRequested = null; |
290 | 363 |
291 @Override | 364 @Override |
(...skipping 11 matching lines...) Expand all Loading... |
303 } | 376 } |
304 @Override | 377 @Override |
305 public void requestPermissions(String[] permissions, PermissionCallback
callback) { | 378 public void requestPermissions(String[] permissions, PermissionCallback
callback) { |
306 mPermissionsRequested = permissions; | 379 mPermissionsRequested = permissions; |
307 if (permissions.length == 1 | 380 if (permissions.length == 1 |
308 && permissions[0].equals(Manifest.permission.ACCESS_COARSE_L
OCATION)) { | 381 && permissions[0].equals(Manifest.permission.ACCESS_COARSE_L
OCATION)) { |
309 mCallback = callback; | 382 mCallback = callback; |
310 } | 383 } |
311 } | 384 } |
312 } | 385 } |
| 386 |
| 387 private static class TestLocationSettings extends LocationSettings { |
| 388 public TestLocationSettings(Context context) { |
| 389 super(context); |
| 390 } |
| 391 |
| 392 public boolean mSystemLocationSettingsEnabled = true; |
| 393 |
| 394 @Override |
| 395 public boolean isSystemLocationSettingEnabled() { |
| 396 return mSystemLocationSettingsEnabled; |
| 397 } |
| 398 } |
313 } | 399 } |
OLD | NEW |