From 76dbb21cb527463a62b8b999541d24700f2a0e01 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Thu, 5 Apr 2018 14:44:13 -0700 Subject: [PATCH] Protect against invalid authority in account sync pref. Some apps might contain account synclets with empty authority. Settings UI should protect against this type of synclets. Otherwise clicking on these synclets will crash. (Also removed some strings that are no longer needed) Change-Id: I364b45fc67679aa287ff1e04e6f5ac749116543a Fixes: 74240862 Test: robotests --- res/values/strings.xml | 4 -- .../accounts/AccountSyncSettings.java | 9 ++- .../accounts/SyncStateSwitchPreference.java | 2 + .../SyncStateSwitchPreferenceTest.java | 62 +++++++++++++++++++ 4 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/accounts/SyncStateSwitchPreferenceTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 7507de2dee8..650f9d9d282 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5922,10 +5922,6 @@ Removing this account will delete all of its messages, contacts, and other data from the device! This change isn\'t allowed by your admin - - Push subscriptions - - %s Can\u2019t manually sync diff --git a/src/com/android/settings/accounts/AccountSyncSettings.java b/src/com/android/settings/accounts/AccountSyncSettings.java index d83694da449..6b60e87f85c 100644 --- a/src/com/android/settings/accounts/AccountSyncSettings.java +++ b/src/com/android/settings/accounts/AccountSyncSettings.java @@ -194,25 +194,24 @@ public class AccountSyncSettings extends AccountPreferenceBase { } else { item.setup(account, authority, packageName, uid); } + final PackageManager packageManager = getPackageManager(); item.setPersistent(false); - final ProviderInfo providerInfo = getPackageManager().resolveContentProviderAsUser( + final ProviderInfo providerInfo = packageManager.resolveContentProviderAsUser( authority, 0, mUserHandle.getIdentifier()); if (providerInfo == null) { return; } - CharSequence providerLabel = providerInfo.loadLabel(getPackageManager()); + final CharSequence providerLabel = providerInfo.loadLabel(packageManager); if (TextUtils.isEmpty(providerLabel)) { Log.e(TAG, "Provider needs a label for authority '" + authority + "'"); return; } - String title = getString(R.string.sync_item_title, providerLabel); - item.setTitle(title); + item.setTitle(providerLabel); item.setKey(authority); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - MenuItem syncNow = menu.add(0, MENU_SYNC_NOW_ID, 0, getString(R.string.sync_menu_sync_now)) .setIcon(R.drawable.ic_menu_refresh_holo_dark); diff --git a/src/com/android/settings/accounts/SyncStateSwitchPreference.java b/src/com/android/settings/accounts/SyncStateSwitchPreference.java index 058fedd9e7d..456edbabc2d 100644 --- a/src/com/android/settings/accounts/SyncStateSwitchPreference.java +++ b/src/com/android/settings/accounts/SyncStateSwitchPreference.java @@ -21,6 +21,7 @@ import android.app.ActivityManager; import android.content.Context; import android.support.v14.preference.SwitchPreference; import android.support.v7.preference.PreferenceViewHolder; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.View; @@ -64,6 +65,7 @@ public class SyncStateSwitchPreference extends SwitchPreference { mAuthority = authority; mPackageName = packageName; mUid = uid; + setVisible(!TextUtils.isEmpty(mAuthority)); notifyChanged(); } diff --git a/tests/robotests/src/com/android/settings/accounts/SyncStateSwitchPreferenceTest.java b/tests/robotests/src/com/android/settings/accounts/SyncStateSwitchPreferenceTest.java new file mode 100644 index 00000000000..0d454181f7e --- /dev/null +++ b/tests/robotests/src/com/android/settings/accounts/SyncStateSwitchPreferenceTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.accounts; + +import static com.google.common.truth.Truth.assertThat; + +import android.accounts.Account; +import android.content.Context; +import android.os.UserHandle; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class SyncStateSwitchPreferenceTest { + + private Context mContext; + private SyncStateSwitchPreference mPreference; + + @Before + public void setup() { + mContext = RuntimeEnvironment.application; + } + + @Test + public void setup_validAuthority_shouldBeVisible() { + mPreference = new SyncStateSwitchPreference(mContext, null /* attrs */); + + mPreference.setup(new Account("name", "type"), "authority", mContext.getPackageName(), + UserHandle.USER_CURRENT); + + assertThat(mPreference.isVisible()).isTrue(); + } + + @Test + public void setup_emptyAuthority_shouldBeInvisible() { + mPreference = new SyncStateSwitchPreference(mContext, null /* attrs */); + + mPreference.setup(new Account("name", "type"), null /* authority */, + mContext.getPackageName(), UserHandle.USER_CURRENT); + + assertThat(mPreference.isVisible()).isFalse(); + } +}