Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3597)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ConfirmImportantSitesDialogFragment.java

Issue 1465363002: [Storage] Android - ManageSpace UI, Important Origins, and CBD Dialog (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: successful async startup. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ConfirmImportantSitesDialogFragment.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ConfirmImportantSitesDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ConfirmImportantSitesDialogFragment.java
new file mode 100644
index 0000000000000000000000000000000000000000..68ce11ff394bf368d74443a1b5c6ef77292f4374
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ConfirmImportantSitesDialogFragment.java
@@ -0,0 +1,266 @@
+// Copyright 2016 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.privacy;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.support.v7.app.AlertDialog;
+import android.util.LruCache;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.CheckedTextView;
+import android.widget.ListView;
+
+import org.chromium.base.ApiCompatibilityUtils;
+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.PrefServiceBridge;
+import org.chromium.chrome.browser.profiles.Profile;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Modal dialog that shows a list of important domains to the user which they can uncheck. Used to
+ * allow the user to exclude domains from being cleared by the clear browsing data function.
+ * We use proper bundle construction (through the {@link #newInstance(String[])} method) and
+ * onActivityResult return conventions.
+ */
+public class ConfirmImportantSitesDialogFragment extends DialogFragment {
+ private class ClearBrowsingDataAdapter extends ArrayAdapter<String> {
+ String[] mDomains;
+ private final Drawable mDefaultFavicon;
+ private final int mFaviconSize;
+
+ private ClearBrowsingDataAdapter(String[] domains) {
+ super(getActivity(), R.layout.select_dialog_multichoice_material, domains);
+ mDomains = domains;
+ Resources resources = getActivity().getResources();
+ mFaviconSize = resources.getDimensionPixelSize(R.dimen.default_favicon_size);
+ mDefaultFavicon =
+ ApiCompatibilityUtils.getDrawable(resources, R.drawable.default_favicon);
+ }
+
+ @Override
+ public int getCount() {
+ return mDomains.length;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View childView = convertView;
+ if (childView == null) {
+ LayoutInflater inflater = LayoutInflater.from(getActivity());
+ childView = inflater.inflate(
+ R.layout.select_dialog_multichoice_material, parent, false);
+
+ ViewAndFaviconHolder viewHolder = new ViewAndFaviconHolder();
+ viewHolder.textView = (CheckedTextView) childView;
+ childView.setTag(viewHolder);
+ }
+ ViewAndFaviconHolder viewHolder = (ViewAndFaviconHolder) childView.getTag();
+ configureChildView(position, viewHolder);
+ return childView;
+ }
+
+ public void configureChildView(int position, ViewAndFaviconHolder viewHolder) {
+ String domain = mDomains[position];
+ viewHolder.textView.setChecked(!mDeselectedDomains.contains(domain));
+ viewHolder.textView.setText(domain);
+ loadLocalFavicon(viewHolder, transformDomainToOrigin(domain));
+ }
+
+ public void onClick(int position, View view) {
+ String domain = mDomains[position];
+ ViewAndFaviconHolder viewHolder = (ViewAndFaviconHolder) view.getTag();
+ if (mDeselectedDomains.contains(domain)) {
+ mDeselectedDomains.remove(domain);
+ viewHolder.textView.setChecked(true);
+ } else {
+ mDeselectedDomains.add(domain);
+ viewHolder.textView.setChecked(false);
+ }
+ }
+
+ private void loadLocalFavicon(final ViewAndFaviconHolder viewHolder, final String url) {
+ Drawable image;
+ if (url == null) {
+ // URL is null for print jobs, for example.
+ image = mDefaultFavicon;
+ } else {
+ image = mFaviconCache.getLocalFaviconImage(url);
+ if (image == null) {
+ FaviconImageCallback imageCallback = new FaviconImageCallback() {
+ @Override
+ public void onFaviconAvailable(Bitmap bitmap, String iconUrl) {
+ if (this != viewHolder.imageCallback) return;
+ Drawable image = getFaviconDrawable(bitmap);
+ image = (image == null) ? mDefaultFavicon : image;
+ mFaviconCache.putLocalFaviconImage(url, image);
+ viewHolder.textView.setCheckMarkDrawable(image);
+ }
+ };
+ viewHolder.imageCallback = imageCallback;
+ mFaviconHelper.getLocalFaviconImageForURL(
+ mProfile, url, mFaviconSize, imageCallback);
+ image = mDefaultFavicon;
+ }
+ }
+ viewHolder.textView.setCheckMarkDrawable(image);
+ }
+
+ private Drawable getFaviconDrawable(Bitmap image) {
+ if (image == null) return null;
+ return new BitmapDrawable(getActivity().getResources(),
+ Bitmap.createScaledBitmap(image, mFaviconSize, mFaviconSize, true));
+ }
+ }
+
+ private static class FaviconCache {
+ private final LruCache<String, Drawable> mMemoryCache;
+
+ public FaviconCache(int size) {
+ mMemoryCache = new LruCache<String, Drawable>(size);
+ }
+
+ public Drawable getLocalFaviconImage(String url) {
+ return mMemoryCache.get(url);
+ }
+
+ public void putLocalFaviconImage(String url, Drawable image) {
+ mMemoryCache.put(url, image);
+ }
+ }
+
+ /**
+ * ViewHolder class optimizes looking up table row fields. findViewById is only called once
+ * per row view initialization, and the references are cached here. Also stores a reference to
+ * the favicon image callback; so that we can make sure we load the correct favicon.
+ */
+ private static class ViewAndFaviconHolder {
+ public CheckedTextView textView;
+ public FaviconImageCallback imageCallback;
+ }
+
+ /**
+ * Constructs a new instance of the important sites dialog fragment.
+ * @param importantDomains The list of important domains to display.
+ * @return An instance of ConfirmImportantSitesDialogFragment with the bundle arguments set.
+ */
+ public static ConfirmImportantSitesDialogFragment newInstance(String[] importantDomains) {
+ ConfirmImportantSitesDialogFragment dialogFragment =
+ new ConfirmImportantSitesDialogFragment();
+ Bundle bundle = new Bundle();
+ bundle.putStringArray(IMPORTANT_DOMAINS_TAG, importantDomains);
+ dialogFragment.setArguments(bundle);
+ return dialogFragment;
+ }
+
+ /** The tag used when showing the clear browsing fragment. */
+ public static final String FRAGMENT_TAG = "ConfirmImportantSitesDialogFragment";
+
+ /**
+ * The tag used to return the string array of deselected domains. These are meant to NOT be
+ * cleared.
+ */
+ public static final String DESELECTED_DOMAINS_TAG = "DeselectedDomains";
+
+ /** The tag used to store the important domains in the bundle. */
+ private static final String IMPORTANT_DOMAINS_TAG = "ImportantDomains";
+
+ /** Transforms a domain into an origin for favicon lookup. */
+ private static String transformDomainToOrigin(String domain) {
+ return "http://www." + domain;
+ }
+
+ /** Array of important registerable domains we're showing to the user. */
+ private String[] mImportantDomains;
+ /** The set of domains that the user has deselected. */
+ private Set<String> mDeselectedDomains;
+ /** The alert dialog shown to the user. */
+ private AlertDialog mDialog;
+ /** Our adapter that we use with the list view in the dialog. */
+ private ClearBrowsingDataAdapter mAdapter;
+ /** We use this to fetch favicon images. */
+ private FaviconHelper mFaviconHelper;
+ /**
+ * We store favicon images here so we don't have to reload them when Android wants to refresh
+ * each row.
+ */
+ private FaviconCache mFaviconCache;
+ private Profile mProfile;
+
+ protected ConfirmImportantSitesDialogFragment() {
+ mProfile = Profile.getLastUsedProfile();
+ mFaviconHelper = new FaviconHelper();
+ mDeselectedDomains = new HashSet<>();
+ mFaviconCache = new FaviconCache(PrefServiceBridge.getMaxImportantSites());
+ }
+
+ @Override
+ public void setArguments(Bundle args) {
+ super.setArguments(args);
+ mImportantDomains = args.getStringArray(IMPORTANT_DOMAINS_TAG);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ mAdapter = new ClearBrowsingDataAdapter(mImportantDomains);
+ DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == AlertDialog.BUTTON_POSITIVE) {
+ // Return our deselected domains.
+ Intent data = getActivity().getIntent();
+ String[] deselectedDomains = mDeselectedDomains.toArray(new String[0]);
+ data.putExtra(DESELECTED_DOMAINS_TAG, deselectedDomains);
+ getTargetFragment().onActivityResult(
+ getTargetRequestCode(), Activity.RESULT_OK, data);
+ } else {
+ getTargetFragment().onActivityResult(getTargetRequestCode(),
+ Activity.RESULT_CANCELED, getActivity().getIntent());
+ }
+ }
+ };
+ // We create our own ListView, as AlertDialog doesn't let us set a message and a list
+ // adapter at the same time.
+ ListView listView = (ListView) getActivity().getLayoutInflater().inflate(
+ R.layout.select_dialog_listview, null);
+ listView.setAdapter(mAdapter);
+ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
+ mAdapter.onClick(position, v);
+ }
+ });
+ final AlertDialog.Builder builder =
+ new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme)
+ .setTitle(R.string.storage_clear_site_storage_title)
+ .setMessage(R.string.clear_browsing_data_important_dialog_text)
+ .setPositiveButton(R.string.clear_data_delete, listener)
+ .setNegativeButton(R.string.cancel, listener)
+ .setView(listView);
+ mDialog = builder.create();
+
+ return mDialog;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698