Home | History | Annotate | Download | only in webview
      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 
     43 import com.android.settings.SettingsRobolectricTestRunner;
     44 import com.android.settings.TestConfig;
     45 import com.android.settings.applications.PackageManagerWrapper;
     46 import com.android.settings.applications.defaultapps.DefaultAppInfo;
     47 import com.android.settings.widget.RadioButtonPreference;
     48 
     49 import org.junit.Before;
     50 import org.junit.Test;
     51 import org.junit.runner.RunWith;
     52 import org.mockito.Answers;
     53 import org.mockito.Mock;
     54 import org.mockito.MockitoAnnotations;
     55 import org.robolectric.RuntimeEnvironment;
     56 import org.robolectric.annotation.Config;
     57 import org.robolectric.util.ReflectionHelpers;
     58 
     59 import java.util.Arrays;
     60 
     61 @RunWith(SettingsRobolectricTestRunner.class)
     62 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
     63 public class WebViewAppPickerTest {
     64     private Context mContext = RuntimeEnvironment.application;
     65 
     66     private final static UserInfo FIRST_USER = new UserInfo(0, "FIRST_USER", 0);
     67     private final static UserInfo SECOND_USER = new UserInfo(0, "SECOND_USER", 0);
     68 
     69     private final static String DEFAULT_PACKAGE_NAME = "DEFAULT_PACKAGE_NAME";
     70 
     71     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     72     private Activity mActivity;
     73     @Mock
     74     private UserManager mUserManager;
     75     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     76     private PackageManagerWrapper mPackageManager;
     77 
     78     private WebViewAppPicker mPicker;
     79     private WebViewUpdateServiceWrapper mWvusWrapper;
     80 
     81     private static ApplicationInfo createApplicationInfo(String packageName) {
     82         ApplicationInfo ai = new ApplicationInfo();
     83         ai.packageName = packageName;
     84         return ai;
     85     }
     86 
     87     @Before
     88     public void setUp() {
     89         MockitoAnnotations.initMocks(this);
     90         when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
     91 
     92         mPicker = new WebViewAppPicker();
     93         mPicker = spy(mPicker);
     94         doNothing().when(mPicker).updateCandidates();
     95         doNothing().when(mPicker).updateCheckedState(any());
     96         doReturn(mActivity).when(mPicker).getActivity();
     97 
     98         ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
     99 
    100         mWvusWrapper = mock(WebViewUpdateServiceWrapper.class);
    101         mPicker.setWebViewUpdateServiceWrapper(mWvusWrapper);
    102     }
    103 
    104     @Test
    105     public void testClickingItemChangesProvider() {
    106         testSuccessfulClickChangesProvider();
    107     }
    108 
    109     @Test
    110     public void testFailingClick() {
    111         testFailingClickUpdatesSetting();
    112     }
    113 
    114     @Test
    115     public void testClickingItemInActivityModeChangesProviderAndFinishes() {
    116         useWebViewSettingIntent();
    117         testSuccessfulClickChangesProvider();
    118         verify(mActivity, times(1)).finish();
    119     }
    120 
    121     @Test
    122     public void testFailingClickInActivityMode() {
    123         useWebViewSettingIntent();
    124         testFailingClick();
    125     }
    126 
    127     private void useWebViewSettingIntent() {
    128         Intent intent = new Intent(ACTION_WEBVIEW_SETTINGS);
    129         when(mActivity.getIntent()).thenReturn(intent);
    130     }
    131 
    132     private void testSuccessfulClickChangesProvider() {
    133         when(mWvusWrapper.getValidWebViewApplicationInfos(any())).thenReturn(
    134                 Arrays.asList(createApplicationInfo(DEFAULT_PACKAGE_NAME)));
    135         when(mWvusWrapper.setWebViewProvider(eq(DEFAULT_PACKAGE_NAME))).thenReturn(true);
    136 
    137         RadioButtonPreference defaultPackagePref = mock(RadioButtonPreference.class);
    138         when(defaultPackagePref.getKey()).thenReturn(DEFAULT_PACKAGE_NAME);
    139         mPicker.onRadioButtonClicked(defaultPackagePref);
    140 
    141         verify(mWvusWrapper, times(1)).setWebViewProvider(eq(DEFAULT_PACKAGE_NAME));
    142         verify(mPicker, times(1)).updateCheckedState(DEFAULT_PACKAGE_NAME);
    143         verify(mWvusWrapper, never()).showInvalidChoiceToast(any());
    144     }
    145 
    146     private void testFailingClickUpdatesSetting() {
    147         when(mWvusWrapper.getValidWebViewApplicationInfos(any())).thenReturn(
    148                 Arrays.asList(createApplicationInfo(DEFAULT_PACKAGE_NAME)));
    149         when(mWvusWrapper.setWebViewProvider(eq(DEFAULT_PACKAGE_NAME))).thenReturn(false);
    150 
    151         RadioButtonPreference defaultPackagePref = mock(RadioButtonPreference.class);
    152         when(defaultPackagePref.getKey()).thenReturn(DEFAULT_PACKAGE_NAME);
    153         mPicker.onRadioButtonClicked(defaultPackagePref);
    154 
    155         verify(mWvusWrapper, times(1)).setWebViewProvider(eq(DEFAULT_PACKAGE_NAME));
    156         // Ensure we update the list of packages when we click a non-valid package - the list must
    157         // have changed, otherwise this click wouldn't fail.
    158         verify(mPicker, times(1)).updateCandidates();
    159         verify(mWvusWrapper, times(1)).showInvalidChoiceToast(any());
    160     }
    161 
    162     @Test
    163     public void testDisabledPackageShownAsDisabled() {
    164         String disabledReason = "disabled";
    165         DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mPackageManager,
    166                 createApplicationInfo(DEFAULT_PACKAGE_NAME), disabledReason);
    167 
    168         RadioButtonPreference mockPreference = mock(RadioButtonPreference.class);
    169         mPicker.bindPreference(mockPreference,
    170                 DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
    171         mPicker.bindPreferenceExtra(mockPreference,
    172                 DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
    173         verify(mockPreference, times(1)).setEnabled(eq(false));
    174         verify(mockPreference, never()).setEnabled(eq(true));
    175     }
    176 
    177     @Test
    178     public void testEnabledPackageShownAsEnabled() {
    179         String disabledReason = "";
    180         DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mPackageManager,
    181                 createApplicationInfo(DEFAULT_PACKAGE_NAME), disabledReason);
    182 
    183         RadioButtonPreference mockPreference = mock(RadioButtonPreference.class);
    184         mPicker.bindPreference(mockPreference,
    185                 DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
    186         mPicker.bindPreferenceExtra(mockPreference,
    187                 DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
    188         verify(mockPreference, times(1)).setEnabled(eq(true));
    189         verify(mockPreference, never()).setEnabled(eq(false));
    190     }
    191 
    192     @Test
    193     public void testDisabledPackageShowsDisabledReasonSummary() {
    194         String disabledReason = "disabled";
    195         DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mPackageManager,
    196                 createApplicationInfo(DEFAULT_PACKAGE_NAME), disabledReason);
    197 
    198         RadioButtonPreference mockPreference = mock(RadioButtonPreference.class);
    199         mPicker.bindPreference(mockPreference,
    200                 DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
    201         mPicker.bindPreferenceExtra(mockPreference,
    202                 DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
    203         verify(mockPreference, times(1)).setSummary(eq(disabledReason));
    204         // Ensure we haven't called setSummary several times.
    205         verify(mockPreference, times(1)).setSummary(any());
    206     }
    207 
    208     @Test
    209     public void testEnabledPackageShowsEmptySummary() {
    210         String disabledReason = null;
    211         DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mPackageManager,
    212                 createApplicationInfo(DEFAULT_PACKAGE_NAME), disabledReason);
    213 
    214         RadioButtonPreference mockPreference = mock(RadioButtonPreference.class);
    215         mPicker.bindPreference(mockPreference,
    216                 DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
    217         mPicker.bindPreferenceExtra(mockPreference,
    218                 DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
    219         verify(mockPreference, never()).setSummary(any());
    220     }
    221 
    222     @Test
    223     public void testFinishIfNotAdmin() {
    224         doReturn(false).when(mUserManager).isAdminUser();
    225         mPicker.onAttach((Context) mActivity);
    226         verify(mActivity, times(1)).finish();
    227     }
    228 
    229     @Test
    230     public void testNotFinishedIfAdmin() {
    231         doReturn(true).when(mUserManager).isAdminUser();
    232         mPicker.onAttach((Context) mActivity);
    233         verify(mActivity, never()).finish();
    234     }
    235 
    236     @Test
    237     public void testDisabledReasonNullIfPackagesOk() {
    238         UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
    239         when(packageForFirstUser.isEnabledPackage()).thenReturn(true);
    240         when(packageForFirstUser.isInstalledPackage()).thenReturn(true);
    241 
    242         UserPackageWrapper packageForSecondUser = mock(UserPackageWrapper.class);
    243         when(packageForSecondUser.isEnabledPackage()).thenReturn(true);
    244         when(packageForSecondUser.isInstalledPackage()).thenReturn(true);
    245 
    246         WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
    247         when(wvusWrapper.getPackageInfosAllUsers(
    248                 any(), eq(DEFAULT_PACKAGE_NAME))).thenReturn(
    249                 Arrays.asList(packageForFirstUser, packageForSecondUser));
    250 
    251         assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, DEFAULT_PACKAGE_NAME)).isNull();
    252     }
    253 
    254     @Test
    255     public void testDisabledReasonForSingleUserDisabledPackage() {
    256         UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
    257         when(packageForFirstUser.isEnabledPackage()).thenReturn(false);
    258         when(packageForFirstUser.isInstalledPackage()).thenReturn(true);
    259         when(packageForFirstUser.getUserInfo()).thenReturn(FIRST_USER);
    260 
    261         WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
    262         when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
    263                 .thenReturn(Arrays.asList(packageForFirstUser));
    264 
    265         final String EXPECTED_DISABLED_REASON = String.format(
    266                 "(disabled for user %s)", FIRST_USER.name);
    267         assertThat(mPicker.getDisabledReason(wvusWrapper, mContext,
    268                 DEFAULT_PACKAGE_NAME)).isEqualTo(EXPECTED_DISABLED_REASON);
    269     }
    270 
    271     @Test
    272     public void testDisabledReasonForSingleUserUninstalledPackage() {
    273         UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
    274         when(packageForFirstUser.isEnabledPackage()).thenReturn(true);
    275         when(packageForFirstUser.isInstalledPackage()).thenReturn(false);
    276         when(packageForFirstUser.getUserInfo()).thenReturn(FIRST_USER);
    277 
    278         WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
    279         when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
    280                 .thenReturn(Arrays.asList(packageForFirstUser));
    281 
    282         final String EXPECTED_DISABLED_REASON = String.format(
    283                 "(uninstalled for user %s)", FIRST_USER.name);
    284         assertThat(mPicker.getDisabledReason(wvusWrapper, mContext,
    285                 DEFAULT_PACKAGE_NAME)).isEqualTo(EXPECTED_DISABLED_REASON);
    286     }
    287 
    288     @Test
    289     public void testDisabledReasonSeveralUsers() {
    290         UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
    291         when(packageForFirstUser.isEnabledPackage()).thenReturn(false);
    292         when(packageForFirstUser.isInstalledPackage()).thenReturn(true);
    293         when(packageForFirstUser.getUserInfo()).thenReturn(FIRST_USER);
    294 
    295         UserPackageWrapper packageForSecondUser = mock(UserPackageWrapper.class);
    296         when(packageForSecondUser.isEnabledPackage()).thenReturn(true);
    297         when(packageForSecondUser.isInstalledPackage()).thenReturn(false);
    298         when(packageForSecondUser.getUserInfo()).thenReturn(SECOND_USER);
    299 
    300         WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
    301         when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
    302                 .thenReturn(Arrays.asList(packageForFirstUser, packageForSecondUser));
    303 
    304         final String EXPECTED_DISABLED_REASON = String.format(
    305                 "(disabled for user %s)", FIRST_USER.name);
    306         assertThat(mPicker.getDisabledReason(
    307                 wvusWrapper, mContext, DEFAULT_PACKAGE_NAME)).isEqualTo(EXPECTED_DISABLED_REASON);
    308     }
    309 
    310     /**
    311      * Ensure we only proclaim a package as uninstalled for a certain user if it's both uninstalled
    312      * and disabled.
    313      */
    314     @Test
    315     public void testDisabledReasonUninstalledAndDisabled() {
    316         UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
    317         when(packageForFirstUser.isEnabledPackage()).thenReturn(false);
    318         when(packageForFirstUser.isInstalledPackage()).thenReturn(false);
    319         when(packageForFirstUser.getUserInfo()).thenReturn(FIRST_USER);
    320 
    321         UserPackageWrapper packageForSecondUser = mock(UserPackageWrapper.class);
    322         when(packageForSecondUser.isEnabledPackage()).thenReturn(true);
    323         when(packageForSecondUser.isInstalledPackage()).thenReturn(true);
    324         when(packageForSecondUser.getUserInfo()).thenReturn(SECOND_USER);
    325 
    326         WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
    327         when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)))
    328                 .thenReturn(Arrays.asList(packageForFirstUser, packageForSecondUser));
    329 
    330         final String EXPECTED_DISABLED_REASON = String.format(
    331                 "(uninstalled for user %s)", FIRST_USER.name);
    332         assertThat(mPicker.getDisabledReason(wvusWrapper, mContext,
    333                 DEFAULT_PACKAGE_NAME)).isEqualTo(EXPECTED_DISABLED_REASON);
    334     }
    335 
    336     /**
    337      * Ensure that the version name of a WebView package is displayed after its name in the
    338      * preference title.
    339      */
    340     @Test
    341     public void testWebViewVersionAddedAfterLabel() throws PackageManager.NameNotFoundException {
    342         PackageItemInfo mockPackageItemInfo = mock(PackageItemInfo.class);
    343         mockPackageItemInfo.packageName = DEFAULT_PACKAGE_NAME;
    344         when(mockPackageItemInfo.loadLabel(any())).thenReturn("myPackage");
    345         DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(mPackageManager,
    346                 mockPackageItemInfo, "" /* disabledReason */);
    347 
    348         PackageInfo packageInfo = new PackageInfo();
    349         packageInfo.versionName = "myVersionName";
    350         PackageManager pm = mock(PackageManager.class);
    351         when(pm.getPackageInfo(eq(DEFAULT_PACKAGE_NAME), anyInt())).thenReturn(packageInfo);
    352         when(mPackageManager.getPackageManager()).thenReturn(pm);
    353 
    354         RadioButtonPreference mockPreference = mock(RadioButtonPreference.class);
    355         mPicker.bindPreference(mockPreference,
    356                 DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
    357         mPicker.bindPreferenceExtra(mockPreference,
    358                 DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
    359         verify(mockPreference, times(1)).setTitle(eq("myPackage myVersionName"));
    360         verify(mockPreference, times(1)).setTitle(any());
    361     }
    362 }
    363