// Copyright 2015 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.website;

import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.SearchView;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.format.Formatter;
import android.text.style.ForegroundColorSpan;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.help.HelpAndFeedback;
import org.chromium.chrome.browser.media.cdm.MediaDrmCredentialManager;
import org.chromium.chrome.browser.media.cdm.MediaDrmCredentialManager.MediaDrmCredentialManagerCallback;
import org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreference;
import org.chromium.chrome.browser.preferences.ChromeBasePreference;
import org.chromium.chrome.browser.preferences.ChromeSwitchPreference;
import org.chromium.chrome.browser.preferences.ExpandablePreferenceGroup;
import org.chromium.chrome.browser.preferences.LocationSettings;
import org.chromium.chrome.browser.preferences.ManagedPreferenceDelegate;
import org.chromium.chrome.browser.preferences.ManagedPreferencesUtils;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.preferences.PreferenceUtils;
import org.chromium.chrome.browser.preferences.ProtectedContentResetCredentialConfirmDialogFragment;
import org.chromium.chrome.browser.preferences.website.Website.StoredDataClearedCallback;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.ui.widget.Toast;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * Shows a list of sites in a particular Site Settings category. For example, this could show all
 * the websites with microphone permissions. When the user selects a site, SingleWebsitePreferences
 * is launched to allow the user to see or modify the settings for that particular website.
 */
