Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 76dbb21c authored by Fan Zhang's avatar Fan Zhang
Browse files

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
parent a8c53f7d
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -5922,10 +5922,6 @@
    <string name="really_remove_account_message" product="device">Removing this account will delete all of its messages, contacts, and other data from the device!</string>
    <!-- This is shown if the autheticator for a given account fails to remove it. [CHAR LIMIT=NONE] -->
    <string name="remove_account_failed">This change isn\'t allowed by your admin</string>
    <!-- What to show in messaging that refers to this provider, e.g. AccountSyncSettings -->
    <string name="provider_label">Push subscriptions</string>
    <!-- Formatter in AccountSyncSettings for each application we wish to synchronize, e.g. "Sync Calendar" -->
    <string name="sync_item_title"><xliff:g id="authority" example="Calendar">%s</xliff:g></string>
    <!-- Title of dialog shown when you can't manually sync an item because it's disabled -->
    <string name="cant_sync_dialog_title">Can\u2019t manually sync</string>
    <!-- Messaage shown in dialog when you can't manually sync -->
+4 −5
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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();
    }

+62 −0
Original line number Diff line number Diff line
/*
 * 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();
    }
}