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

Unified Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/snackbar/undo/UndoBarPopupController.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 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_staging/src/org/chromium/chrome/browser/snackbar/undo/UndoBarPopupController.java
diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/snackbar/undo/UndoBarPopupController.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/snackbar/undo/UndoBarPopupController.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb37bcc3f45e8d5b2dbc9c58d7a00d5a28274811
--- /dev/null
+++ b/chrome/android/java_staging/src/org/chromium/chrome/browser/snackbar/undo/UndoBarPopupController.java
@@ -0,0 +1,204 @@
+// 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.snackbar.undo;
+
+import android.content.Context;
+
+import com.google.android.apps.chrome.R;
+
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.Tab;
+import org.chromium.chrome.browser.device.DeviceClassManager;
+import org.chromium.chrome.browser.snackbar.SnackbarManager;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModelObserver;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * A controller that listens to and visually represents cancelable tab closures.
+ * <p/>
+ * Each time a tab is undoably closed via {@link TabModelObserver#tabPendingClosure(Tab)},
+ * this controller saves that tab id and title to the stack of SnackbarManager. It will then let
+ * SnackbarManager to show a snackbar representing the top entry in of stack. Each added entry
+ * resets the timeout that tracks when to commit the undoable actions.
+ * <p/>
+ * When the undo button is clicked, it will cancel the tab closure if any. all pending closing will
+ * be committed.
+ * <p/>
+ * This class also responds to external changes to the undo state by monitoring
+ * {@link TabModelObserver#tabClosureUndone(Tab)} and
+ * {@link TabModelObserver#tabClosureCommitted(Tab)} to properly keep it's internal state
+ * in sync with the model.
+ */
+public class UndoBarPopupController implements SnackbarManager.SnackbarController {
+ // AndroidTabCloseUndoToastEvent defined in tools/metrics/histograms/histograms.xml.
+ private static final int TAB_CLOSE_UNDO_TOAST_SHOWN_COLD = 0;
+ private static final int TAB_CLOSE_UNDO_TOAST_SHOWN_WARM = 1;
+ private static final int TAB_CLOSE_UNDO_TOAST_PRESSED = 2;
+ private static final int TAB_CLOSE_UNDO_TOAST_DISMISSED_TIMEOUT = 3;
+ private static final int TAB_CLOSE_UNDO_TOAST_DISMISSED_ACTION = 4;
+ private static final int TAB_CLOSE_UNDO_TOAST_COUNT = 5;
+
+ private final TabModelSelector mTabModelSelector;
+ private final TabModelObserver mTabModelObserver;
+ private final SnackbarManager mSnackbarManager;
+ private final Context mContext;
+
+ /**
+ * Creates an instance of a {@link UndoBarPopupController}.
+ * @param context The {@link Context} in which snackbar is shown.
+ * @param selector The {@link TabModelSelector} that will be used to commit and undo tab
+ * closures.
+ * @param snackbarManager The manager that helps to show up snackbar.
+ */
+ public UndoBarPopupController(Context context, TabModelSelector selector,
+ SnackbarManager snackbarManager) {
+ mSnackbarManager = snackbarManager;
+ mTabModelSelector = selector;
+ mContext = context;
+ mTabModelObserver = new EmptyTabModelObserver() {
+ private boolean disableUndo() {
+ return !DeviceClassManager.enableUndo(mContext)
+ || DeviceClassManager.isAccessibilityModeEnabled(mContext)
+ || DeviceClassManager.enableAccessibilityLayout();
+ }
+
+ @Override
+ public void tabPendingClosure(Tab tab) {
+ if (disableUndo()) return;
+ showUndoBar(tab.getId(), tab.getTitle());
+ }
+
+ @Override
+ public void tabClosureUndone(Tab tab) {
+ if (disableUndo()) return;
+ mSnackbarManager.removeSnackbarEntry(UndoBarPopupController.this, tab.getId());
+ }
+
+ @Override
+ public void tabClosureCommitted(Tab tab) {
+ if (disableUndo()) return;
+ mSnackbarManager.removeSnackbarEntry(UndoBarPopupController.this, tab.getId());
+ }
+
+ @Override
+ public void allTabsPendingClosure(List<Integer> tabIds) {
+ if (disableUndo()) return;
+ showUndoCloseAllBar(tabIds);
+ }
+
+ @Override
+ public void allTabsClosureCommitted() {
+ if (disableUndo()) return;
+ mSnackbarManager.removeSnackbarEntry(UndoBarPopupController.this);
+ }
+ };
+ }
+
+ /**
+ * Carry out native library dependent operations like registering observers and notifications.
+ */
+ public void initialize() {
+ mTabModelSelector.getModel(false).addObserver(mTabModelObserver);
+ }
+
+ /**
+ * Cleans up this class, unregistering for application notifications from the
+ * {@link TabModelSelector}.
+ */
+ public void destroy() {
+ TabModel model = mTabModelSelector.getModel(false);
+ if (model != null) model.removeObserver(mTabModelObserver);
+ }
+
+ /**
+ * Shows an undo bar. Based on user actions, this will cause a call to either
+ * {@link TabModel#commitTabClosure(int)} or {@link TabModel#cancelTabClosure(int)} to be called
+ * for {@code tabId}.
+ *
+ * @param tabId The id of the tab.
+ * @param content The title of the tab.
+ */
+ private void showUndoBar(int tabId, String content) {
+ RecordHistogram.recordEnumeratedHistogram("AndroidTabCloseUndo.Toast",
+ mSnackbarManager.isShowing() ? TAB_CLOSE_UNDO_TOAST_SHOWN_WARM
+ : TAB_CLOSE_UNDO_TOAST_SHOWN_COLD,
+ TAB_CLOSE_UNDO_TOAST_COUNT);
+ mSnackbarManager.showSnackbar(mContext.getString(R.string.undo_bar_close_message),
+ content, mContext.getString(R.string.undo_bar_button_text),
+ tabId, this);
+ }
+
+ /**
+ * Shows an undo close all bar. Based on user actions, this will cause a call to either
+ * {@link TabModel#commitTabClosure(int)} or {@link TabModel#cancelTabClosure(int)} to be called
+ * for each tab in {@code closedTabIds}. This will happen unless
+ * {@code SnackbarManager#removeFromStackForData(Object)} is called.
+ *
+ * @param closedTabIds A list of ids corresponding to tabs that were closed
+ */
+ private void showUndoCloseAllBar(List<Integer> closedTabIds) {
+ String content = String.format(Locale.getDefault(), "%d", closedTabIds.size());
+ mSnackbarManager.showSnackbar(mContext.getString(R.string.undo_bar_close_all_message),
+ content, mContext.getString(R.string.undo_bar_button_text),
+ closedTabIds, this);
+ }
+
+ /**
+ * Calls {@link TabModel#cancelTabClosure(int)} for the tab or for each tab in
+ * the list of closed tabs.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void onAction(Object actionData) {
+ RecordHistogram.recordEnumeratedHistogram("AndroidTabCloseUndo.Toast",
+ TAB_CLOSE_UNDO_TOAST_PRESSED, TAB_CLOSE_UNDO_TOAST_COUNT);
+ if (actionData instanceof Integer) {
+ cancelTabClosure((Integer) actionData);
+ } else {
+ for (Integer id : (List<Integer>) actionData) {
+ cancelTabClosure(id);
+ }
+ }
+ }
+
+ private void cancelTabClosure(int tabId) {
+ TabModel model = mTabModelSelector.getModelForTabId(tabId);
+ if (model != null) model.cancelTabClosure(tabId);
+ }
+
+ /**
+ * Calls {@link TabModel#commitTabClosure(int)} for the tab or for each tab in
+ * the list of closed tabs.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void onDismissNoAction(Object actionData) {
+ if (actionData instanceof Integer) {
+ commitTabClosure((Integer) actionData);
+ } else {
+ for (Integer tabId : (List<Integer>) actionData) {
+ commitTabClosure(tabId);
+ }
+ }
+ }
+
+ private void commitTabClosure(int tabId) {
+ TabModel model = mTabModelSelector.getModelForTabId(tabId);
+ if (model != null) model.commitTabClosure(tabId);
+ }
+
+ @Override
+ public void onDismissForEachType(boolean isTimeout) {
+ RecordHistogram.recordEnumeratedHistogram("AndroidTabCloseUndo.Toast",
+ isTimeout ? TAB_CLOSE_UNDO_TOAST_DISMISSED_TIMEOUT
+ : TAB_CLOSE_UNDO_TOAST_DISMISSED_ACTION,
+ TAB_CLOSE_UNDO_TOAST_COUNT);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698