• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.webview;
18 
19 import static android.provider.Settings.ACTION_WEBVIEW_SETTINGS;
20 import static com.google.common.truth.Truth.assertThat;
21 import static org.mockito.Matchers.any;
22 import static org.mockito.Matchers.anyInt;
23 import static org.mockito.Matchers.eq;
24 import static org.mockito.Mockito.doNothing;
25 import static org.mockito.Mockito.doReturn;
26 import static org.mockito.Mockito.mock;
27 import static org.mockito.Mockito.never;
28 import static org.mockito.Mockito.spy;
29 import static org.mockito.Mockito.times;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.when;
32 
33 import android.app.Activity;
34 import android.content.Context;
35 import android.content.Intent;
36 import android.content.pm.ApplicationInfo;
37 import android.content.pm.PackageInfo;
38 import android.content.pm.PackageItemInfo;
39 import android.content.pm.PackageManager;
40 import android.content.pm.UserInfo;
41 import android.os.UserManager;
42 import android.webkit.UserPackage;
43 
44 import com.android.settings.testutils.SettingsRobolectricTestRunner;
45 import com.android.settings.widget.RadioButtonPreference;
46 import com.android.settingslib.applications.DefaultAppInfo;
47 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
48 import com.android.settingslib.wrapper.PackageManagerWrapper;
49 
50 import org.junit.Before;
51 import org.junit.Test;
52 import org.junit.runner.RunWith;
53 import org.mockito.Answers;
54 import org.mockito.Mock;
55 import org.mockito.MockitoAnnotations;
56 import org.robolectric.RuntimeEnvironment;
57 import org.robolectric.util.ReflectionHelpers;
58 
59 import java.util.Arrays;
60 import java.util.Collections;
61 
62 @RunWith(SettingsRobolectricTestRunner.class)
63 public class WebViewAppPickerTest {
64 
65     private final static String DEFAULT_PACKAGE_NAME = "DEFAULT_PACKAGE_NAME";
66 
67     private Context mContext;
68 
69     private UserInfo mFirstUser;
70     private UserInfo mSecondUser;
71 
72     @Mock
73     private Activity mActivity;
74     @Mock
75     private UserManager mUserManager;
76     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
77     private PackageManagerWrapper mPackageManager;
78 
79     private WebViewAppPicker mPicker;
80     private WebViewUpdateServiceWrapper mWvusWrapper;
81 
createApplicationInfo(String packageName)82     private static ApplicationInfo createApplicationInfo(String packageName) {
83         ApplicationInfo ai = new ApplicationInfo();
84         ai.packageName = packageName;
85         return ai;
86     }
87 
88     @Before
setUp()89     public void setUp() {
90         MockitoAnnotations.initMocks(this);
91         mContext = spy(RuntimeEnvironment.application);
92         doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
93         mFirstUser = new UserInfo(0, "FIRST_USER", 0);
94         mSecondUser = new UserInfo(0, "SECOND_USER", 0);
95         mPicker = new WebViewAppPicker();
96         mPicker = spy(mPicker);
97         doNothing().when(mPicker).updateCandidates();
98         doNothing().when(mPicker).updateCheckedState(any());
99         doReturn(mActivity).when(mPicker).getActivity();
100 
101         ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
102         ReflectionHelpers.setField(mPicker, "mMetricsFeatureProvider",
103                 mock(MetricsFeatureProvider.class));
104         mWvusWrapper = mock(WebViewUpdateServiceWrapper.class);
105         mPicker.setWebViewUpdateServiceWrapper(mWvusWrapper);
106     }
107 
108     @Test
testClickingItemChangesProvider()109     public void testClickingItemChangesProvider() {
110         testSuccessfulClickChangesProvider();
111     }
112 
113     @Test
testFailingClick()114     public void testFailingClick() {
115         testFailingClickUpdatesSetting();
116     }
117 
118     @Test
testClickingItemInActivityModeChangesProviderAndFinishes()119     public void testClickingItemInActivityModeChangesProviderAndFinishes() {
120         useWebViewSettingIntent();
121         testSuccessfulClickChangesProvider();
122         verify(mActivity, times(1)).finish();
123     }
124 
125     @Test
testFailingClickInActivityMode()126     public void testFailingClickInActivityMode() {
127         useWebViewSettingIntent();
128         testFailingClick();
129     }
130 
useWebViewSettingIntent()131     private void useWebViewSettingIntent() {
132         Intent intent = new Intent(ACTION_WEBVIEW_SETTINGS);
133         when(mActivity.getIntent()).thenReturn(intent);
134     }
135 
testSuccessfulClickChangesProvider()136     private void testSuccessfulClickChangesProvider() {
137         when(mWvusWrapper.getValidWebViewApplicationInfos(any()))
138                 .thenReturn(Collections.singletonList(createApplicationInfo(DEFAULT_PACKAGE_NAME)));
139         when(mWvusWrapper.setWebViewProvider(eq(DEFAULT_PACKAGE_NAME))).thenReturn(true);
140 
141         RadioButtonPreference defaultPackagePref = mock(RadioButtonPreference.class);
142         when(defaultPackagePref.getKey()).thenReturn(DEFAULT_PACKAGE_NAME);
143         mPicker.onRadioButtonClicked(defaultPackagePref);
144 
145         verify(mWvusWrapper, times(1)).setWebViewProvider(eq(DEFAULT_PACKAGE_NAME));
146         verify(mPicker, times(1)).updateCheckedState(DEFAULT_PACKAGE_NAME);
147         verify(mWvusWrapper, never()).showInvalidChoiceToast(any());
148     }
149 
testFailingClickUpdatesSetting()150     private void testFailingClickUpdatesSetting() {
151         when(mWvusWrapper.getValidWebViewApplicationInfos(any()))
152                 .thenReturn(Collections.singletonList(createApplicationInfo(DEFAULT_PACKAGE_NAME)));
153         when(mWvusWrapper.setWebViewProvider(eq(DEFAULT_PACKAGE_NAME))).thenReturn(false);
154 
155         RadioButtonPreference defaultPackagePref = mock(RadioButtonPreference.class);
156         when(defaultPackagePref.getKey()).thenReturn(DEFAULT_PACKAGE_NAME);
157         mPicker.onRadioButtonClicked(defaultPackagePref);
158 
159         verify(mWvusWrapper, times(1)).setWebViewProvider(eq(DEFAULT_PACKAGE_NAME));
160         // Ensure we update the list of packages when we click a non-valid package - the list must
161         // have changed, otherwise this click wouldn't fail.
162         verify(mPicker, times(1)).updateCandidates();
163         verify(mWvusWrapper, times(1)).showInvalidChoiceToast(any());
164     }
165 
166     @Test
testDisabledPackageShownAsDisabled()167     public void testDisabledPackageShownAsDisabled() {
168         DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext, mPackageManager,
169                 createApplicationInfo(DEFAULT_PACKAGE_NAME), "disabled");
170 
171         RadioButtonPreference preference = mock(RadioButtonPreference.class);
172         mPicker.bindPreference(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
173         mPicker.bindPreferenceExtra(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
174         verify(preference, times(1)).setEnabled(eq(false));
175         verify(preference, never()).setEnabled(eq(true));
176     }
177 
178     @Test
testEnabledPackageShownAsEnabled()179     public void testEnabledPackageShownAsEnabled() {
180         String disabledReason = "";
181         DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext, mPackageManager,
182                 createApplicationInfo(DEFAULT_PACKAGE_NAME), disabledReason);
183 
184         RadioButtonPreference preference = mock(RadioButtonPreference.class);
185         mPicker.bindPreference(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
186         mPicker.bindPreferenceExtra(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
187         verify(preference, times(1)).setEnabled(eq(true));
188         verify(preference, never()).setEnabled(eq(false));
189     }
190 
191     @Test
testDisabledPackageShowsDisabledReasonSummary()192     public void testDisabledPackageShowsDisabledReasonSummary() {
193         String disabledReason = "disabled";
194         DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext, mPackageManager,
195                 createApplicationInfo(DEFAULT_PACKAGE_NAME), disabledReason);
196 
197         RadioButtonPreference preference = mock(RadioButtonPreference.class);
198         mPicker.bindPreference(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
199         mPicker.bindPreferenceExtra(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
200         verify(preference, times(1)).setSummary(eq(disabledReason));
201         // Ensure we haven't called setSummary several times.
202         verify(preference, times(1)).setSummary(any());
203     }
204 
205     @Test
testEnabledPackageShowsEmptySummary()206     public void testEnabledPackageShowsEmptySummary() {
207         DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext, mPackageManager,
208                 createApplicationInfo(DEFAULT_PACKAGE_NAME), null);
209 
210         RadioButtonPreference preference = mock(RadioButtonPreference.class);
211         mPicker.bindPreference(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
212         mPicker.bindPreferenceExtra(preference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
213         verify(preference, never()).setSummary(any());
214     }
215 
216     @Test
testFinishIfNotAdmin()217     public void testFinishIfNotAdmin() {
218         doReturn(false).when(mUserManager).isAdminUser();
219         mPicker.onAttach(mContext);
220         verify(mActivity, times(1)).finish();
221     }
222 
223     @Test
testNotFinishedIfAdmin()224     public void testNotFinishedIfAdmin() {
225         doReturn(true).when(mUserManager).isAdminUser();
226         mPicker.onAttach(mContext);
227         verify(mActivity, never()).finish();
228     }
229 
230     @Test
testDisabledReasonNullIfPackagesOk()231     public void testDisabledReasonNullIfPackagesOk() {
232         UserPackage packageForFirstUser = mock(UserPackage.class);
233         when(packageForFirstUser.isEnabledPackage()).thenReturn(true);
234         when(packageForFirstUser.isInstalledPackage()).thenReturn(true);
235 
236         UserPackage packageForSecondUser = mock(UserPackage.class);
237         when(packageForSecondUser.isEnabledPackage()).thenReturn(true);
238         when(packageForSecondUser.isInstalledPackage()).thenReturn(true);
239 
240         WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
241         when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
242                 .thenReturn(Arrays.asList(packageForFirstUser, packageForSecondUser));
243 
244         assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, DEFAULT_PACKAGE_NAME)).isNull();
245     }
246 
247     @Test
testDisabledReasonForSingleUserDisabledPackage()248     public void testDisabledReasonForSingleUserDisabledPackage() {
249         UserPackage packageForFirstUser = mock(UserPackage.class);
250         when(packageForFirstUser.isEnabledPackage()).thenReturn(false);
251         when(packageForFirstUser.isInstalledPackage()).thenReturn(true);
252         when(packageForFirstUser.getUserInfo()).thenReturn(mFirstUser);
253 
254         WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
255         when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
256                 .thenReturn(Collections.singletonList(packageForFirstUser));
257 
258         final String expectedReason = String.format("(disabled for user %s)", mFirstUser.name);
259         assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, DEFAULT_PACKAGE_NAME))
260                 .isEqualTo(expectedReason);
261     }
262 
263     @Test
testDisabledReasonForSingleUserUninstalledPackage()264     public void testDisabledReasonForSingleUserUninstalledPackage() {
265         UserPackage packageForFirstUser = mock(UserPackage.class);
266         when(packageForFirstUser.isEnabledPackage()).thenReturn(true);
267         when(packageForFirstUser.isInstalledPackage()).thenReturn(false);
268         when(packageForFirstUser.getUserInfo()).thenReturn(mFirstUser);
269 
270         WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
271         when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
272                 .thenReturn(Collections.singletonList(packageForFirstUser));
273 
274         final String expectedReason = String.format("(uninstalled for user %s)", mFirstUser.name);
275         assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, DEFAULT_PACKAGE_NAME))
276                 .isEqualTo(expectedReason);
277     }
278 
279     @Test
testDisabledReasonSeveralUsers()280     public void testDisabledReasonSeveralUsers() {
281         UserPackage packageForFirstUser = mock(UserPackage.class);
282         when(packageForFirstUser.isEnabledPackage()).thenReturn(false);
283         when(packageForFirstUser.isInstalledPackage()).thenReturn(true);
284         when(packageForFirstUser.getUserInfo()).thenReturn(mFirstUser);
285 
286         UserPackage packageForSecondUser = mock(UserPackage.class);
287         when(packageForSecondUser.isEnabledPackage()).thenReturn(true);
288         when(packageForSecondUser.isInstalledPackage()).thenReturn(false);
289         when(packageForSecondUser.getUserInfo()).thenReturn(mSecondUser);
290 
291         WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
292         when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
293                 .thenReturn(Arrays.asList(packageForFirstUser, packageForSecondUser));
294 
295         final String expectedReason = String.format("(disabled for user %s)", mFirstUser.name);
296         assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, DEFAULT_PACKAGE_NAME))
297                 .isEqualTo(expectedReason);
298     }
299 
300     /**
301      * Ensure we only proclaim a package as uninstalled for a certain user if it's both uninstalled
302      * and disabled.
303      */
304     @Test
testDisabledReasonUninstalledAndDisabled()305     public void testDisabledReasonUninstalledAndDisabled() {
306         UserPackage packageForFirstUser = mock(UserPackage.class);
307         when(packageForFirstUser.isEnabledPackage()).thenReturn(false);
308         when(packageForFirstUser.isInstalledPackage()).thenReturn(false);
309         when(packageForFirstUser.getUserInfo()).thenReturn(mFirstUser);
310 
311         UserPackage packageForSecondUser = mock(UserPackage.class);
312         when(packageForSecondUser.isEnabledPackage()).thenReturn(true);
313         when(packageForSecondUser.isInstalledPackage()).thenReturn(true);
314         when(packageForSecondUser.getUserInfo()).thenReturn(mSecondUser);
315 
316         WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
317         when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
318                 .thenReturn(Arrays.asList(packageForFirstUser, packageForSecondUser));
319 
320         final String expectedReason = String.format("(uninstalled for user %s)", mFirstUser.name);
321         assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, DEFAULT_PACKAGE_NAME))
322                 .isEqualTo(expectedReason);
323     }
324 
325     /**
326      * Ensure that the version name of a WebView package is displayed after its name in the
327      * preference title.
328      */
329     @Test
testWebViewVersionAddedAfterLabel()330     public void testWebViewVersionAddedAfterLabel() throws PackageManager.NameNotFoundException {
331         PackageItemInfo mockPackageItemInfo = mock(PackageItemInfo.class);
332         mockPackageItemInfo.packageName = DEFAULT_PACKAGE_NAME;
333         when(mockPackageItemInfo.loadLabel(any())).thenReturn("myPackage");
334         DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mContext, mPackageManager,
335                 mockPackageItemInfo, "" /* disabledReason */);
336 
337         PackageInfo packageInfo = new PackageInfo();
338         packageInfo.versionName = "myVersionName";
339         PackageManager pm = mock(PackageManager.class);
340         when(pm.getPackageInfo(eq(DEFAULT_PACKAGE_NAME), anyInt())).thenReturn(packageInfo);
341         when(mPackageManager.getPackageManager()).thenReturn(pm);
342 
343         RadioButtonPreference mockPreference = mock(RadioButtonPreference.class);
344         mPicker.bindPreference(mockPreference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
345         mPicker
346                 .bindPreferenceExtra(mockPreference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null,
347                         null);
348         verify(mockPreference, times(1)).setTitle(eq("myPackage myVersionName"));
349         verify(mockPreference, times(1)).setTitle(any());
350     }
351 }
352