Commit d7d3dc88 authored by Natalie Chouinard's avatar Natalie Chouinard Committed by Commit Bot

Migrate Site Category Preferences to SL

Migrate the SingleCategoryPreferences and ChosenObjectPreferences from
deprecated Framework preferences to Support Library preferences.

This change also removes the complete fragment layout override used by
Storage preferences in favor of simply appending the custom views to the
bottom of the layout.

Because this is the first fragment migrated which contains a
ChromeImageViewPreference, it includes some duplication of code so that
the compat and non-compat image view preferences can coexist. Once the
remaining ChromeImageViewPreferences are migrated to support library,
this duplicate code will be removed (https://crbug.com/967022).

Bug: 968592, 929743
Change-Id: I3a0ed1ec24d2824d22cfecf50c2053bd62a45add
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1706540
Commit-Queue: Natalie Chouinard <chouinard@chromium.org>
Reviewed-by: default avatarTheresa <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#678505}
parent eeed93d3
......@@ -1231,6 +1231,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/preferences/ChromeBasePreference.java",
"java/src/org/chromium/chrome/browser/preferences/ChromeBasePreferenceCompat.java",
"java/src/org/chromium/chrome/browser/preferences/ChromeImageViewPreference.java",
"java/src/org/chromium/chrome/browser/preferences/ChromeImageViewPreferenceCompat.java",
"java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java",
"java/src/org/chromium/chrome/browser/preferences/ChromeSwitchPreference.java",
"java/src/org/chromium/chrome/browser/preferences/ChromeSwitchPreferenceCompat.java",
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2016 The Chromium Authors. All rights reserved.
<!-- Copyright 2019 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<!-- TODO(https://crbug.com/929743): Use standard layout and specify only bottom button here. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent">
<org.chromium.ui.widget.OptimizedFrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<ListView android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_shadow_height"
android:layout_gravity="bottom"
android:background="@drawable/modern_toolbar_shadow"
android:scaleY="-1"
tools:ignore="ContentDescription" />
</org.chromium.ui.widget.OptimizedFrameLayout>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- TODO(crbug.com/971791): Copied over this TextView for empty state because there are minor
UI differences between it and the built-in android.R.id.empty view in support library
preferences, but we should later investigate whether we can remove this and take advantage
of the default implementation instead. -->
<TextView
android:id="@android:id/empty"
android:id="@+id/empty_storage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:padding="8dp"
android:text="@string/no_saved_website_settings"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center"
android:visibility="gone" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_shadow_height"
android:layout_gravity="bottom"
android:background="@drawable/modern_toolbar_shadow"
android:scaleY="-1" />
<org.chromium.ui.widget.ButtonCompat
android:id="@+id/clear_button"
style="@style/TextButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingTop="16dp"
android:text="@string/storage_clear_button_title"
app:verticalInset="0dp"
style="@style/TextButton" />
</LinearLayout>
\ No newline at end of file
app:verticalInset="0dp" />
</merge>
\ No newline at end of file
......@@ -3,14 +3,14 @@
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<PreferenceScreen
<android.support.v7.preference.PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:title="@string/all_sites">
<!-- A common binary toggle, only shown for specific categories that allow
turning default values for that category on/off.-->
<org.chromium.chrome.browser.preferences.ChromeSwitchPreference
<org.chromium.chrome.browser.preferences.ChromeSwitchPreferenceCompat
android:key="binary_toggle"
android:defaultValue="true" />
<!-- A common Allow/Ask/Block 3-state toggle (radio group). Only shown when
......@@ -20,20 +20,20 @@
android:key="tri_state_toggle" />
<!-- A toggle for blocking third-party cookies, only shown for the Cookies category. -->
<org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreference
<org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreferenceCompat
android:key="third_party_cookies"
android:title="@string/block_third_party_cookies_title"
android:summary="@string/block_third_party_cookies_summary"
android:defaultValue="true"
android:persistent="false" />
<!-- A toggle for enabling vibration in notifications. -->
<org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreference
<org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreferenceCompat
android:key="notifications_vibrate"
android:title="@string/enable_notifications_vibrate_title"
android:summary="@string/enable_notifications_vibrate_summary"
android:defaultValue="true" />
<!-- An hyperlink to explain more about Protected Media content settings. -->
<org.chromium.chrome.browser.preferences.LearnMorePreference
<org.chromium.chrome.browser.preferences.LearnMorePreferenceCompat
android:key="protected_content_learn_more"
android:background="?android:attr/listDivider"
app:helpContext="@string/help_context_protected_content"/>
......@@ -45,4 +45,4 @@
android:key="blocked_group" />
<org.chromium.chrome.browser.preferences.ExpandablePreferenceGroup
android:key="allowed_group" />
</PreferenceScreen>
</android.support.v7.preference.PreferenceScreen>
......@@ -114,7 +114,7 @@ public class ClearDataDialogActivity extends AppCompatActivity {
extras.putInt(SettingsNavigationSource.EXTRA_KEY,
SettingsNavigationSource.TWA_CLEAR_DATA_DIALOG);
PreferencesLauncher.launchSettingsPage(this, SingleCategoryPreferences.class, extras);
PreferencesLauncher.launchSettingsPageCompat(this, SingleCategoryPreferences.class, extras);
}
private void recordDecision(boolean accepted) {
......
......@@ -4,7 +4,6 @@
package org.chromium.chrome.browser.notifications;
import android.app.Fragment;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
......@@ -266,10 +265,6 @@ public class NotificationPlatformBridge {
String origin = getOriginFromIntent(incomingIntent);
boolean launchSingleWebsitePreferences = origin != null;
Class<? extends Fragment> fragment = launchSingleWebsitePreferences
? SingleWebsitePreferences.class
: SingleCategoryPreferences.class;
Bundle fragmentArguments;
if (launchSingleWebsitePreferences) {
// Record that the user has clicked on the [Site Settings] button.
......@@ -287,7 +282,13 @@ public class NotificationPlatformBridge {
R.string.push_notifications_permission_title));
}
PreferencesLauncher.launchSettingsPage(applicationContext, fragment, fragmentArguments);
if (launchSingleWebsitePreferences) {
PreferencesLauncher.launchSettingsPage(
applicationContext, SingleWebsitePreferences.class, fragmentArguments);
} else {
PreferencesLauncher.launchSettingsPageCompat(
applicationContext, SingleCategoryPreferences.class, fragmentArguments);
}
}
/**
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.preferences;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import org.chromium.chrome.R;
/**
* TODO(crbug.com/967022): This class is a duplicate of {@link ChromeImageViewPreference}, but with
* Support Library classes replacing deprecated Framework classes. When Preference Support Library
* migration is complete remove {@link ChromeImageViewPreference} in favor of this class.
*
* A preference that supports some Chrome-specific customizations:
*
* 1. This preference supports being managed. If this preference is managed (as determined by its
* ManagedPreferenceDelegate), it updates its appearance and behavior appropriately: shows an
* enterprise icon in its widget ImageView, disables clicks, etc.
* 2. This preference can have a multiline title.
* 3. This preference can have an onClick listener set for its ImageView widget.
*
* The preference includes the preference_chrome_image_view widget layout to provide these
* customizations, however a custom widget may also be included as long as there is an ImageView
* with the image_view_widget ID.
*/
public class ChromeImageViewPreferenceCompat extends Preference {
@Nullable
private ManagedPreferenceDelegateCompat mManagedPrefDelegate;
// The onClick listener to handle click events for the ImageView widget.
@Nullable
private View.OnClickListener mListener;
// The image resource ID to use for the ImageView widget source.
@DrawableRes
private int mImageRes;
// The string resource ID to use for the ImageView widget content description.
@StringRes
private int mContentDescriptionRes;
// Whether the ImageView should be enabled.
private boolean mImageViewEnabled = true;
/**
* Constructor for use in Java.
*/
public ChromeImageViewPreferenceCompat(Context context) {
this(context, null);
}
/**
* Constructor for inflating from XML.
*/
public ChromeImageViewPreferenceCompat(Context context, AttributeSet attrs) {
super(context, attrs);
setWidgetLayoutResource(R.layout.preference_chrome_image_view);
setSingleLineTitle(false);
}
/**
* Sets the ManagedPreferenceDelegate which will determine whether this preference is managed.
*/
public void setManagedPreferenceDelegate(@Nullable ManagedPreferenceDelegateCompat delegate) {
mManagedPrefDelegate = delegate;
ManagedPreferencesUtils.initPreference(mManagedPrefDelegate, this);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
ImageView button = (ImageView) holder.findViewById(R.id.image_view_widget);
View view = holder.itemView;
if (mImageRes != 0) {
Drawable buttonImg = PreferenceUtils.getTintedIcon(getContext(), mImageRes);
button.setImageDrawable(buttonImg);
button.setBackgroundColor(Color.TRANSPARENT);
button.setVisibility(View.VISIBLE);
button.setEnabled(mImageViewEnabled);
if (mImageViewEnabled) button.setOnClickListener(mListener);
if (mContentDescriptionRes != 0) {
button.setContentDescription(view.getResources().getString(mContentDescriptionRes));
}
}
ManagedPreferencesUtils.onBindViewToImageViewPreference(mManagedPrefDelegate, this, view);
}
@Override
protected void onClick() {
if (ManagedPreferencesUtils.onClickPreference(mManagedPrefDelegate, this)) return;
super.onClick();
}
/**
* Sets the Drawable resource ID, the String resource ID, and the OnClickListener for the
* ImageView widget's source, content description, and onClick, respectively.
*/
public void setImageView(@DrawableRes int imageRes, @StringRes int contentDescriptionRes,
@Nullable View.OnClickListener listener) {
mImageRes = imageRes;
mContentDescriptionRes = contentDescriptionRes;
mListener = listener;
notifyChanged();
}
/**
* Enables/Disables the ImageView, allowing for clicks to pass through (when disabled).
*/
public void setImageViewEnabled(boolean enabled) {
mImageViewEnabled = enabled;
}
/**
* If a {@link ManagedPreferenceDelegate} has been set, check if this preference is managed.
* @return True if the preference is managed.
*/
public boolean isManaged() {
if (mManagedPrefDelegate == null) return false;
return mManagedPrefDelegate.isPreferenceControlledByPolicy(this)
|| mManagedPrefDelegate.isPreferenceControlledByCustodian(this);
}
}
......@@ -6,10 +6,10 @@ package org.chromium.chrome.browser.preferences;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.preference.PreferenceGroup;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.content.res.AppCompatResources;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.view.View;
......@@ -30,13 +30,6 @@ public class ExpandablePreferenceGroup extends PreferenceGroup {
public ExpandablePreferenceGroup(Context context, AttributeSet attrs) {
super(context, attrs, android.R.attr.preferenceStyle);
setWidgetLayoutResource(R.layout.checkable_image_view_widget);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Fix animations. Background: setWidgetLayout resource call above disables view
// recycling, thus breaking animations. Views recycling is safe in this case, as this
// Preference doesn't change view types on the fly.
setRecycleEnabled(true);
}
}
/** Returns whether the preference group is expanded. */
......@@ -59,18 +52,19 @@ public class ExpandablePreferenceGroup extends PreferenceGroup {
protected void onExpandedChanged(boolean expanded) {}
@Override
protected void onBindView(View view) {
super.onBindView(view);
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
if (mDrawable == null) {
mDrawable = createDrawable(getContext());
}
CheckableImageView imageView =
(CheckableImageView) view.findViewById(R.id.checkable_image_view);
(CheckableImageView) holder.findViewById(R.id.checkable_image_view);
imageView.setImageDrawable(mDrawable);
imageView.setChecked(mExpanded);
// For accessibility, read out the whole title and whether the group is collapsed/expanded.
View view = holder.itemView;
String description = getTitle() + getContext().getResources().getString(mExpanded
? R.string.accessibility_expanded_group
: R.string.accessibility_collapsed_group);
......
......@@ -95,6 +95,32 @@ public class ManagedPreferencesUtils {
return preference.getIcon();
}
/**
* TODO(crbug.com/967022): This method is a duplicate of {@link
* #getManagedIconDrawable(ManagedPreferenceDelegate, Preference)}, but with Support Library
* classes replacing deprecated Framework classes. When Preference Support Library migration is
* complete remove {@link #getManagedIconDrawable(ManagedPreferenceDelegate, Preference)} in
* favor of this method.
*
* @return The appropriate Drawable based on whether the preference is controlled by a policy or
* a custodian.
*/
public static Drawable getManagedIconDrawable(
@Nullable ManagedPreferenceDelegateCompat delegate,
android.support.v7.preference.Preference preference) {
if (delegate == null) return preference.getIcon();
if (delegate.isPreferenceControlledByPolicy(preference)) {
return PreferenceUtils.getTintedIcon(
preference.getContext(), getManagedByEnterpriseIconId());
} else if (delegate.isPreferenceControlledByCustodian(preference)) {
return PreferenceUtils.getTintedIcon(
preference.getContext(), getManagedByCustodianIconId());
}
return preference.getIcon();
}
/**
* Initializes the Preference based on the state of any policies that may affect it,
* e.g. by showing a managed icon or disabling clicks on the preference. If |preference| is an
......@@ -146,13 +172,9 @@ public class ManagedPreferencesUtils {
android.support.v7.preference.Preference preference) {
if (delegate == null) return;
// TODO(chouinard): A compat version of ChromeImageViewPreference hasn't been created yet.
// Once it is, uncomment this section.
/*
if (!(preference instanceof ChromeImageViewPreference)) {
if (!(preference instanceof ChromeImageViewPreferenceCompat)) {
preference.setIcon(getManagedIconDrawable(delegate, preference));
}
*/
if (delegate.isPreferenceClickDisabledByPolicy(preference)) {
// Disable the views and prevent the Preference from mucking with the enabled state.
......@@ -267,6 +289,47 @@ public class ManagedPreferencesUtils {
});
}
/**
* TODO(crbug.com/967022): This method is a duplicate of {@link
* #onBindViewToPreference(ManagedPreferenceDelegate, Preference, View)}, but with Support
* Library classes replacing deprecated Framework classes. When Preference Support Library
* migration is complete remove {@link #onBindViewToPreference(ManagedPreferenceDelegate,
* Preference, View)} in favor of this method.
*
* Calls onBindViewToPreference() above. Then, if the ChromeImageViewPreference is managed, the
* widget ImageView is set to the appropriate managed icon, and its onClick listener is set to
* show the appropriate managed message toast.
*
* This should be called from the Preference's onBindView() method.
*
* @param delegate The delegate that controls whether the preference is managed. May be null,
* then this method does nothing.
* @param preference The ChromeImageViewPreference that owns the view.
* @param view The View that was bound to the ChromeImageViewPreference.
*/
public static void onBindViewToImageViewPreference(
@Nullable ManagedPreferenceDelegateCompat delegate,
ChromeImageViewPreferenceCompat preference, View view) {
if (delegate == null) return;
onBindViewToPreference(delegate, preference, view);
if (!delegate.isPreferenceControlledByPolicy(preference)
&& !delegate.isPreferenceControlledByCustodian(preference)) {
return;
}
ImageView button = view.findViewById(R.id.image_view_widget);
button.setImageDrawable(getManagedIconDrawable(delegate, preference));
button.setOnClickListener((View v) -> {
if (delegate.isPreferenceControlledByPolicy(preference)) {
showManagedByAdministratorToast(preference.getContext());
} else if (delegate.isPreferenceControlledByCustodian(preference)) {
showManagedByParentToast(preference.getContext());
}
});
}
/**
* Intercepts the click event if the given Preference is managed and shows a toast in that case.
*
......
......@@ -10,10 +10,10 @@ import android.content.res.Resources;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Vibrator;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.provider.Settings;
import android.support.v7.app.AlertDialog;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
......@@ -30,7 +30,8 @@ import org.chromium.ui.KeyboardVisibilityDelegate;
* A utility class for the UI recording exceptions to the blocked list for site
* settings.
*/
public class AddExceptionPreference extends Preference implements OnPreferenceClickListener {
public class AddExceptionPreference
extends Preference implements Preference.OnPreferenceClickListener {
// The callback to notify when the user adds a site.
private SiteAddedCallback mSiteAddedCallback;
......@@ -81,9 +82,9 @@ public class AddExceptionPreference extends Preference implements OnPreferenceCl
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
TextView titleView = (TextView) view.findViewById(android.R.id.title);
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
TextView titleView = (TextView) holder.findViewById(android.R.id.title);
titleView.setAllCaps(true);
titleView.setTextColor(mPrefAccentColor);
}
......
......@@ -4,29 +4,28 @@
package org.chromium.chrome.browser.preferences.website;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.support.graphics.drawable.VectorDrawableCompat;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.widget.SearchView;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.ListView;
import org.chromium.base.annotations.RemovableInRelease;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.help.HelpAndFeedback;
import org.chromium.chrome.browser.preferences.ChromeImageViewPreference;
import org.chromium.chrome.browser.preferences.ManagedPreferenceDelegate;
import org.chromium.chrome.browser.preferences.ChromeImageViewPreferenceCompat;
import org.chromium.chrome.browser.preferences.ManagedPreferenceDelegateCompat;
import org.chromium.chrome.browser.preferences.ManagedPreferencesUtils;
import org.chromium.chrome.browser.preferences.PreferenceUtils;
import org.chromium.chrome.browser.profiles.Profile;
import java.util.ArrayList;
......@@ -37,7 +36,7 @@ import java.util.Locale;
* Shows a particular chosen object (e.g. a USB device) and the list of sites that have been
* granted access to it by the user.
*/
public class ChosenObjectPreferences extends PreferenceFragment {
public class ChosenObjectPreferences extends PreferenceFragmentCompat {
public static final String EXTRA_OBJECT_INFOS = "org.chromium.chrome.preferences.object_infos";
public static final String EXTRA_SITES = "org.chromium.chrome.preferences.site_set";
public static final String EXTRA_CATEGORY =
......@@ -54,13 +53,17 @@ public class ChosenObjectPreferences extends PreferenceFragment {
// If not blank, represents a substring to use to search for site names.
private String mSearch = "";
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
// Set empty preferences screen.
PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getStyledContext());
setPreferenceScreen(screen);
}
@Override
@SuppressWarnings("unchecked")
public void onActivityCreated(Bundle savedInstanceState) {
PreferenceUtils.addPreferencesFromResource(this, R.xml.blank_preference_fragment_screen);
ListView listView = (ListView) getView().findViewById(android.R.id.list);
listView.setDivider(null);
setDivider(null);
int contentSettingsType = getArguments().getInt(EXTRA_CATEGORY);
mCategory = SiteSettingsCategory.createFromContentSettingsType(contentSettingsType);
mObjectInfos =
......@@ -226,7 +229,8 @@ public class ChosenObjectPreferences extends PreferenceFragment {
*/
private void createHeader() {
PreferenceScreen preferenceScreen = getPreferenceScreen();
ChromeImageViewPreference header = new ChromeImageViewPreference(getActivity());
ChromeImageViewPreferenceCompat header =
new ChromeImageViewPreferenceCompat(getStyledContext());
String titleText = mObjectInfos.get(0).getName();
String dialogMsg =
String.format(getView().getContext().getString(
......@@ -249,7 +253,10 @@ public class ChosenObjectPreferences extends PreferenceFragment {
});
preferenceScreen.addPreference(header);
Preference divider = new Preference(getActivity());
// TODO(chouinard): Handle this header and divider in a cleaner way. May need to migrate
// WebsitePreference to extend ChromeBasePreferenceCompat to more easily set dividers
// programmatically.
Preference divider = new Preference(getStyledContext());
divider.setLayoutResource(R.layout.divider_preference);
preferenceScreen.addPreference(divider);
}
......@@ -268,7 +275,8 @@ public class ChosenObjectPreferences extends PreferenceFragment {
for (int i = 0; i < mSites.size() && i < mObjectInfos.size(); ++i) {
Website site = mSites.get(i);
ChosenObjectInfo info = mObjectInfos.get(i);
WebsitePreference preference = new WebsitePreference(getActivity(), site, mCategory);
WebsitePreference preference =
new WebsitePreference(getStyledContext(), site, mCategory);
preference.getExtras().putSerializable(SingleWebsitePreferences.EXTRA_SITE, site);
preference.setFragment(SingleWebsitePreferences.class.getCanonicalName());
......@@ -278,7 +286,7 @@ public class ChosenObjectPreferences extends PreferenceFragment {
getInfo();
});
preference.setManagedPreferenceDelegate(new ManagedPreferenceDelegate() {
preference.setManagedPreferenceDelegate(new ManagedPreferenceDelegateCompat() {
@Override
public boolean isPreferenceControlledByPolicy(Preference preference) {
return info.isManaged();
......@@ -301,4 +309,8 @@ public class ChosenObjectPreferences extends PreferenceFragment {
// Force this list to be reloaded if the activity is resumed.
mSites = null;
}
private Context getStyledContext() {
return getPreferenceManager().getContext();
}
}
......@@ -242,7 +242,7 @@ public class ManageSpaceActivity extends AppCompatActivity implements View.OnCli
getString(R.string.website_settings_storage));
RecordHistogram.recordEnumeratedHistogram(
"Android.ManageSpace.ActionTaken", OPTION_MANAGE_STORAGE, OPTION_MAX);
PreferencesLauncher.launchSettingsPage(
PreferencesLauncher.launchSettingsPageCompat(
this, SingleCategoryPreferences.class, initialArguments);
} else if (view == mClearAllDataButton) {
final ActivityManager activityManager =
......
......@@ -316,7 +316,6 @@ public class SiteSettingsCategory {
* calling this method, if osWarningExtra has no title, the preference
* should not be added to the preference screen.
* @param activity The current activity.
* @param category The category associated with the warnings.
* @param specificCategory Whether the warnings refer to a single category or is an aggregate
* for many permissions.
*/
......@@ -359,6 +358,66 @@ public class SiteSettingsCategory {
}
}
/**
* TODO(crbug.com/967022): This method is a duplicate of {@link
* #configurePermissionIsOffPreferences(Preference, Preference, Activity, boolean)}, but with
* Support Library classes replacing deprecated Framework classes. When Preference Support
* Library migration is complete remove {@link #configurePermissionIsOffPreferences(Preference,
* Preference, Activity, boolean)} in favor of this method.
*
* Configure a preference to show when when the Android permission for this category is
* disabled.
* @param osWarning A preference to hold the first permission warning. After calling this
* method, if osWarning has no title, the preference should not be added to the
* preference screen.
* @param osWarningExtra A preference to hold any additional permission warning (if any). After
* calling this method, if osWarningExtra has no title, the preference
* should not be added to the preference screen.
* @param activity The current activity.
* @param specificCategory Whether the warnings refer to a single category or is an aggregate
* for many permissions.
*/
public void configurePermissionIsOffPreferences(
android.support.v7.preference.Preference osWarning,
android.support.v7.preference.Preference osWarningExtra, Activity activity,
boolean specificCategory) {
Intent perAppIntent = getIntentToEnableOsPerAppPermission(activity);
Intent globalIntent = getIntentToEnableOsGlobalPermission(activity);
String perAppMessage = getMessageForEnablingOsPerAppPermission(activity, !specificCategory);
String globalMessage = getMessageForEnablingOsGlobalPermission(activity);
Resources resources = activity.getResources();
int color = ApiCompatibilityUtils.getColor(resources, R.color.pref_accent_color);
ForegroundColorSpan linkSpan = new ForegroundColorSpan(color);
if (perAppIntent != null) {
SpannableString messageWithLink = SpanApplier.applySpans(
perAppMessage, new SpanInfo("<link>", "</link>", linkSpan));
osWarning.setTitle(messageWithLink);
osWarning.setIntent(perAppIntent);
if (!specificCategory) {
osWarning.setIcon(getDisabledInAndroidIcon(activity));
}
}
if (globalIntent != null) {
SpannableString messageWithLink = SpanApplier.applySpans(
globalMessage, new SpanInfo("<link>", "</link>", linkSpan));
osWarningExtra.setTitle(messageWithLink);
osWarningExtra.setIntent(globalIntent);
if (!specificCategory) {
if (perAppIntent == null) {
osWarningExtra.setIcon(getDisabledInAndroidIcon(activity));
} else {
Drawable transparent = new ColorDrawable(Color.TRANSPARENT);
osWarningExtra.setIcon(transparent);
}
}
}
}
/**
* Returns the icon for permissions that have been disabled by Android.
*/
......
......@@ -5,10 +5,9 @@
package org.chromium.chrome.browser.preferences.website;
import android.content.Context;
import android.preference.Preference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.widget.RadioButtonWithDescription;
......@@ -29,6 +28,10 @@ public class TriStateSiteSettingsPreference
public TriStateSiteSettingsPreference(Context context, AttributeSet attrs) {
super(context, attrs);
// Inflating from XML.
setLayoutResource(R.layout.tri_state_site_settings_preference);
// Make unselectable, otherwise TriStateSiteSettingsPreference is treated as one
// selectable Preference, instead of three selectable radio buttons.
// Allows radio buttons to be selected via Bluetooth keyboard (key events).
......@@ -53,13 +56,6 @@ public class TriStateSiteSettingsPreference
return mSetting;
}
@Override
public View onCreateView(ViewGroup parent) {
// Inflating from XML.
setLayoutResource(R.layout.tri_state_site_settings_preference);
return super.onCreateView(parent);
}
@Override
public void onCheckedChanged() {
if (mAllowed.isChecked())
......@@ -73,16 +69,18 @@ public class TriStateSiteSettingsPreference
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mAllowed = (RadioButtonWithDescription) view.findViewById(R.id.allowed);
mAsk = (RadioButtonWithDescription) view.findViewById(R.id.ask);
mBlocked = (RadioButtonWithDescription) view.findViewById(R.id.blocked);
mAllowed = (RadioButtonWithDescription) holder.findViewById(R.id.allowed);
mAsk = (RadioButtonWithDescription) holder.findViewById(R.id.ask);
mBlocked = (RadioButtonWithDescription) holder.findViewById(R.id.blocked);
mAllowed.setDescriptionText(getContext().getText(mDescriptionIds[0]));
mAsk.setDescriptionText(getContext().getText(mDescriptionIds[1]));
mBlocked.setDescriptionText(getContext().getText(mDescriptionIds[2]));
if (mDescriptionIds != null) {
mAllowed.setDescriptionText(getContext().getText(mDescriptionIds[0]));
mAsk.setDescriptionText(getContext().getText(mDescriptionIds[1]));
mBlocked.setDescriptionText(getContext().getText(mDescriptionIds[2]));
}
List<RadioButtonWithDescription> radioGroup = Arrays.asList(mAllowed, mAsk, mBlocked);
for (RadioButtonWithDescription option : radioGroup) {
......
......@@ -11,7 +11,8 @@ import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.preference.Preference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.text.format.Formatter;
import android.view.View;
import android.widget.TextView;
......@@ -20,6 +21,7 @@ import org.chromium.chrome.R;
import org.chromium.chrome.browser.favicon.FaviconHelper;
import org.chromium.chrome.browser.favicon.FaviconHelper.FaviconImageCallback;
import org.chromium.chrome.browser.preferences.ChromeImageViewPreference;
import org.chromium.chrome.browser.preferences.ChromeImageViewPreferenceCompat;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.widget.RoundedIconGenerator;
......@@ -29,7 +31,7 @@ import org.chromium.chrome.browser.widget.RoundedIconGenerator;
* of the preference. See {@link ChromeImageViewPreference} for more details on how this icon can
* be used.
*/
class WebsitePreference extends ChromeImageViewPreference implements FaviconImageCallback {
class WebsitePreference extends ChromeImageViewPreferenceCompat implements FaviconImageCallback {
private final Website mSite;
private final SiteSettingsCategory mCategory;
......@@ -139,10 +141,10 @@ class WebsitePreference extends ChromeImageViewPreference implements FaviconImag
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
TextView usageText = (TextView) view.findViewById(R.id.usage_text);
TextView usageText = (TextView) holder.findViewById(R.id.usage_text);
usageText.setVisibility(View.GONE);
if (mCategory.showSites(SiteSettingsCategory.Type.USE_STORAGE)) {
long totalUsage = mSite.getTotalUsage();
......@@ -165,7 +167,7 @@ class WebsitePreference extends ChromeImageViewPreference implements FaviconImag
float density = getContext().getResources().getDisplayMetrics().density;
int iconPadding = Math.round(FAVICON_PADDING_DP * density);
View iconView = view.findViewById(android.R.id.icon);
View iconView = holder.findViewById(android.R.id.icon);
iconView.setPadding(iconPadding, iconPadding, iconPadding, iconPadding);
}
}
......@@ -4,7 +4,6 @@
package org.chromium.chrome.browser.browserservices.permissiondelegation;
import android.preference.Preference;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
......@@ -82,7 +81,7 @@ public class TrustedWebActivityPreferencesUiTest {
final SingleCategoryPreferences websitePreferences =
TestThreadUtils.runOnUiThreadBlocking(() -> {
final SingleCategoryPreferences preferences =
(SingleCategoryPreferences) preferenceActivity.getMainFragment();
(SingleCategoryPreferences) preferenceActivity.getMainFragmentCompat();
final ExpandablePreferenceGroup group =
(ExpandablePreferenceGroup) preferences.findPreference(groupName);
preferences.onPreferenceClick(group);
......@@ -104,7 +103,7 @@ public class TrustedWebActivityPreferencesUiTest {
final ExpandablePreferenceGroup group =
(ExpandablePreferenceGroup) websitePreferences.findPreference(groupName);
Assert.assertEquals(1, group.getPreferenceCount());
Preference preference = group.getPreference(0);
android.support.v7.preference.Preference preference = group.getPreference(0);
CharSequence title = preference.getTitle();
Assert.assertEquals("example.com", title.toString());
});
......
......@@ -80,8 +80,8 @@ public class NotificationPlatformBridgeIntentTest {
});
Assert.assertNotNull("Could not find the Preferences activity", activity);
SingleCategoryPreferences fragment =
ActivityUtils.waitForFragmentToAttach(activity, SingleCategoryPreferences.class);
SingleCategoryPreferences fragment = ActivityUtils.waitForFragmentToAttachCompat(
activity, SingleCategoryPreferences.class);
Assert.assertNotNull("Could not find the SingleCategoryPreferences fragment", fragment);
}
......
......@@ -4,10 +4,10 @@
package org.chromium.chrome.browser.preferences;
import android.app.Fragment;
import android.os.Build;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.v4.app.Fragment;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat;
......@@ -173,7 +173,7 @@ public class NotificationsPreferencesTest {
/** Gets the fragment of the top Activity. Assumes the top Activity is a Preferences. */
private static Fragment getTopFragment() {
Preferences preferences = (Preferences) ApplicationStatus.getLastTrackedFocusedActivity();
return preferences.getMainFragment();
return preferences.getMainFragmentCompat();
}
/** Gets the summary text that should be used for site specific notifications. */
......
......@@ -4,11 +4,11 @@
package org.chromium.chrome.browser.preferences.website;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.support.v7.preference.PreferenceScreen;
import android.util.Pair;
import org.junit.After;
......@@ -28,8 +28,8 @@ import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.ContentSettingsType;
import org.chromium.chrome.browser.infobar.InfoBarContainer;
import org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreference;
import org.chromium.chrome.browser.preferences.ChromeSwitchPreference;
import org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreferenceCompat;
import org.chromium.chrome.browser.preferences.ChromeSwitchPreferenceCompat;
import org.chromium.chrome.browser.preferences.LocationSettings;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.preferences.Preferences;
......@@ -82,9 +82,9 @@ public class SiteSettingsPreferencesTest {
TestThreadUtils.runOnUiThreadBlocking(() -> {
SingleCategoryPreferences websitePreferences =
(SingleCategoryPreferences) preferenceActivity.getMainFragment();
ChromeSwitchPreference location =
(ChromeSwitchPreference) websitePreferences.findPreference(
(SingleCategoryPreferences) preferenceActivity.getMainFragmentCompat();
ChromeSwitchPreferenceCompat location =
(ChromeSwitchPreferenceCompat) websitePreferences.findPreference(
SingleCategoryPreferences.BINARY_TOGGLE_KEY);
websitePreferences.onPreferenceChange(location, enabled);
......@@ -155,12 +155,12 @@ public class SiteSettingsPreferencesTest {
@Override
public void run() {
final SingleCategoryPreferences websitePreferences =
(SingleCategoryPreferences) preferenceActivity.getMainFragment();
final ChromeSwitchPreference cookies =
(ChromeSwitchPreference) websitePreferences.findPreference(
(SingleCategoryPreferences) preferenceActivity.getMainFragmentCompat();
final ChromeSwitchPreferenceCompat cookies =
(ChromeSwitchPreferenceCompat) websitePreferences.findPreference(
SingleCategoryPreferences.BINARY_TOGGLE_KEY);
final ChromeBaseCheckBoxPreference thirdPartyCookies =
(ChromeBaseCheckBoxPreference) websitePreferences.findPreference(
final ChromeBaseCheckBoxPreferenceCompat thirdPartyCookies =
(ChromeBaseCheckBoxPreferenceCompat) websitePreferences.findPreference(
SingleCategoryPreferences.THIRD_PARTY_COOKIES_TOGGLE_KEY);
if (thirdPartyCookies != null) {
......@@ -184,9 +184,9 @@ public class SiteSettingsPreferencesTest {
final boolean enabled) {
TestThreadUtils.runOnUiThreadBlocking(() -> {
final SingleCategoryPreferences websitePreferences =
(SingleCategoryPreferences) preferenceActivity.getMainFragment();
final ChromeBaseCheckBoxPreference thirdPartyCookies =
(ChromeBaseCheckBoxPreference) websitePreferences.findPreference(
(SingleCategoryPreferences) preferenceActivity.getMainFragmentCompat();
final ChromeBaseCheckBoxPreferenceCompat thirdPartyCookies =
(ChromeBaseCheckBoxPreferenceCompat) websitePreferences.findPreference(
SingleCategoryPreferences.THIRD_PARTY_COOKIES_TOGGLE_KEY);
websitePreferences.onPreferenceChange(thirdPartyCookies, enabled);
......@@ -203,9 +203,10 @@ public class SiteSettingsPreferencesTest {
TestThreadUtils.runOnUiThreadBlocking(() -> {
SingleCategoryPreferences preferences =
(SingleCategoryPreferences) preferenceActivity.getMainFragment();
ChromeSwitchPreference toggle = (ChromeSwitchPreference) preferences.findPreference(
SingleCategoryPreferences.BINARY_TOGGLE_KEY);
(SingleCategoryPreferences) preferenceActivity.getMainFragmentCompat();
ChromeSwitchPreferenceCompat toggle =
(ChromeSwitchPreferenceCompat) preferences.findPreference(
SingleCategoryPreferences.BINARY_TOGGLE_KEY);
preferences.onPreferenceChange(toggle, enabled);
});
preferenceActivity.finish();
......@@ -244,8 +245,8 @@ public class SiteSettingsPreferencesTest {
SiteSettingsTestUtils.startSiteSettingsCategory(type);
TestThreadUtils.runOnUiThreadBlocking(() -> {
PreferenceFragment preferenceFragment =
(PreferenceFragment) preferenceActivity.getMainFragment();
PreferenceFragmentCompat preferenceFragment =
(PreferenceFragmentCompat) preferenceActivity.getMainFragmentCompat();
PreferenceScreen preferenceScreen = preferenceFragment.getPreferenceScreen();
int preferenceCount = preferenceScreen.getPreferenceCount();
......
......@@ -73,8 +73,8 @@ public class TouchlessPreferencesTest {
Assert.assertTrue(activity instanceof TouchlessPreferences);
SingleCategoryPreferences cookiesPreferences =
(SingleCategoryPreferences) activity.getMainFragment();
(SingleCategoryPreferences) activity.getMainFragmentCompat();
Assert.assertNull(cookiesPreferences.findPreference(
SingleCategoryPreferences.THIRD_PARTY_COOKIES_TOGGLE_KEY));
}
}
\ No newline at end of file
}
......@@ -208,4 +208,34 @@ public class ActivityUtils {
}, ACTIVITY_START_TIMEOUT_MS, CONDITION_POLL_INTERVAL_MS);
return (T) activity.getMainFragment();
}
/**
* TODO(crbug.com/967022): This method is a duplicate of {@link #waitForFragment(Activity,
* String)}, but with Support Library classes replacing deprecated Framework classes. When
* Preference Support Library migration is complete remove {@link #waitForFragment(Activity,
* String)} in favor of this method.
*
* Waits until the specified fragment has been attached to the specified activity. Note that
* we don't guarantee that the fragment is visible. Some UI operations can happen too
* quickly and we can miss the time that a fragment is visible. This method allows you to get a
* reference to any fragment that was attached to the activity at any point.
*
* @param <T> A subclass of {@link android.support.v4.app.Fragment}.
* @param activity An instance or subclass of {@link Preferences}.
* @param fragmentClass The class object for {@link T}.
* @return A reference to the requested fragment or null.
*/
@SuppressWarnings("unchecked")
public static <T extends android.support.v4.app.Fragment> T waitForFragmentToAttachCompat(
final Preferences activity, final Class<T> fragmentClass) {
String failureReason = String.format(
"Could not find fragment of type %s", fragmentClass.getCanonicalName());
CriteriaHelper.pollInstrumentationThread(new Criteria(failureReason) {
@Override
public boolean isSatisfied() {
return fragmentClass.isInstance(activity.getMainFragmentCompat());
}
}, ACTIVITY_START_TIMEOUT_MS, CONDITION_POLL_INTERVAL_MS);
return (T) activity.getMainFragmentCompat();
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment