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

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelStateHandler.java

Issue 987883002: Upstream Layout.java and associated files (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Move to SuppressFBWarnings from findbugs_exclude.xml Created 5 years, 9 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/compositor/bottombar/contextualsearch/ContextualSearchPanelStateHandler.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelStateHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelStateHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..a775698d7fc9035061834e91867a9ea0d7b373a5
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelStateHandler.java
@@ -0,0 +1,263 @@
+// 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.compositor.bottombar.contextualsearch;
+
+import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel.PanelState;
+import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel.StateChangeReason;
+import org.chromium.chrome.browser.contextualsearch.ContextualSearchUma;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Holds the state of the Contextual Search Panel.
+ */
+abstract class ContextualSearchPanelStateHandler {
+
+ // Valid previous states for when the promo is active.
+ private static final Map<PanelState, PanelState> PREVIOUS_STATES_PROMO;
+ static {
+ Map<PanelState, PanelState> states = new HashMap<PanelState, PanelState>();
+ // Pairs are of the form <Current, Previous>.
+ states.put(PanelState.PEEKED, PanelState.CLOSED);
+ states.put(PanelState.PROMO, PanelState.PEEKED);
+ states.put(PanelState.EXPANDED, PanelState.PROMO);
+ PREVIOUS_STATES_PROMO = Collections.unmodifiableMap(states);
+ }
+
+ // Valid previous states for when the promo is not active (normal flow).
+ private static final Map<PanelState, PanelState> PREVIOUS_STATES_NORMAL;
+ static {
+ Map<PanelState, PanelState> states = new HashMap<PanelState, PanelState>();
+ // Pairs are of the form <Current, Previous>.
+ states.put(PanelState.PEEKED, PanelState.CLOSED);
+ states.put(PanelState.EXPANDED, PanelState.PEEKED);
+ states.put(PanelState.MAXIMIZED, PanelState.EXPANDED);
+ PREVIOUS_STATES_NORMAL = Collections.unmodifiableMap(states);
+ }
+
+ // The current state of the Contextual Search Panel.
+ private PanelState mPanelState = PanelState.UNDEFINED;
+ private boolean mDidSearchInvolvePromo;
+ private boolean mWasSearchContentViewSeen;
+ private boolean mIsPromoActive;
+ private boolean mHasExpanded;
+ private boolean mHasMaximized;
+ private boolean mHasExitedPeeking;
+ private boolean mHasExitedExpanded;
+ private boolean mHasExitedMaximized;
+ private boolean mIsSerpNavigation;
+ private long mSearchStartTimeNs;
+
+ // --------------------------------------------------------------------------------------------
+ // Contextual Search Panel states
+ // --------------------------------------------------------------------------------------------
+
+ /**
+ * @return The panel's state.
+ */
+ PanelState getPanelState() {
+ return mPanelState;
+ }
+
+ /**
+ * @return The {@code PanelState} that is before the |state| in the order of states.
+ */
+ PanelState getPreviousPanelState(PanelState state) {
+ PanelState prevState = mIsPromoActive
+ ? PREVIOUS_STATES_PROMO.get(state)
+ : PREVIOUS_STATES_NORMAL.get(state);
+ return prevState != null ? prevState : PanelState.UNDEFINED;
+ }
+
+ /**
+ * Return the maximum state that the panel can be in, depending on whether the promo is
+ * active.
+ */
+ PanelState getMaximumState() {
+ return mIsPromoActive ? PanelState.PROMO : PanelState.MAXIMIZED;
+ }
+
+ /**
+ * Return the intermediary state that the panel can be in, depending on whether the promo is
+ * active.
+ */
+ PanelState getIntermediaryState() {
+ return mIsPromoActive ? PanelState.PROMO : PanelState.EXPANDED;
+ }
+
+ /**
+ * Sets the panel's state.
+ * @param toState The panel state to transition to.
+ * @param reason The reason for a change in the panel's state.
+ */
+ protected void setPanelState(PanelState toState, StateChangeReason reason) {
+ // Note: the logging within this function includes the promo, unless specifically
+ // excluded.
+ PanelState fromState = mPanelState;
+ boolean isStartingSearch = isStartingNewContextualSearch(toState, reason);
+ boolean isEndingSearch = isEndingContextualSearch(toState, isStartingSearch);
+ boolean isChained = isStartingSearch && isOngoingContextualSearch();
+ boolean isSameState = fromState == toState;
+ boolean isFirstExitFromPeeking = fromState == PanelState.PEEKED && !mHasExitedPeeking
+ && (!isSameState || isStartingSearch);
+ boolean isFirstExitFromExpanded = fromState == PanelState.EXPANDED && !mHasExitedExpanded
+ && !isSameState;
+ boolean isFirstExitFromMaximized = fromState == PanelState.MAXIMIZED && !mHasExitedMaximized
+ && !isSameState;
+
+ if (isEndingSearch) {
+ if (!mDidSearchInvolvePromo) {
+ // Measure duration only when the promo is not involved.
+ long durationMs = (System.nanoTime() - mSearchStartTimeNs) / 1000000;
+ ContextualSearchUma.logDuration(mWasSearchContentViewSeen, isChained, durationMs);
+ }
+ if (mIsPromoActive) {
+ // The user is exiting still in the promo, without choosing an option.
+ ContextualSearchUma.logFirstRunPanelSeen(mWasSearchContentViewSeen);
+ } else {
+ ContextualSearchUma.logResultsSeen(mWasSearchContentViewSeen);
+ }
+ }
+ if (isStartingSearch) {
+ mSearchStartTimeNs = System.nanoTime();
+ }
+
+ // Log state changes. We only log the first transition to a state within a contextual
+ // search. Note that when a user clicks on a link on the search content view, this will
+ // trigger a transition to MAXIMIZED (SERP_NAVIGATION) followed by a transition to
+ // CLOSED (TAB_PROMOTION). For the purpose of logging, the reason for the second transition
+ // is reinterpreted to SERP_NAVIGATION, in order to distinguish it from a tab promotion
+ // caused when tapping on the Search Bar when the Panel is maximized.
+ StateChangeReason reasonForLogging =
+ mIsSerpNavigation ? StateChangeReason.SERP_NAVIGATION : reason;
+ if (isStartingSearch || isEndingSearch
+ || (!mHasExpanded && toState == PanelState.EXPANDED)
+ || (!mHasMaximized && toState == PanelState.MAXIMIZED)) {
+ ContextualSearchUma.logFirstStateEntry(fromState, toState, reasonForLogging);
+ }
+ // Note: CLOSED / UNDEFINED state exits are detected when a search that is not chained is
+ // starting.
+ if ((isStartingSearch && !isChained) || isFirstExitFromPeeking || isFirstExitFromExpanded
+ || isFirstExitFromMaximized) {
+ ContextualSearchUma.logFirstStateExit(fromState, toState, reasonForLogging);
+ }
+
+ // We can now modify the state.
+ if (isFirstExitFromPeeking) {
+ mHasExitedPeeking = true;
+ } else if (isFirstExitFromExpanded) {
+ mHasExitedExpanded = true;
+ } else if (isFirstExitFromMaximized) {
+ mHasExitedMaximized = true;
+ }
+
+ mPanelState = toState;
+
+ if (toState == PanelState.EXPANDED) {
+ mHasExpanded = true;
+ } else if (toState == PanelState.MAXIMIZED) {
+ mHasMaximized = true;
+ }
+ if (reason == StateChangeReason.SERP_NAVIGATION) {
+ mIsSerpNavigation = true;
+ }
+
+ if (isEndingSearch) {
+ mDidSearchInvolvePromo = false;
+ mWasSearchContentViewSeen = false;
+ mHasExpanded = false;
+ mHasMaximized = false;
+ mHasExitedPeeking = false;
+ mHasExitedExpanded = false;
+ mHasExitedMaximized = false;
+ mIsSerpNavigation = false;
+ }
+
+ // TODO(manzagop): When the user opts in, we should replay his actions for the current
+ // contextual search for the standard (non promo) UMA histograms.
+ }
+
+ /**
+ * Determine if a specific {@code PanelState} is a valid state in the current environment.
+ * @param state The state being evaluated.
+ * @return whether the state is valid.
+ */
+ boolean isValidState(PanelState state) {
+ ArrayList<PanelState> validStates;
+ if (mIsPromoActive) {
+ validStates = new ArrayList<PanelState>(PREVIOUS_STATES_PROMO.values());
+ } else {
+ validStates = new ArrayList<PanelState>(PREVIOUS_STATES_NORMAL.values());
+ // MAXIMIZED is not the previous state of anything, but it's a valid state.
+ validStates.add(PanelState.MAXIMIZED);
+ }
+
+ return validStates.contains(state);
+ }
+
+ /**
+ * Sets that the contextual search involved the promo.
+ */
+ void setDidSearchInvolvePromo() {
+ mDidSearchInvolvePromo = true;
+ }
+
+ /**
+ * Sets that the Search Content View was seen.
+ */
+ void setWasSearchContentViewSeen() {
+ mWasSearchContentViewSeen = true;
+ }
+
+ /**
+ * Sets whether the promo is active.
+ */
+ void setIsPromoActive(boolean shown) {
+ mIsPromoActive = shown;
+ }
+
+ /**
+ * Gets whether the promo is active.
+ */
+ boolean getIsPromoActive() {
+ return mIsPromoActive;
+ }
+
+ // --------------------------------------------------------------------------------------------
+ // Helpers
+ // --------------------------------------------------------------------------------------------
+
+ /**
+ * Determine whether a new contextual search is starting.
+ * @param toState The contextual search state that will be transitioned to.
+ * @param reason The reason for the search state transition.
+ * @return Whether a new contextual search is starting.
+ */
+ private boolean isStartingNewContextualSearch(PanelState toState, StateChangeReason reason) {
+ return toState == PanelState.PEEKED
+ && (reason == StateChangeReason.TEXT_SELECT_TAP
+ || reason == StateChangeReason.TEXT_SELECT_LONG_PRESS);
+ }
+
+ /**
+ * Determine whether a contextual search is ending.
+ * @param toState The contextual search state that will be transitioned to.
+ * @param isStartingSearch Whether a new contextual search is starting.
+ * @return Whether a contextual search is ending.
+ */
+ private boolean isEndingContextualSearch(PanelState toState, boolean isStartingSearch) {
+ return isOngoingContextualSearch() && (toState == PanelState.CLOSED || isStartingSearch);
+ }
+
+ /**
+ * @return Whether there is an ongoing contextual search.
+ */
+ private boolean isOngoingContextualSearch() {
+ return mPanelState != PanelState.UNDEFINED && mPanelState != PanelState.CLOSED;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698