public class SingleCategoryPreferences extends PreferenceFragment
        implements OnPreferenceChangeListener, OnPreferenceClickListener,
                   AddExceptionPreference.SiteAddedCallback,
                   ProtectedContentResetCredentialConfirmDialogFragment.Listener,
                   View.OnClickListener {
    // The key to use to pass which category this preference should display,
    // e.g. Location/Popups/All sites (if blank).
    public static final String EXTRA_CATEGORY = "category";
    public static final String EXTRA_TITLE = "title";

    // The view to show when the list is empty.
    private TextView mEmptyView;
    // The view for searching the list of items.
    private SearchView mSearchView;
    // The clear button displayed in the Storage view.
    private Button mClearButton;
    // The Site Settings Category we are showing.
    private SiteSettingsCategory mCategory;
    // If not blank, represents a substring to use to search for site names.
    private String mSearch = "";
    // Whether to group by allowed/blocked list.
    private boolean mGroupByAllowBlock;
    // Whether the Blocked list should be shown expanded.
    private boolean mBlockListExpanded;
    // Whether the Allowed list should be shown expanded.
    private boolean mAllowListExpanded = true;
    // Whether this is the first time this screen is shown.
    private boolean mIsInitialRun = true;
    // The number of sites that are on the Allowed list.
    private int mAllowedSiteCount;
    // The websites that are currently displayed to the user.
    private List<WebsitePreference> mWebsites;

    // Keys for individual preferences.
    public static final String READ_WRITE_TOGGLE_KEY = "read_write_toggle";
    public static final String THIRD_PARTY_COOKIES_TOGGLE_KEY = "third_party_cookies";
    public static final String NOTIFICATIONS_VIBRATE_TOGGLE_KEY = "notifications_vibrate";
    public static final String EXPLAIN_PROTECTED_MEDIA_KEY = "protected_content_learn_more";
    private static final String ADD_EXCEPTION_KEY = "add_exception";
    // Keys for Allowed/Blocked preference groups/headers.
    private static final String ALLOWED_GROUP = "allowed_group";
    private static final String BLOCKED_GROUP = "blocked_group";

    private void getInfoForOrigins() {
        if (!mCategory.enabledInAndroid(getActivity())) {
            // No need to fetch any data if we're not going to show it, but we do need to update
            // the global toggle to reflect updates in Android settings (e.g. Location).
            resetList();
            return;
        }

        WebsitePermissionsFetcher fetcher =
                new WebsitePermissionsFetcher(new ResultsPopulator(), false);
        fetcher.fetchPreferencesForCategory(mCategory);
    }

    private class ResultsPopulator implements WebsitePermissionsFetcher.WebsitePermissionsCallback {
        @Override
        public void onWebsitePermissionsAvailable(Collection<Website> sites) {
            // This method may be called after the activity has been destroyed.
            // In that case, bail out.
            if (getActivity() == null) return;
            mWebsites = null;

            resetList();

            boolean hasEntries = mCategory.showSites(SiteSettingsCategory.Type.USB)
                    ? addChosenObjects(sites)
                    : addWebsites(sites);

            if (!hasEntries && mEmptyView != null)
                mEmptyView.setText(R.string.no_saved_website_settings);
        }
    }

    /**
     * Returns whether a website is on the Blocked list for the category currently showing.
     * @param website The website to check.
     */
    private boolean isOnBlockList(WebsitePreference website) {
        ContentSetting setting;
        // This list is ordered alphabetically by permission.
        if (mCategory.showSites(SiteSettingsCategory.Type.ADS)) {
            setting = website.site().getContentSettingPermission(ContentSettingException.Type.ADS);
        } else if (mCategory.showSites(SiteSettingsCategory.Type.AUTOPLAY)) {
            setting = website.site().getContentSettingPermission(
                    ContentSettingException.Type.AUTOPLAY);
        } else if (mCategory.showSites(SiteSettingsCategory.Type.BACKGROUND_SYNC)) {
            setting = website.site().getContentSettingPermission(
                    ContentSettingException.Type.BACKGROUND_SYNC);
        } else if (mCategory.showSites(SiteSettingsCategory.Type.CAMERA)) {
            setting = website.site().getPermission(PermissionInfo.Type.CAMERA);
        } else if (mCategory.showSites(SiteSettingsCategory.Type.CLIPBOARD)) {
            setting = website.site().getPermission(PermissionInfo.Type.CLIPBOARD);
        } else if (mCategory.showSites(SiteSettingsCategory.Type.COOKIES)) {
            setting =
                    website.site().getContentSettingPermission(ContentSettingException.Type.COOKIE);
        } else if (mCategory.showSites(SiteSettingsCategory.Type.DEVICE_LOCATION)) {
            setting = website.site().getPermission(PermissionInfo.Type.GEOLOCATION);
        } else if (mCategory.showSites(SiteSettingsCategory.Type.JAVASCRIPT)) {
            setting = website.site().getContentSettingPermission(
                    ContentSettingException.Type.JAVASCRIPT);
        } else if (mCategory.showSites(SiteSettingsCategory.Type.MICROPHONE)) {
            setting = website.site().getPermission(PermissionInfo.Type.MICROPHONE);
        } else if (mCategory.showSites(SiteSettingsCategory.Type.NOTIFICATIONS)) {
            setting = website.site().getPermission(PermissionInfo.Type.NOTIFICATION);
        } else if (mCategory.showSites(SiteSettingsCategory.Type.POPUPS)) {
            setting =
                    website.site().getContentSettingPermission(ContentSettingException.Type.POPUP);
        } else if (mCategory.showSites(SiteSettingsCategory.Type.PROTECTED_MEDIA)) {
            setting = website.site().getPermission(PermissionInfo.Type.PROTECTED_MEDIA_IDENTIFIER);
        } else if (mCategory.showSites(SiteSettingsCategory.Type.SENSORS)) {
            setting = website.site().getPermission(PermissionInfo.Type.SENSORS);
        } else if (mCategory.showSites(SiteSettingsCategory.Type.SOUND)) {
            setting =
                    website.site().getContentSettingPermission(ContentSettingException.Type.SOUND);
        } else {
            return false;
        }

        return setting == ContentSetting.BLOCK;
    }

    /**
     * Update the Category Header for the Allowed list.
     * @param numAllowed The number of sites that are on the Allowed list
     * @param toggleValue The value the global toggle will have once precessing ends.
     */
    private void updateAllowedHeader(int numAllowed, boolean toggleValue) {
        ExpandablePreferenceGroup allowedGroup =
                (ExpandablePreferenceGroup) getPreferenceScreen().findPreference(ALLOWED_GROUP);
        if (numAllowed == 0) {
            if (allowedGroup != null) getPreferenceScreen().removePreference(allowedGroup);
            return;
        }
        if (!mGroupByAllowBlock) return;

        // When the toggle is set to Blocked, the Allowed list header should read 'Exceptions', not
        // 'Allowed' (because it shows exceptions from the rule).
        int resourceId = toggleValue
                ? R.string.website_settings_allowed_group_heading
                : R.string.website_settings_exceptions_group_heading;
        allowedGroup.setTitle(getHeaderTitle(resourceId, numAllowed));
        allowedGroup.setExpanded(mAllowListExpanded);
    }

    private void updateBlockedHeader(int numBlocked) {
        ExpandablePreferenceGroup blockedGroup =
                (ExpandablePreferenceGroup) getPreferenceScreen().findPreference(BLOCKED_GROUP);
        if (numBlocked == 0) {
            if (blockedGroup != null) getPreferenceScreen().removePreference(blockedGroup);
            return;
        }
        if (!mGroupByAllowBlock) return;

        // Set the title and arrow icons for the header.
        int resourceId = mCategory.showSites(SiteSettingsCategory.Type.SOUND)
                ? R.string.website_settings_blocked_group_heading_sound
                : R.string.website_settings_blocked_group_heading;
        blockedGroup.setTitle(getHeaderTitle(resourceId, numBlocked));
        blockedGroup.setExpanded(mBlockListExpanded);
    }

    private CharSequence getHeaderTitle(int resourceId, int count) {
        SpannableStringBuilder spannable =
                new SpannableStringBuilder(getResources().getString(resourceId));
        String prefCount = String.format(Locale.getDefault(), " - %d", count);
        spannable.append(prefCount);

        // Color the first part of the title blue.
        ForegroundColorSpan blueSpan = new ForegroundColorSpan(
                ApiCompatibilityUtils.getColor(getResources(), R.color.default_text_color_link));
        spannable.setSpan(blueSpan, 0, spannable.length() - prefCount.length(),
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        // Gray out the total count of items.
        int gray = ApiCompatibilityUtils.getColor(getResources(), R.color.black_alpha_54);
        spannable.setSpan(new ForegroundColorSpan(gray), spannable.length() - prefCount.length(),
                spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return spannable;
    }

    @Override
    public View onCreateView(
            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Read which category we should be showing.
        if (getArguments() != null) {
            int contentSettingsType = SiteSettingsCategory.contentSettingsType(
                    getArguments().getString(EXTRA_CATEGORY, ""));
            if (contentSettingsType != -1) {
                mCategory = SiteSettingsCategory.createFromContentSettingsType(contentSettingsType);
            }
        }
        if (mCategory == null) {
            mCategory = SiteSettingsCategory.createFromType(SiteSettingsCategory.Type.ALL_SITES);
        }
        if (!mCategory.showSites(SiteSettingsCategory.Type.USE_STORAGE)) {
            return super.onCreateView(inflater, container, savedInstanceState);
        } else {
            return inflater.inflate(R.layout.storage_preferences, container, false);
        }
    }

    /**
     * Returns the category being displayed. For testing.
     */
    public SiteSettingsCategory getCategoryForTest() {
        return mCategory;
    }

    /**
     * This clears all the storage for websites that are displayed to the user. This happens
     * asynchronously, and then we call {@link #getInfoForOrigins()} when we're done.
     */
    public void clearStorage() {
        if (mWebsites == null) return;
        RecordUserAction.record("MobileSettingsStorageClearAll");

        // The goal is to refresh the info for origins again after we've cleared all of them, so we
        // wait until the last website is cleared to refresh the origin list.
        final int[] numLeft = new int[1];
        numLeft[0] = mWebsites.size();
        for (int i = 0; i < mWebsites.size(); i++) {
            WebsitePreference preference = mWebsites.get(i);
            preference.site().clearAllStoredData(new StoredDataClearedCallback() {
                @Override
                public void onStoredDataCleared() {
                    if (--numLeft[0] <= 0) getInfoForOrigins();
                }
            });
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        PreferenceUtils.addPreferencesFromResource(this, R.xml.website_preferences);
        ListView listView = (ListView) getView().findViewById(android.R.id.list);
        mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
        listView.setEmptyView(mEmptyView);
        listView.setDivider(null);

        mClearButton = (Button) getView().findViewById(R.id.clear_button);
        if (mClearButton != null) mClearButton.setOnClickListener(this);

        String title = getArguments().getString(EXTRA_TITLE);
        if (title != null) getActivity().setTitle(title);

        configureGlobalToggles();

        setHasOptionsMenu(true);

        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        menu.clear();
        inflater.inflate(R.menu.website_preferences_menu, menu);

        MenuItem searchItem = menu.findItem(R.id.search);
        mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
        mSearchView.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);
        SearchView.OnQueryTextListener queryTextListener =
                new SearchView.OnQueryTextListener() {
                    @Override
                    public boolean onQueryTextSubmit(String query) {
                        return true;
                    }

                    @Override
                    public boolean onQueryTextChange(String query) {
                        if (query.equals(mSearch)) return true;

                        mSearch = query;
                        getInfoForOrigins();
                        return true;
                    }
                };
        mSearchView.setOnQueryTextListener(queryTextListener);

        if (mCategory.showSites(SiteSettingsCategory.Type.PROTECTED_MEDIA)) {
            // Add a menu item to reset protected media identifier device credentials.
            MenuItem resetMenu =
                    menu.add(Menu.NONE, Menu.NONE, Menu.NONE, R.string.reset_device_credentials);
            resetMenu.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem menuItem) {
                    ProtectedContentResetCredentialConfirmDialogFragment
                            .newInstance(SingleCategoryPreferences.this)
                            .show(getFragmentManager(), null);
                    return true;
                }
            });
        }

        MenuItem help = menu.add(
                Menu.NONE, R.id.menu_id_targeted_help, Menu.NONE, R.string.menu_help);
        help.setIcon(R.drawable.ic_help_and_feedback);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.menu_id_targeted_help) {
            int helpContextResId = R.string.help_context_settings;
            if (mCategory.showSites(SiteSettingsCategory.Type.PROTECTED_MEDIA)) {
                helpContextResId = R.string.help_context_protected_content;
            }
            HelpAndFeedback.getInstance(getActivity()).show(
                    getActivity(), getString(helpContextResId), Profile.getLastUsedProfile(), null);
            return true;
        }
        return false;
    }

    @Override
    public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
        // Do not show the toast if the System Location setting is disabled.
        if (getPreferenceScreen().findPreference(READ_WRITE_TOGGLE_KEY) != null
                && mCategory.isManaged()) {
            showManagedToast();
            return false;
        }

        if (!mSearch.isEmpty()) {
            // Clear out any lingering searches, so that the full list is shown
            // when coming back to this page.
            mSearch = "";
            mSearchView.setQuery("", false);
        }

        if (preference instanceof WebsitePreference) {
            WebsitePreference website = (WebsitePreference) preference;
            website.setFragment(SingleWebsitePreferences.class.getName());
            // EXTRA_SITE re-uses already-fetched permissions, which we can only use if the Website
            // was populated with data for all permission types.
            if (mCategory.showSites(SiteSettingsCategory.Type.ALL_SITES)) {
                website.putSiteIntoExtras(SingleWebsitePreferences.EXTRA_SITE);
            } else {
                website.putSiteAddressIntoExtras(SingleWebsitePreferences.EXTRA_SITE_ADDRESS);
            }
        }

        return super.onPreferenceTreeClick(screen, preference);
    }

    /** OnClickListener for the clear button. We show an alert dialog to confirm the action */
    @Override
    public void onClick(View v) {
        if (getActivity() == null || v != mClearButton) return;

        long totalUsage = 0;
        if (mWebsites != null) {
            for (WebsitePreference preference : mWebsites) {
                totalUsage += preference.site().getTotalUsage();
            }
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setPositiveButton(R.string.storage_clear_dialog_clear_storage_option,
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        clearStorage();
                    }
                });
        builder.setNegativeButton(R.string.cancel, null);
        builder.setTitle(R.string.storage_clear_site_storage_title);
        Resources res = getResources();
        String dialogFormattedText = res.getString(R.string.storage_clear_dialog_text,
                Formatter.formatShortFileSize(getActivity(), totalUsage));
        builder.setMessage(dialogFormattedText);
        builder.create().show();
    }

    // OnPreferenceChangeListener:
    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        if (READ_WRITE_TOGGLE_KEY.equals(preference.getKey())) {
            assert !mCategory.isManaged();

            if (mCategory.showSites(SiteSettingsCategory.Type.ADS)) {
                PrefServiceBridge.getInstance().setAllowAdsEnabled((boolean) newValue);
            } else if (mCategory.showSites(SiteSettingsCategory.Type.AUTOPLAY)) {
                PrefServiceBridge.getInstance().setAutoplayEnabled((boolean) newValue);
            } else if (mCategory.showSites(SiteSettingsCategory.Type.BACKGROUND_SYNC)) {
                PrefServiceBridge.getInstance().setBackgroundSyncEnabled((boolean) newValue);
            } else if (mCategory.showSites(SiteSettingsCategory.Type.CAMERA)) {
                PrefServiceBridge.getInstance().setCameraEnabled((boolean) newValue);
            } else if (mCategory.showSites(SiteSettingsCategory.Type.CLIPBOARD)) {
                PrefServiceBridge.getInstance().setClipboardEnabled((boolean) newValue);
            } else if (mCategory.showSites(SiteSettingsCategory.Type.COOKIES)) {
                PrefServiceBridge.getInstance().setAllowCookiesEnabled((boolean) newValue);
                updateThirdPartyCookiesCheckBox();
            } else if (mCategory.showSites(SiteSettingsCategory.Type.DEVICE_LOCATION)) {
                PrefServiceBridge.getInstance().setAllowLocationEnabled((boolean) newValue);
            } else if (mCategory.showSites(SiteSettingsCategory.Type.JAVASCRIPT)) {
                PrefServiceBridge.getInstance().setJavaScriptEnabled((boolean) newValue);
            } else if (mCategory.showSites(SiteSettingsCategory.Type.MICROPHONE)) {
                PrefServiceBridge.getInstance().setMicEnabled((boolean) newValue);
            } else if (mCategory.showSites(SiteSettingsCategory.Type.NOTIFICATIONS)) {
                PrefServiceBridge.getInstance().setNotificationsEnabled((boolean) newValue);
                updateNotificationsVibrateCheckBox();
            } else if (mCategory.showSites(SiteSettingsCategory.Type.POPUPS)) {
                PrefServiceBridge.getInstance().setAllowPopupsEnabled((boolean) newValue);
            } else if (mCategory.showSites(SiteSettingsCategory.Type.PROTECTED_MEDIA)) {
                PrefServiceBridge.getInstance().setProtectedMediaIdentifierEnabled(
                        (boolean) newValue);
            } else if (mCategory.showSites(SiteSettingsCategory.Type.SENSORS)) {
                PrefServiceBridge.getInstance().setSensorsEnabled((boolean) newValue);
            } else if (mCategory.showSites(SiteSettingsCategory.Type.SOUND)) {
                PrefServiceBridge.getInstance().setSoundEnabled((boolean) newValue);
            } else if (mCategory.showSites(SiteSettingsCategory.Type.USB)) {
                PrefServiceBridge.getInstance().setUsbEnabled((boolean) newValue);
            }

            // Categories that support adding exceptions also manage the 'Add site' preference.
            // This should only be used for settings that have host-pattern based exceptions.
            if (mCategory.showSites(SiteSettingsCategory.Type.AUTOPLAY)
                    || mCategory.showSites(SiteSettingsCategory.Type.BACKGROUND_SYNC)
                    || mCategory.showSites(SiteSettingsCategory.Type.JAVASCRIPT)
                    || mCategory.showSites(SiteSettingsCategory.Type.SOUND)) {
                if ((boolean) newValue) {
                    Preference addException = getPreferenceScreen().findPreference(
                            ADD_EXCEPTION_KEY);
                    if (addException != null) {  // Can be null in testing.
                        getPreferenceScreen().removePreference(addException);
                    }
                } else {
                    getPreferenceScreen().addPreference(
                            new AddExceptionPreference(getActivity(), ADD_EXCEPTION_KEY,
                                    getAddExceptionDialogMessage(), this));
                }
            }

            ChromeSwitchPreference globalToggle = (ChromeSwitchPreference)
                    getPreferenceScreen().findPreference(READ_WRITE_TOGGLE_KEY);
            updateAllowedHeader(mAllowedSiteCount, !globalToggle.isChecked());

            getInfoForOrigins();
        } else if (THIRD_PARTY_COOKIES_TOGGLE_KEY.equals(preference.getKey())) {
            PrefServiceBridge.getInstance().setBlockThirdPartyCookiesEnabled(!((boolean) newValue));
        } else if (NOTIFICATIONS_VIBRATE_TOGGLE_KEY.equals(preference.getKey())) {
            PrefServiceBridge.getInstance().setNotificationsVibrateEnabled((boolean) newValue);
        }
        return true;
    }

    private String getAddExceptionDialogMessage() {
        int resource = 0;
        if (mCategory.showSites(SiteSettingsCategory.Type.AUTOPLAY)) {
            resource = R.string.website_settings_add_site_description_autoplay;
        } else if (mCategory.showSites(SiteSettingsCategory.Type.BACKGROUND_SYNC)) {
            resource = R.string.website_settings_add_site_description_background_sync;
        } else if (mCategory.showSites(SiteSettingsCategory.Type.JAVASCRIPT)) {
            resource = R.string.website_settings_add_site_description_javascript;
        } else if (mCategory.showSites(SiteSettingsCategory.Type.SOUND)) {
            resource = PrefServiceBridge.getInstance().isSoundEnabled()
                    ? R.string.website_settings_add_site_description_sound_block
                    : R.string.website_settings_add_site_description_sound_allow;
        }
        assert resource > 0;
        return getResources().getString(resource);
    }

    // OnPreferenceClickListener:
    @Override
    public boolean onPreferenceClick(Preference preference) {
        if (ALLOWED_GROUP.equals(preference.getKey()))  {
            mAllowListExpanded = !mAllowListExpanded;
        } else {
            mBlockListExpanded = !mBlockListExpanded;
        }
        getInfoForOrigins();
        return true;
    }

    @Override
    public void onResume() {
        super.onResume();

        getInfoForOrigins();
    }

    // AddExceptionPreference.SiteAddedCallback:
    @Override
    public void onAddSite(String hostname) {
        // The Sound content setting has exception lists for both BLOCK and ALLOW (others just
        // have exceptions to ALLOW).
        int setting = (mCategory.showSites(SiteSettingsCategory.Type.SOUND)
                              && PrefServiceBridge.getInstance().isSoundEnabled())
                ? ContentSetting.BLOCK.toInt()
                : ContentSetting.ALLOW.toInt();
        PrefServiceBridge.getInstance().nativeSetContentSettingForPattern(
                mCategory.getContentSettingsType(), hostname, setting);

        Toast.makeText(getActivity(),
                String.format(getActivity().getString(
                        R.string.website_settings_add_site_toast),
                        hostname),
                Toast.LENGTH_SHORT).show();

        getInfoForOrigins();

        if (mCategory.showSites(SiteSettingsCategory.Type.SOUND)) {
            if (setting == ContentSetting.BLOCK.toInt()) {
                RecordUserAction.record("SoundContentSetting.MuteBy.PatternException");
            } else {
                RecordUserAction.record("SoundContentSetting.UnmuteBy.PatternException");
            }
        }
    }

    /**
     * Reset the preference screen an initialize it again.
     */
    private void resetList() {
        // This will remove the combo box at the top and all the sites listed below it.
        getPreferenceScreen().removeAll();
        // And this will add the filter preference back (combo box).
        PreferenceUtils.addPreferencesFromResource(this, R.xml.website_preferences);

        configureGlobalToggles();

        if ((mCategory.showSites(SiteSettingsCategory.Type.AUTOPLAY)
                    && !PrefServiceBridge.getInstance().isAutoplayEnabled())
                || (mCategory.showSites(SiteSettingsCategory.Type.JAVASCRIPT)
                           && !PrefServiceBridge.getInstance().javaScriptEnabled())
                || mCategory.showSites(SiteSettingsCategory.Type.SOUND)
                || (mCategory.showSites(SiteSettingsCategory.Type.BACKGROUND_SYNC)
                           && !PrefServiceBridge.getInstance().isBackgroundSyncAllowed())) {
            getPreferenceScreen().addPreference(
                    new AddExceptionPreference(getActivity(), ADD_EXCEPTION_KEY,
                            getAddExceptionDialogMessage(), this));
        }
    }

    private boolean addWebsites(Collection<Website> sites) {
        List<WebsitePreference> websites = new ArrayList<>();

        // Find origins matching the current search.
        for (Website site : sites) {
            if (mSearch.isEmpty() || site.getTitle().contains(mSearch)) {
                websites.add(new WebsitePreference(getActivity(), site, mCategory));
            }
        }

        mAllowedSiteCount = 0;

        if (websites.size() == 0) {
            updateBlockedHeader(0);
            updateAllowedHeader(0, true);
            return false;
        }

        Collections.sort(websites);
        int blocked = 0;

        if (!mGroupByAllowBlock) {
            // We're not grouping sites into Allowed/Blocked lists, so show all in order
            // (will be alphabetical).
            for (WebsitePreference website : websites) {
                getPreferenceScreen().addPreference(website);
            }
        } else {
            // Group sites into Allowed/Blocked lists.
            PreferenceGroup allowedGroup =
                    (PreferenceGroup) getPreferenceScreen().findPreference(ALLOWED_GROUP);
            PreferenceGroup blockedGroup =
                    (PreferenceGroup) getPreferenceScreen().findPreference(BLOCKED_GROUP);

            for (WebsitePreference website : websites) {
                if (isOnBlockList(website)) {
                    blockedGroup.addPreference(website);
                    blocked += 1;
                } else {
                    allowedGroup.addPreference(website);
                    mAllowedSiteCount += 1;
                }
            }

            // For the ads permission, the Allowed list should appear first. Default
            // collapsed settings should not change.
            if (mCategory.showSites(SiteSettingsCategory.Type.ADS)) {
                blockedGroup.setOrder(allowedGroup.getOrder() + 1);
            }

            // The default, when the two lists are shown for the first time, is for the
            // Blocked list to be collapsed and Allowed expanded -- because the data in
            // the Allowed list is normally more useful than the data in the Blocked
            // list. A collapsed initial Blocked list works well *except* when there's
            // nothing in the Allowed list because then there's only Blocked items to
            // show and it doesn't make sense for those items to be hidden. So, in that
            // case (and only when the list is shown for the first time) do we ignore
            // the collapsed directive. The user can still collapse and expand the
            // Blocked list at will.
            if (mIsInitialRun) {
                if (allowedGroup.getPreferenceCount() == 0) mBlockListExpanded = true;
                mIsInitialRun = false;
            }

            if (!mBlockListExpanded) {
                blockedGroup.removeAll();
            }

            if (!mAllowListExpanded) {
                allowedGroup.removeAll();
            }
        }

        mWebsites = websites;
        updateBlockedHeader(blocked);
        ChromeSwitchPreference globalToggle =
                (ChromeSwitchPreference) getPreferenceScreen().findPreference(
                        READ_WRITE_TOGGLE_KEY);
        updateAllowedHeader(
                mAllowedSiteCount, (globalToggle != null ? globalToggle.isChecked() : true));

        return websites.size() != 0;
    }

    private boolean addChosenObjects(Collection<Website> sites) {
        Map<String, Pair<ArrayList<ChosenObjectInfo>, ArrayList<Website>>> objects =
                new HashMap<>();

        // Find chosen objects matching the current search and collect the list of sites
        // that have permission to access each.
        for (Website site : sites) {
            for (ChosenObjectInfo info : site.getChosenObjectInfo()) {
                if (mSearch.isEmpty() || info.getName().toLowerCase().contains(mSearch)) {
                    Pair<ArrayList<ChosenObjectInfo>, ArrayList<Website>> entry =
                            objects.get(info.getObject());
                    if (entry == null) {
                        entry = Pair.create(
                                new ArrayList<ChosenObjectInfo>(), new ArrayList<Website>());
                        objects.put(info.getObject(), entry);
                    }
                    entry.first.add(info);
                    entry.second.add(site);
                }
            }
        }

        updateBlockedHeader(0);
        updateAllowedHeader(0, true);

        for (Pair<ArrayList<ChosenObjectInfo>, ArrayList<Website>> entry : objects.values()) {
            Preference preference = new Preference(getActivity());
            Bundle extras = preference.getExtras();
            extras.putInt(
                    ChosenObjectPreferences.EXTRA_CATEGORY, mCategory.getContentSettingsType());
            extras.putString(EXTRA_TITLE, getActivity().getTitle().toString());
            extras.putSerializable(ChosenObjectPreferences.EXTRA_OBJECT_INFOS, entry.first);
            extras.putSerializable(ChosenObjectPreferences.EXTRA_SITES, entry.second);
            preference.setIcon(
                    ContentSettingsResources.getIcon(mCategory.getContentSettingsType()));
            preference.setTitle(entry.first.get(0).getName());
            preference.setFragment(ChosenObjectPreferences.class.getCanonicalName());
            getPreferenceScreen().addPreference(preference);
        }

        return objects.size() != 0;
    }

    private void configureGlobalToggles() {
        // Only some have a global toggle at the top.
        ChromeSwitchPreference globalToggle = (ChromeSwitchPreference)
                getPreferenceScreen().findPreference(READ_WRITE_TOGGLE_KEY);

        // Configure/hide the third-party cookie toggle, as needed.
        Preference thirdPartyCookies = getPreferenceScreen().findPreference(
                THIRD_PARTY_COOKIES_TOGGLE_KEY);
        if (mCategory.showSites(SiteSettingsCategory.Type.COOKIES)) {
            thirdPartyCookies.setOnPreferenceChangeListener(this);
            updateThirdPartyCookiesCheckBox();
        } else {
            getPreferenceScreen().removePreference(thirdPartyCookies);
        }

        // Configure/hide the notifications vibrate toggle, as needed.
        Preference notificationsVibrate =
                getPreferenceScreen().findPreference(NOTIFICATIONS_VIBRATE_TOGGLE_KEY);
        if (mCategory.showSites(SiteSettingsCategory.Type.NOTIFICATIONS)
                && Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            notificationsVibrate.setOnPreferenceChangeListener(this);
            updateNotificationsVibrateCheckBox();
        } else {
            getPreferenceScreen().removePreference(notificationsVibrate);
        }

        // Show/hide the link that explains protected media settings, as needed.
        if (!mCategory.showSites(SiteSettingsCategory.Type.PROTECTED_MEDIA)) {
            getPreferenceScreen().removePreference(
                    getPreferenceScreen().findPreference(EXPLAIN_PROTECTED_MEDIA_KEY));
        }

        if (mCategory.showSites(SiteSettingsCategory.Type.ALL_SITES)
                || mCategory.showSites(SiteSettingsCategory.Type.USE_STORAGE)) {
            getPreferenceScreen().removePreference(globalToggle);
            getPreferenceScreen().removePreference(
                    getPreferenceScreen().findPreference(ALLOWED_GROUP));
            getPreferenceScreen().removePreference(
                    getPreferenceScreen().findPreference(BLOCKED_GROUP));
            return;
        }
        // When this menu opens, make sure the Blocked list is collapsed.
        if (!mGroupByAllowBlock) {
            mBlockListExpanded = false;
            mAllowListExpanded = true;
        }
        mGroupByAllowBlock = true;
        PreferenceGroup allowedGroup =
                (PreferenceGroup) getPreferenceScreen().findPreference(ALLOWED_GROUP);
        PreferenceGroup blockedGroup =
                (PreferenceGroup) getPreferenceScreen().findPreference(BLOCKED_GROUP);

        if (mCategory.showPermissionBlockedMessage(getActivity())) {
            getPreferenceScreen().removePreference(globalToggle);
            getPreferenceScreen().removePreference(allowedGroup);
            getPreferenceScreen().removePreference(blockedGroup);

            // Show the link to system settings since permission is disabled.
            ChromeBasePreference osWarning = new ChromeBasePreference(getActivity(), null);
            ChromeBasePreference osWarningExtra = new ChromeBasePreference(getActivity(), null);
            mCategory.configurePermissionIsOffPreferences(
                    osWarning, osWarningExtra, getActivity(), true);
            if (osWarning.getTitle() != null) {
                getPreferenceScreen().addPreference(osWarning);
            }
            if (osWarningExtra.getTitle() != null) {
                getPreferenceScreen().addPreference(osWarningExtra);
            }
            return;
        }

        allowedGroup.setOnPreferenceClickListener(this);
        blockedGroup.setOnPreferenceClickListener(this);

        // Determine what toggle to use and what it should display.
        int contentType = mCategory.getContentSettingsType();
        globalToggle.setOnPreferenceChangeListener(this);
        globalToggle.setTitle(ContentSettingsResources.getTitle(contentType));
        if (mCategory.showSites(SiteSettingsCategory.Type.DEVICE_LOCATION)
                && PrefServiceBridge.getInstance().isLocationAllowedByPolicy()) {
            globalToggle.setSummaryOn(ContentSettingsResources.getGeolocationAllowedSummary());
        } else {
            globalToggle.setSummaryOn(ContentSettingsResources.getEnabledSummary(contentType));
        }
        globalToggle.setSummaryOff(ContentSettingsResources.getDisabledSummary(contentType));
        globalToggle.setManagedPreferenceDelegate(new ManagedPreferenceDelegate() {
            @Override
            public boolean isPreferenceControlledByPolicy(Preference preference) {
                // TODO(bauerb): Align the ManagedPreferenceDelegate and
                // SiteSettingsCategory interfaces better to avoid this indirection.
                return mCategory.isManaged() && !mCategory.isManagedByCustodian();
            }

            @Override
            public boolean isPreferenceControlledByCustodian(Preference preference) {
                return mCategory.isManagedByCustodian();
            }
        });
        if (mCategory.showSites(SiteSettingsCategory.Type.ADS))
            globalToggle.setChecked(PrefServiceBridge.getInstance().adsEnabled());
        else if (mCategory.showSites(SiteSettingsCategory.Type.AUTOPLAY))
            globalToggle.setChecked(PrefServiceBridge.getInstance().isAutoplayEnabled());
        else if (mCategory.showSites(SiteSettingsCategory.Type.BACKGROUND_SYNC))
            globalToggle.setChecked(PrefServiceBridge.getInstance().isBackgroundSyncAllowed());
        else if (mCategory.showSites(SiteSettingsCategory.Type.CAMERA))
            globalToggle.setChecked(PrefServiceBridge.getInstance().isCameraEnabled());
        else if (mCategory.showSites(SiteSettingsCategory.Type.CLIPBOARD))
            globalToggle.setChecked(PrefServiceBridge.getInstance().isClipboardEnabled());
        else if (mCategory.showSites(SiteSettingsCategory.Type.COOKIES))
            globalToggle.setChecked(PrefServiceBridge.getInstance().isAcceptCookiesEnabled());
        else if (mCategory.showSites(SiteSettingsCategory.Type.DEVICE_LOCATION))
            globalToggle.setChecked(
                    LocationSettings.getInstance().isChromeLocationSettingEnabled());
        else if (mCategory.showSites(SiteSettingsCategory.Type.JAVASCRIPT))
            globalToggle.setChecked(PrefServiceBridge.getInstance().javaScriptEnabled());
        else if (mCategory.showSites(SiteSettingsCategory.Type.MICROPHONE))
            globalToggle.setChecked(PrefServiceBridge.getInstance().isMicEnabled());
        else if (mCategory.showSites(SiteSettingsCategory.Type.NOTIFICATIONS))
            globalToggle.setChecked(PrefServiceBridge.getInstance().isNotificationsEnabled());
        else if (mCategory.showSites(SiteSettingsCategory.Type.POPUPS))
            globalToggle.setChecked(PrefServiceBridge.getInstance().popupsEnabled());
        else if (mCategory.showSites(SiteSettingsCategory.Type.PROTECTED_MEDIA))
            globalToggle.setChecked(
                    PrefServiceBridge.getInstance().isProtectedMediaIdentifierEnabled());
        else if (mCategory.showSites(SiteSettingsCategory.Type.SENSORS))
            globalToggle.setChecked(PrefServiceBridge.getInstance().areSensorsEnabled());
        else if (mCategory.showSites(SiteSettingsCategory.Type.SOUND))
            globalToggle.setChecked(PrefServiceBridge.getInstance().isSoundEnabled());
        else if (mCategory.showSites(SiteSettingsCategory.Type.USB))
            globalToggle.setChecked(PrefServiceBridge.getInstance().isUsbEnabled());
    }

    private void updateThirdPartyCookiesCheckBox() {
        ChromeBaseCheckBoxPreference thirdPartyCookiesPref = (ChromeBaseCheckBoxPreference)
                getPreferenceScreen().findPreference(THIRD_PARTY_COOKIES_TOGGLE_KEY);
        thirdPartyCookiesPref.setChecked(
                !PrefServiceBridge.getInstance().isBlockThirdPartyCookiesEnabled());
        thirdPartyCookiesPref.setEnabled(PrefServiceBridge.getInstance().isAcceptCookiesEnabled());
        thirdPartyCookiesPref.setManagedPreferenceDelegate(
                preference -> PrefServiceBridge.getInstance().isBlockThirdPartyCookiesManaged());
    }

    private void updateNotificationsVibrateCheckBox() {
        ChromeBaseCheckBoxPreference preference =
                (ChromeBaseCheckBoxPreference) getPreferenceScreen().findPreference(
                        NOTIFICATIONS_VIBRATE_TOGGLE_KEY);
        if (preference != null) {
            preference.setEnabled(PrefServiceBridge.getInstance().isNotificationsEnabled());
        }
    }

    private void showManagedToast() {
        if (mCategory.isManagedByCustodian()) {
            ManagedPreferencesUtils.showManagedByParentToast(getActivity());
        } else {
            ManagedPreferencesUtils.showManagedByAdministratorToast(getActivity());
        }
    }

    // ProtectedContentResetCredentialConfirmDialogFragment.Listener:
    @Override
    public void resetDeviceCredential() {
        MediaDrmCredentialManager.resetCredentials(new MediaDrmCredentialManagerCallback() {
            @Override
            public void onCredentialResetFinished(boolean succeeded) {
                if (succeeded) return;
                Toast.makeText(getActivity(), getString(R.string.protected_content_reset_failed),
                             Toast.LENGTH_SHORT)
                        .show();
            }
        });
    }
}
