Commit a8c329d4 authored by dtrainor's avatar dtrainor Committed by Commit bot

IPH - connect data saver previews

Adds the IPH that points to the data saver preview infobar.  This
includes three main changes:
- Adding support for determining which kind of infobar is showing in
Java.
- Hooking up the info bar show code to log an event saying it was shown.
- Hooking up the info bar show code to a function which can pick (if
any) a feature and string to show which will point to that infobar.

BUG=710648

Review-Url: https://codereview.chromium.org/2815653003
Cr-Commit-Position: refs/heads/master@{#467935}
parent fa3fcf6e
// Copyright 2017 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.infobar;
import android.content.Context;
import android.support.annotation.StringRes;
import android.view.View;
import android.widget.PopupWindow.OnDismissListener;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory;
import org.chromium.chrome.browser.infobar.InfoBarContainer.InfoBarContainerObserver;
import org.chromium.chrome.browser.infobar.InfoBarContainerLayout.Item;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.widget.textbubble.TextBubble;
import org.chromium.chrome.browser.widget.textbubble.ViewAnchoredTextBubble;
import org.chromium.components.feature_engagement_tracker.EventConstants;
import org.chromium.components.feature_engagement_tracker.FeatureConstants;
import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker;
/**
* A helper class to managing showing and dismissing in-product help dialogs based on which infobar
* is frontmost and showing. This will show an in-product help window when a new relevant infobar
* becomes front-most. If that infobar is closed or another infobar comes to the front the window
* will be dismissed.
*/
class IPHInfoBarSupport implements OnDismissListener, InfoBarContainer.InfoBarAnimationListener,
InfoBarContainerObserver {
private final Context mContext;
private final FeatureEngagementTracker mTracker;
/** Helper class to hold all relevant display parameters for an in-product help window. */
private static class TrackerParameters {
public TrackerParameters(String feature, @StringRes int textId) {
this.feature = feature;
this.textId = textId;
}
/** @see FeatureConstants */
public String feature;
@StringRes
public int textId;
}
/** Helper class to manage state relating to a particular instance of an in-product window. */
private static class PopupState {
/** The View that represents the infobar that the in-product window is attached to. */
public View view;
/** The bubble that is currently showing the in-product help. */
public TextBubble bubble;
}
/** The state of the currently showing in-product window or {@code null} if none is showing. */
private PopupState mCurrentState;
/** Creates a new instance of an IPHInfoBarSupport class. */
IPHInfoBarSupport(Context context) {
mContext = context;
Profile profile = Profile.getLastUsedProfile();
mTracker = FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(profile);
}
// InfoBarContainer.InfoBarAnimationListener implementation.
@Override
public void notifyAnimationFinished(int animationType) {}
@Override
public void notifyAllAnimationsFinished(Item frontInfoBar) {
View view = frontInfoBar == null ? null : frontInfoBar.getView();
if (mCurrentState != null) {
// Clean up any old infobar if necessary.
if (mCurrentState.view != view) {
mCurrentState.bubble.dismiss();
mCurrentState = null;
}
}
if (frontInfoBar == null) return;
// Check if we need to log any IPH events based on the infobar.
logEvent(frontInfoBar);
// Check if there are any IPH'es we need to show.
TrackerParameters params = getTrackerParameters(frontInfoBar);
if (params == null) return;
if (!mTracker.shouldTriggerHelpUI(params.feature)) return;
mCurrentState = new PopupState();
mCurrentState.view = view;
mCurrentState.bubble = new ViewAnchoredTextBubble(mContext, view, params.textId);
mCurrentState.bubble.addOnDismissListener(this);
mCurrentState.bubble.setDismissOnTouchInteraction(true);
mCurrentState.bubble.show();
}
// InfoBarContainerObserver implementation.
@Override
public void onAddInfoBar(InfoBarContainer container, InfoBar infoBar, boolean isFirst) {}
@Override
public void onRemoveInfoBar(InfoBarContainer container, InfoBar infoBar, boolean isLast) {
if (mCurrentState != null && infoBar.getView() == mCurrentState.view) {
mCurrentState.bubble.dismiss();
mCurrentState = null;
}
}
@Override
public void onInfoBarContainerAttachedToWindow(boolean hasInfobars) {}
// PopupWindow.OnDismissListener implementation.
@Override
public void onDismiss() {
mCurrentState = null;
mTracker.dismissed();
}
private void logEvent(Item infoBar) {
switch (infoBar.getInfoBarIdentifier()) {
case InfoBarIdentifier.DATA_REDUCTION_PROXY_PREVIEW_INFOBAR_DELEGATE:
mTracker.notifyEvent(EventConstants.DATA_SAVER_PREVIEW_INFOBAR_SHOWN);
break;
default:
break;
}
}
private TrackerParameters getTrackerParameters(Item infoBar) {
switch (infoBar.getInfoBarIdentifier()) {
case InfoBarIdentifier.DATA_REDUCTION_PROXY_PREVIEW_INFOBAR_DELEGATE:
return new TrackerParameters(
FeatureConstants.DATA_SAVER_PREVIEW, R.string.iph_data_saver_preview_text);
default:
return null;
}
}
}
\ No newline at end of file
......@@ -140,6 +140,13 @@ public abstract class InfoBar implements InfoBarView {
return false;
}
@Override
@InfoBarIdentifier
public int getInfoBarIdentifier() {
if (mNativeInfoBarPtr == 0) return InfoBarIdentifier.INVALID;
return nativeGetInfoBarIdentifier(mNativeInfoBarPtr);
}
/**
* @return whether the infobar actually needed closing.
*/
......@@ -200,6 +207,8 @@ public abstract class InfoBar implements InfoBarView {
public void createContent(InfoBarLayout layout) {
}
@InfoBarIdentifier
private native int nativeGetInfoBarIdentifier(long nativeInfoBarAndroid);
private native void nativeOnLinkClicked(long nativeInfoBarAndroid);
private native void nativeOnButtonClicked(long nativeInfoBarAndroid, int action);
private native void nativeOnCloseButtonClicked(long nativeInfoBarAndroid);
......
......@@ -15,6 +15,7 @@ import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.banners.SwipableOverlayView;
import org.chromium.chrome.browser.infobar.InfoBarContainerLayout.Item;
import org.chromium.chrome.browser.tab.EmptyTabObserver;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabObserver;
......@@ -57,6 +58,12 @@ public class InfoBarContainer extends SwipableOverlayView {
* Notifies the subscriber when an animation is completed.
*/
void notifyAnimationFinished(int animationType);
/**
* Notifies the subscriber when all animations are finished.
* @param frontInfoBar The frontmost infobar or {@code null} if none are showing.
*/
void notifyAllAnimationsFinished(Item frontInfoBar);
}
/**
......@@ -130,6 +137,9 @@ public class InfoBarContainer extends SwipableOverlayView {
private final InfoBarContainerLayout mLayout;
/** Helper class to manage showing in-product help bubbles over specific info bars. */
private final IPHInfoBarSupport mIPHSupport;
/** Native InfoBarContainer pointer which will be set by nativeInit(). */
private final long mNativeInfoBarContainer;
......@@ -173,6 +183,10 @@ public class InfoBarContainer extends SwipableOverlayView {
addView(mLayout, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL));
mIPHSupport = new IPHInfoBarSupport(context);
mLayout.addAnimationListener(mIPHSupport);
addObserver(mIPHSupport);
// Chromium's InfoBarContainer may add an InfoBar immediately during this initialization
// call, so make sure everything in the InfoBarContainer is completely ready beforehand.
mNativeInfoBarContainer = nativeInit();
......@@ -212,8 +226,8 @@ public class InfoBarContainer extends SwipableOverlayView {
}
@VisibleForTesting
public void setAnimationListener(InfoBarAnimationListener listener) {
mLayout.setAnimationListener(listener);
public void addAnimationListener(InfoBarAnimationListener listener) {
mLayout.addAnimationListener(listener);
}
/**
......@@ -298,6 +312,8 @@ public class InfoBarContainer extends SwipableOverlayView {
}
public void destroy() {
mLayout.removeAnimationListener(mIPHSupport);
removeObserver(mIPHSupport);
mDestroyed = true;
if (mNativeInfoBarContainer != 0) {
nativeDestroy(mNativeInfoBarContainer);
......
......@@ -17,6 +17,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import org.chromium.base.ObserverList;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.infobar.InfoBarContainer.InfoBarAnimationListener;
......@@ -60,12 +61,11 @@ import java.util.ArrayList;
*
* TODO(newt): finalize animation timings and interpolators.
*/
class InfoBarContainerLayout extends FrameLayout {
public class InfoBarContainerLayout extends FrameLayout {
/**
* An interface for items that can be added to an InfoBarContainerLayout.
*/
interface Item {
public interface Item {
/**
* Returns the View that represents this infobar. This should have no background or borders;
* a background and shadow will be added by a wrapper view.
......@@ -95,6 +95,13 @@ class InfoBarContainerLayout extends FrameLayout {
* any other infobars already visible.
*/
boolean isLegalDisclosure();
/**
* Returns the type of infobar, as best as can be determined at this time. See
* components/infobars/core/infobar_delegate.h.
*/
@InfoBarIdentifier
int getInfoBarIdentifier();
}
/**
......@@ -146,10 +153,17 @@ class InfoBarContainerLayout extends FrameLayout {
}
/**
* Sets a listener to receive updates when each animation is complete.
* Adds a listener to receive updates when each animation is complete.
*/
void addAnimationListener(InfoBarAnimationListener listener) {
mAnimationListeners.addObserver(listener);
}
/**
* Removes a listener that was receiving updates when each animation is complete.
*/
void setAnimationListener(InfoBarAnimationListener listener) {
mAnimationListener = listener;
void removeAnimationListener(InfoBarAnimationListener listener) {
mAnimationListeners.removeObserver(listener);
}
/////////////////////////////////////////
......@@ -184,8 +198,8 @@ class InfoBarContainerLayout extends FrameLayout {
public void onAnimationEnd(Animator animation) {
mAnimation = null;
InfoBarAnimation.this.onAnimationEnd();
if (mAnimationListener != null) {
mAnimationListener.notifyAnimationFinished(getAnimationType());
for (InfoBarAnimationListener listener : mAnimationListeners) {
listener.notifyAnimationFinished(getAnimationType());
}
processPendingAnimations();
}
......@@ -683,11 +697,12 @@ class InfoBarContainerLayout extends FrameLayout {
*/
private final ArrayList<InfoBarWrapper> mInfoBarWrappers = new ArrayList<>();
/** A list of observers that are notified when animations finish. */
private final ObserverList<InfoBarAnimationListener> mAnimationListeners = new ObserverList<>();
/** The current animation, or null if no animation is happening currently. */
private InfoBarAnimation mAnimation;
private InfoBarAnimationListener mAnimationListener;
private FloatingBehavior mFloatingBehavior;
/**
......@@ -769,6 +784,13 @@ class InfoBarContainerLayout extends FrameLayout {
runAnimation(mInfoBarWrappers.isEmpty()
? new FirstInfoBarAppearingAnimation(itemToShow)
: new BackInfoBarAppearingAnimation(itemToShow));
return;
}
// Fifth, now that we've stabilized, let listeners know that we have no more animations.
Item frontItem = mInfoBarWrappers.size() > 0 ? mInfoBarWrappers.get(0).getItem() : null;
for (InfoBarAnimationListener listener : mAnimationListeners) {
listener.notifyAllAnimationsFinished(frontItem);
}
}
......
......@@ -249,15 +249,19 @@ public class TextBubble implements OnTouchListener {
int spaceAboveAnchor = mAnchorRect.top - mCachedWindowRect.top - paddingY - mMarginPx;
int spaceBelowAnchor = mCachedWindowRect.bottom - mAnchorRect.bottom - paddingY - mMarginPx;
// Position the bubble below the anchor if it fits or, if not, it's the largest space
// available. This does bias the bubbles to show below the anchors if possible.
// Bias based on the center of the bubble and where it is on the screen.
boolean idealFitsBelow = idealHeight <= spaceBelowAnchor;
boolean idealFitsAbove = idealHeight <= spaceAboveAnchor;
// Position the bubble in the largest available space where it can fit. This will bias the
// bubbles to show below the anchor if it will not fit in either place.
boolean positionBelow =
idealHeight <= spaceBelowAnchor || spaceBelowAnchor >= spaceAboveAnchor;
(idealFitsBelow && spaceBelowAnchor >= spaceAboveAnchor) || !idealFitsAbove;
// Override the ideal bubble orientation if we are trying to maintain the current one.
if (preferCurrentOrientation && currentPositionBelow != positionBelow) {
if (currentPositionBelow && idealHeight <= spaceBelowAnchor) positionBelow = true;
if (!currentPositionBelow && idealHeight <= spaceAboveAnchor) positionBelow = false;
if (currentPositionBelow && idealFitsBelow) positionBelow = true;
if (!currentPositionBelow && idealFitsAbove) positionBelow = false;
}
int maxContentHeight = positionBelow ? spaceBelowAnchor : spaceAboveAnchor;
......
......@@ -980,6 +980,11 @@ To obtain new licenses, connect to the internet and play your downloaded content
No USB devices here
</message>
<!-- IPH Strings -->
<message name="IDS_IPH_DATA_SAVER_PREVIEW_TEXT" desc="In-product help for when a data saver preview page and infobar are shown.">
Chrome is using less data to show you this page
</message>
<!-- Data Saver -->
<message name="IDS_DATA_REDUCTION_TITLE" desc="Menu item for Data Saver, which allows users to save mobile data by compressing network traffic.">
Data Saver
......
......@@ -456,6 +456,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/infobar/InfoBarWrapper.java",
"java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBar.java",
"java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBarDelegate.java",
"java/src/org/chromium/chrome/browser/infobar/IPHInfoBarSupport.java",
"java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java",
"java/src/org/chromium/chrome/browser/infobar/PermissionUpdateInfoBarDelegate.java",
"java/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBar.java",
......
......@@ -31,6 +31,7 @@ import org.chromium.chrome.browser.infobar.AppBannerInfoBarDelegateAndroid;
import org.chromium.chrome.browser.infobar.InfoBar;
import org.chromium.chrome.browser.infobar.InfoBarContainer;
import org.chromium.chrome.browser.infobar.InfoBarContainer.InfoBarAnimationListener;
import org.chromium.chrome.browser.infobar.InfoBarContainerLayout.Item;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.webapps.WebappDataStorage;
......@@ -162,6 +163,9 @@ public class AppBannerManagerTest extends ChromeTabbedActivityTestBase {
mDoneAnimating = true;
}
}
@Override
public void notifyAllAnimationsFinished(Item frontInfoBar) {}
}
private MockAppDetailsDelegate mDetailsDelegate;
......@@ -257,7 +261,7 @@ public class AppBannerManagerTest extends ChromeTabbedActivityTestBase {
resetEngagementForUrl(url, 10);
InfoBarContainer container = getActivity().getActivityTab().getInfoBarContainer();
final InfobarListener listener = new InfobarListener();
container.setAnimationListener(listener);
container.addAnimationListener(listener);
new TabLoadObserver(getActivity().getActivityTab()).fullyLoadUrl(url, PageTransition.TYPED);
waitUntilAppDetailsRetrieved(1);
assertEquals(mDetailsDelegate.mReferrer, expectedReferrer);
......@@ -324,7 +328,7 @@ public class AppBannerManagerTest extends ChromeTabbedActivityTestBase {
// Add the animation listener in.
InfoBarContainer container = getActivity().getActivityTab().getInfoBarContainer();
final InfobarListener listener = new InfobarListener();
container.setAnimationListener(listener);
container.addAnimationListener(listener);
// Update engagement, then revisit the page to get the banner to appear.
resetEngagementForUrl(url, 10);
......@@ -442,7 +446,7 @@ public class AppBannerManagerTest extends ChromeTabbedActivityTestBase {
resetEngagementForUrl(mNativeAppUrl, 10);
InfoBarContainer container = getActivity().getActivityTab().getInfoBarContainer();
final InfobarListener listener = new InfobarListener();
container.setAnimationListener(listener);
container.addAnimationListener(listener);
new TabLoadObserver(getActivity().getActivityTab())
.fullyLoadUrl(mNativeAppUrl, PageTransition.TYPED);
waitUntilAppDetailsRetrieved(1);
......@@ -490,7 +494,7 @@ public class AppBannerManagerTest extends ChromeTabbedActivityTestBase {
resetEngagementForUrl(mWebAppUrl, 10);
InfoBarContainer container = getActivity().getActivityTab().getInfoBarContainer();
final InfobarListener listener = new InfobarListener();
container.setAnimationListener(listener);
container.addAnimationListener(listener);
new TabLoadObserver(getActivity().getActivityTab())
.fullyLoadUrl(mWebAppUrl, PageTransition.TYPED);
waitUntilAppBannerInfoBarAppears(WEB_APP_TITLE);
......
......@@ -73,7 +73,7 @@ public class InfoBarContainerTest extends ChromeActivityTestCaseBase<ChromeActiv
InfoBarContainer container =
getActivity().getActivityTab().getInfoBarContainer();
mListener = new InfoBarTestAnimationListener();
container.setAnimationListener(mListener);
container.addAnimationListener(mListener);
mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
}
......
......@@ -92,7 +92,7 @@ public class InfoBarTest extends ChromeActivityTestCaseBase<ChromeActivity> {
});
InfoBarContainer container = getActivity().getActivityTab().getInfoBarContainer();
mListener = new InfoBarTestAnimationListener();
container.setAnimationListener(mListener);
container.addAnimationListener(mListener);
mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
......@@ -471,7 +471,7 @@ public class InfoBarTest extends ChromeActivityTestCaseBase<ChromeActivity> {
// Swap out the WebContents and send the user somewhere so that the InfoBar gets removed.
InfoBarTestAnimationListener removeListener = new InfoBarTestAnimationListener();
getActivity().getActivityTab().getInfoBarContainer().setAnimationListener(removeListener);
getActivity().getActivityTab().getInfoBarContainer().addAnimationListener(removeListener);
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
......@@ -485,7 +485,7 @@ public class InfoBarTest extends ChromeActivityTestCaseBase<ChromeActivity> {
// Revisiting the original page should make the InfoBar reappear.
InfoBarTestAnimationListener addListener = new InfoBarTestAnimationListener();
getActivity().getActivityTab().getInfoBarContainer().setAnimationListener(addListener);
getActivity().getActivityTab().getInfoBarContainer().addAnimationListener(addListener);
loadUrl(mTestServer.getURL(GEOLOCATION_PAGE));
addListener.addInfoBarAnimationFinished("InfoBar not added");
assertEquals("Wrong infobar count", 1, getInfoBars().size());
......
......@@ -77,7 +77,7 @@ public class PermissionUpdateInfobarTest extends ChromeTabbedActivityTestBase {
});
InfoBarContainer container = getActivity().getActivityTab().getInfoBarContainer();
mListener = new InfoBarTestAnimationListener();
container.setAnimationListener(mListener);
container.addAnimationListener(mListener);
final String locationUrl = mTestServer.getURL(GEOLOCATION_PAGE);
final GeolocationInfo geolocationSettings = ThreadUtils.runOnUiThreadBlockingNoException(
......@@ -156,7 +156,7 @@ public class PermissionUpdateInfobarTest extends ChromeTabbedActivityTestBase {
});
InfoBarContainer container = getActivity().getActivityTab().getInfoBarContainer();
mListener = new InfoBarTestAnimationListener();
container.setAnimationListener(mListener);
container.addAnimationListener(mListener);
final String locationUrl = mTestServer.getURL(GEOLOCATION_IFRAME_PAGE);
final GeolocationInfo geolocationSettings = ThreadUtils.runOnUiThreadBlockingNoException(
......
......@@ -68,7 +68,7 @@ public class SearchGeolocationDisclosureInfoBarTest
// Infobar should appear when doing the first search.
InfoBarContainer container = getActivity().getActivityTab().getInfoBarContainer();
InfoBarTestAnimationListener listener = new InfoBarTestAnimationListener();
container.setAnimationListener(listener);
container.addAnimationListener(listener);
loadUrl(mTestServer.getURL(SEARCH_PAGE));
// Note: the number of infobars is checked immediately after the URL is loaded, unlike in
// other infobar tests where it is checked after animations have completed. This is because
......@@ -89,7 +89,7 @@ public class SearchGeolocationDisclosureInfoBarTest
// Infobar should appear again the next day.
SearchGeolocationDisclosureTabHelper.setDayOffsetForTesting(1);
listener = new InfoBarTestAnimationListener();
container.setAnimationListener(listener);
container.addAnimationListener(listener);
loadUrl(mTestServer.getURL(SEARCH_PAGE));
assertEquals("Wrong infobar count after search", 1, getInfoBars().size());
listener.addInfoBarAnimationFinished("InfoBar not added.");
......@@ -102,7 +102,7 @@ public class SearchGeolocationDisclosureInfoBarTest
// Infobar should appear again the next day.
SearchGeolocationDisclosureTabHelper.setDayOffsetForTesting(2);
listener = new InfoBarTestAnimationListener();
container.setAnimationListener(listener);
container.addAnimationListener(listener);
loadUrl(mTestServer.getURL(SEARCH_PAGE));
assertEquals("Wrong infobar count after search", 1, getInfoBars().size());
listener.addInfoBarAnimationFinished("InfoBar not added.");
......@@ -136,7 +136,7 @@ public class SearchGeolocationDisclosureInfoBarTest
// Infobar should appear when doing the first search.
InfoBarContainer container = getActivity().getActivityTab().getInfoBarContainer();
InfoBarTestAnimationListener listener = new InfoBarTestAnimationListener();
container.setAnimationListener(listener);
container.addAnimationListener(listener);
loadUrl(mTestServer.getURL(SEARCH_PAGE));
assertEquals("Wrong infobar count after search", 1, getInfoBars().size());
listener.addInfoBarAnimationFinished("InfoBar not added.");
......
......@@ -126,7 +126,7 @@ public class PermissionTestCaseBase extends ChromeActivityTestCaseBase<ChromeAct
InfoBarContainer container =
getActivity().getTabModelSelector().getCurrentTab().getInfoBarContainer();
mListener = new InfoBarTestAnimationListener();
container.setAnimationListener(mListener);
container.addAnimationListener(mListener);
mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
}
......
......@@ -87,7 +87,7 @@ public class SiteSettingsPreferencesTest extends ChromeActivityTestCaseBase<Chro
InfoBarContainer container =
getActivity().getActivityTab().getInfoBarContainer();
InfoBarTestAnimationListener listener = new InfoBarTestAnimationListener();
container.setAnimationListener(listener);
container.addAnimationListener(listener);
return listener;
}
});
......
......@@ -56,7 +56,7 @@ public class TranslateInfoBarTest extends ChromeActivityTestCaseBase<ChromeActiv
super.setUp();
mInfoBarContainer = getActivity().getActivityTab().getInfoBarContainer();
mListener = new InfoBarTestAnimationListener();
mInfoBarContainer.setAnimationListener(mListener);
mInfoBarContainer.addAnimationListener(mListener);
mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
}
......
......@@ -55,6 +55,11 @@ bool InfoBarAndroid::HasSetJavaInfoBar() const {
return !java_info_bar_.is_null();
}
int InfoBarAndroid::GetInfoBarIdentifier(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
return delegate()->GetIdentifier();
}
void InfoBarAndroid::OnButtonClicked(JNIEnv* env,
const JavaParamRef<jobject>& obj,
jint action) {
......
......@@ -47,6 +47,8 @@ class InfoBarAndroid : public infobars::InfoBar {
// InfoBar instead of this one.
void ReassignJavaInfoBar(InfoBarAndroid* replacement);
int GetInfoBarIdentifier(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
virtual void OnLinkClicked(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) {}
void OnButtonClicked(JNIEnv* env,
......
......@@ -6,6 +6,7 @@ package org.chromium.chrome.test.util;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.chrome.browser.infobar.InfoBarContainer.InfoBarAnimationListener;
import org.chromium.chrome.browser.infobar.InfoBarContainerLayout.Item;
import java.util.concurrent.TimeoutException;
......@@ -45,6 +46,9 @@ public class InfoBarTestAnimationListener implements InfoBarAnimationListener {
}
}
@Override
public void notifyAllAnimationsFinished(Item frontInfoBar) {}
public void addInfoBarAnimationFinished(String msg)
throws InterruptedException, TimeoutException {
mAddAnimationFinished.waitForCallback(msg, mAddCallCount);
......
......@@ -11,6 +11,8 @@ namespace feature_engagement_tracker {
const base::Feature kIPHDemoMode{"IPH_DemoMode",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHDataSaverPreview{"IPH_DataSaverPreview",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHDownloadPageFeature{"IPH_DownloadPage",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHDownloadHomeFeature{"IPH_DownloadHome",
......
......@@ -11,8 +11,8 @@ namespace feature_engagement_tracker {
namespace {
const base::Feature* kAllFeatures[] = {&kIPHDownloadPageFeature,
&kIPHDownloadHomeFeature};
const base::Feature* kAllFeatures[] = {
&kIPHDataSaverPreview, &kIPHDownloadPageFeature, &kIPHDownloadHomeFeature};
} // namespace
......
......@@ -28,6 +28,11 @@ public final class EventConstants {
*/
public static final String DOWNLOAD_HOME_OPENED = "download_home_opened";
/**
* The data saver preview infobar was shown.
*/
public static final String DATA_SAVER_PREVIEW_INFOBAR_SHOWN = "data_saver_preview_opened";
/**
* Do not instantiate.
*/
......
......@@ -12,6 +12,8 @@ public final class FeatureConstants {
public static final String DOWNLOAD_PAGE_FEATURE = "IPH_DownloadPage";
public static final String DOWNLOAD_HOME_FEATURE = "IPH_DownloadHome";
public static final String DATA_SAVER_PREVIEW = "IPH_DataSaverPreview";
/**
* Do not instantiate.
*/
......
......@@ -15,6 +15,7 @@ extern const base::Feature kIPHDemoMode;
// All the features declared below should also be declared in the Java
// version: org.chromium.components.feature_engagement_tracker.FeatureConstants.
extern const base::Feature kIPHDataSaverPreview;
extern const base::Feature kIPHDownloadPageFeature;
extern const base::Feature kIPHDownloadHomeFeature;
......
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