Commit 5c29aab0 authored by Ehimare Okoyomon's avatar Ehimare Okoyomon Committed by Commit Bot

Create IncognitoNTPCookieControlsManager for ntp logic

Put incognito ntp cookie controls logic in a class and replaced
java-side logic with bridge to connect to c++ backend. Same class is
used for incognito for start surface.

Bug: 1040091
Change-Id: I18d679731aabda57c6b3852d4f0e4a68c268bb07
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2044273
Commit-Queue: Ehimare Okoyomon <eokoyomon@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Reviewed-by: default avatarChristian Dullweber <dullweber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#745417}
parent a165d9d1
......@@ -986,6 +986,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/ntp/FakeRecentlyClosedTabManager.java",
"java/src/org/chromium/chrome/browser/ntp/FakeboxDelegate.java",
"java/src/org/chromium/chrome/browser/ntp/ForeignSessionHelper.java",
"java/src/org/chromium/chrome/browser/ntp/IncognitoCookieControlsManager.java",
"java/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionView.java",
"java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java",
"java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageView.java",
......
......@@ -232,10 +232,12 @@ public class StartSurfaceCoordinator implements StartSurface {
TabManagementModuleProvider.getDelegate().createTasksSurface(mActivity,
propertyModel, mActivity.getToolbarManager().getFakeboxDelegate(), false);
// Intentionally do not call mSecondaryTasksSurface.initialize since the secondary tasks
// surface will never show MV tiles.
// TODO(crbug.com/1041047): Remove constructing of the MV tilles from the
// Call mSecondaryTasksSurface.initialize because some components needed to wait until
// after native is initialized. However, the secondary tasks surface will never show MV
// tiles.
// TODO(crbug.com/1041047): Remove constructing of the MV tiles from the
// TasksSurfaceCoordinator.
mSecondaryTasksSurface.initialize();
mSecondaryTasksSurface.getView().setId(R.id.secondary_tasks_surface_view);
mSecondaryTasksSurfacePropertyModelChangeProcessor =
......
......@@ -12,6 +12,7 @@ import android.widget.LinearLayout;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.help.HelpAndFeedback;
import org.chromium.chrome.browser.ntp.FakeboxDelegate;
import org.chromium.chrome.browser.ntp.IncognitoCookieControlsManager;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider;
import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
......@@ -49,10 +50,12 @@ public class TasksSurfaceCoordinator implements TasksSurface {
activity.getString(R.string.help_context_incognito_learn_more),
Profile.getLastUsedRegularProfile().getOffTheRecordProfile(), null);
};
// TODO(crbug.com/1040091): Add parameter for CookieSettingsBridge to control the cookie
// controls toggle on the IncognitoNTP.
mMediator = new TasksSurfaceMediator(
propertyModel, fakeboxDelegate, incognitoLearnMoreClickListener, isTabCarousel);
IncognitoCookieControlsManager incognitoCookieControlsManager =
new IncognitoCookieControlsManager();
mMediator = new TasksSurfaceMediator(propertyModel, fakeboxDelegate,
incognitoLearnMoreClickListener, incognitoCookieControlsManager, isTabCarousel);
LinearLayout mvTilesLayout = mView.findViewById(R.id.mv_tiles_layout);
mMostVisitedList = new MostVisitedListCoordinator(activity, mvTilesLayout, propertyModel);
......@@ -62,6 +65,7 @@ public class TasksSurfaceCoordinator implements TasksSurface {
@Override
public void initialize() {
mMostVisitedList.initialize();
mMediator.initialize();
}
@Override
......
......@@ -6,6 +6,10 @@ package org.chromium.chrome.browser.tasks;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_TEXT_WATCHER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_CARD_VISIBILITY;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_MANAGER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_LEARN_MORE_CLICK_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_VISIBLE;
......@@ -20,6 +24,7 @@ import androidx.annotation.Nullable;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.browser.ntp.FakeboxDelegate;
import org.chromium.chrome.browser.ntp.IncognitoCookieControlsManager;
import org.chromium.chrome.browser.omnibox.LocationBar;
import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler;
import org.chromium.ui.modelutil.PropertyModel;
......@@ -30,10 +35,13 @@ import org.chromium.ui.modelutil.PropertyModel;
class TasksSurfaceMediator {
@Nullable
private final FakeboxDelegate mFakeboxDelegate;
private final IncognitoCookieControlsManager mIncognitoCookieControlsManager;
private final IncognitoCookieControlsManager.Observer mIncognitoCookieControlsObserver;
private final PropertyModel mModel;
TasksSurfaceMediator(PropertyModel model, FakeboxDelegate fakeboxDelegate,
View.OnClickListener incognitoLearnMoreClickListener, boolean isTabCarousel) {
View.OnClickListener incognitoLearnMoreClickListener,
IncognitoCookieControlsManager incognitoCookieControlsManager, boolean isTabCarousel) {
mFakeboxDelegate = fakeboxDelegate;
assert mFakeboxDelegate != null;
......@@ -75,8 +83,33 @@ class TasksSurfaceMediator {
});
model.set(INCOGNITO_LEARN_MORE_CLICK_LISTENER, incognitoLearnMoreClickListener);
// Set Incognito Cookie Controls functionality
mIncognitoCookieControlsManager = incognitoCookieControlsManager;
mModel.set(INCOGNITO_COOKIE_CONTROLS_MANAGER, mIncognitoCookieControlsManager);
mIncognitoCookieControlsObserver = new IncognitoCookieControlsManager.Observer() {
@Override
public void onUpdate(boolean checked, boolean enforced) {
// TODO(crbug.com/1040091): use enforced to support the case where this toggle is
// managed by organization or the normal 3PC blocking setting and update the UI
// accordingly.
mModel.set(INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED, checked);
}
};
mIncognitoCookieControlsManager.addObserver(mIncognitoCookieControlsObserver);
mModel.set(
INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED_LISTENER, mIncognitoCookieControlsManager);
// Set the initial state.
mModel.set(IS_FAKE_SEARCH_BOX_VISIBLE, true);
mModel.set(IS_VOICE_RECOGNITION_BUTTON_VISIBLE, false);
}
/**
* Called to initialize this Mediator.
*/
void initialize() {
mIncognitoCookieControlsManager.initialize();
mModel.set(INCOGNITO_COOKIE_CONTROLS_CARD_VISIBILITY,
mIncognitoCookieControlsManager.shouldShowCookieControlsCard());
}
}
......@@ -8,7 +8,9 @@ import static org.chromium.chrome.browser.tasks.MostVisitedListProperties.IS_VIS
import android.text.TextWatcher;
import android.view.View;
import android.widget.CompoundButton.OnCheckedChangeListener;
import org.chromium.chrome.browser.ntp.IncognitoCookieControlsManager;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel;
......@@ -30,6 +32,18 @@ public class TasksSurfaceProperties {
public static final PropertyModel
.WritableBooleanPropertyKey IS_VOICE_RECOGNITION_BUTTON_VISIBLE =
new PropertyModel.WritableBooleanPropertyKey();
public static final PropertyModel
.WritableBooleanPropertyKey INCOGNITO_COOKIE_CONTROLS_CARD_VISIBILITY =
new PropertyModel.WritableBooleanPropertyKey();
public static final PropertyModel
.WritableBooleanPropertyKey INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED =
new PropertyModel.WritableBooleanPropertyKey();
public static final PropertyModel.WritableObjectPropertyKey<OnCheckedChangeListener>
INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED_LISTENER =
new PropertyModel.WritableObjectPropertyKey<OnCheckedChangeListener>();
public static final PropertyModel.WritableObjectPropertyKey<IncognitoCookieControlsManager>
INCOGNITO_COOKIE_CONTROLS_MANAGER =
new PropertyModel.WritableObjectPropertyKey<IncognitoCookieControlsManager>();
public static final PropertyModel
.WritableObjectPropertyKey<View.OnClickListener> INCOGNITO_LEARN_MORE_CLICK_LISTENER =
new PropertyModel.WritableObjectPropertyKey<View.OnClickListener>();
......@@ -49,6 +63,8 @@ public class TasksSurfaceProperties {
public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {IS_FAKE_SEARCH_BOX_VISIBLE,
IS_INCOGNITO, IS_INCOGNITO_DESCRIPTION_INITIALIZED, IS_INCOGNITO_DESCRIPTION_VISIBLE,
IS_TAB_CAROUSEL_VISIBLE, IS_VOICE_RECOGNITION_BUTTON_VISIBLE,
INCOGNITO_COOKIE_CONTROLS_CARD_VISIBILITY, INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED,
INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED_LISTENER, INCOGNITO_COOKIE_CONTROLS_MANAGER,
INCOGNITO_LEARN_MORE_CLICK_LISTENER, FAKE_SEARCH_BOX_CLICK_LISTENER,
FAKE_SEARCH_BOX_TEXT_WATCHER, MORE_TABS_CLICK_LISTENER, MV_TILES_VISIBLE,
VOICE_SEARCH_BUTTON_CLICK_LISTENER};
......
......@@ -11,6 +11,7 @@ import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.FrameLayout;
import android.widget.TextView;
......@@ -36,6 +37,9 @@ class TasksView extends CoordinatorLayoutForPointer {
private TextView mSearchBoxText;
private IncognitoDescriptionView mIncognitoDescriptionView;
private View.OnClickListener mIncognitoDescriptionLearnMoreListener;
private boolean mIncognitoCookieControlsCardIsVisible;
private boolean mIncognitoCookieControlsToggleIsChecked;
private OnCheckedChangeListener mIncognitoCookieControlsToggleCheckedListener;
/** Default constructor needed to inflate via XML. */
public TasksView(Context context, AttributeSet attrs) {
......@@ -164,6 +168,13 @@ class TasksView extends CoordinatorLayoutForPointer {
setIncognitoDescriptionLearnMoreClickListener(mIncognitoDescriptionLearnMoreListener);
mIncognitoDescriptionLearnMoreListener = null;
}
setIncognitoCookieControlsCardVisibility(mIncognitoCookieControlsCardIsVisible);
setIncognitoCookieControlsToggleChecked(mIncognitoCookieControlsToggleIsChecked);
if (mIncognitoCookieControlsToggleCheckedListener != null) {
setIncognitoCookieControlsToggleCheckedListener(
mIncognitoCookieControlsToggleCheckedListener);
mIncognitoCookieControlsToggleCheckedListener = null;
}
}
/**
......@@ -185,4 +196,37 @@ class TasksView extends CoordinatorLayoutForPointer {
}
mIncognitoDescriptionView.findViewById(R.id.learn_more).setOnClickListener(listener);
}
/**
* Set the visibility of the cookie controls card on the incognito description.
* @param isVisible Whether it's visible or not.
*/
void setIncognitoCookieControlsCardVisibility(boolean isVisible) {
mIncognitoCookieControlsCardIsVisible = isVisible;
if (mIncognitoDescriptionView != null) {
mIncognitoDescriptionView.showCookieControlsCard(isVisible);
}
}
/**
* Set the toggle on the cookie controls card.
* @param isChecked Whether it's checked or not.
*/
void setIncognitoCookieControlsToggleChecked(boolean isChecked) {
mIncognitoCookieControlsToggleIsChecked = isChecked;
if (mIncognitoDescriptionView != null) {
mIncognitoDescriptionView.setCookieControlsToggle(isChecked);
}
}
/**
* Set the incognito cookie controls toggle checked change listener.
* @param listener The given checked change listener.
*/
void setIncognitoCookieControlsToggleCheckedListener(OnCheckedChangeListener listener) {
mIncognitoCookieControlsToggleCheckedListener = listener;
if (mIncognitoDescriptionView != null) {
mIncognitoDescriptionView.setCookieControlsToggleOnCheckedChangeListener(listener);
}
}
}
......@@ -6,6 +6,10 @@ package org.chromium.chrome.browser.tasks;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_TEXT_WATCHER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_CARD_VISIBILITY;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_MANAGER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_LEARN_MORE_CLICK_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO;
......@@ -29,6 +33,15 @@ class TasksViewBinder {
view.setFakeSearchBoxClickListener(model.get(FAKE_SEARCH_BOX_CLICK_LISTENER));
} else if (propertyKey == FAKE_SEARCH_BOX_TEXT_WATCHER) {
view.setFakeSearchBoxTextWatcher(model.get(FAKE_SEARCH_BOX_TEXT_WATCHER));
} else if (propertyKey == INCOGNITO_COOKIE_CONTROLS_CARD_VISIBILITY) {
view.setIncognitoCookieControlsCardVisibility(
model.get(INCOGNITO_COOKIE_CONTROLS_CARD_VISIBILITY));
} else if (propertyKey == INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED) {
view.setIncognitoCookieControlsToggleChecked(
model.get(INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED));
} else if (propertyKey == INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED_LISTENER) {
view.setIncognitoCookieControlsToggleCheckedListener(
model.get(INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED_LISTENER));
} else if (propertyKey == INCOGNITO_LEARN_MORE_CLICK_LISTENER) {
view.setIncognitoDescriptionLearnMoreClickListener(
model.get(INCOGNITO_LEARN_MORE_CLICK_LISTENER));
......@@ -41,7 +54,13 @@ class TasksViewBinder {
view.initializeIncognitoDescriptionView();
}
} else if (propertyKey == IS_INCOGNITO_DESCRIPTION_VISIBLE) {
view.setIncognitoDescriptionVisibility(model.get(IS_INCOGNITO_DESCRIPTION_VISIBLE));
boolean isVisible = model.get(IS_INCOGNITO_DESCRIPTION_VISIBLE);
if (isVisible) {
// Need to update the service when the description view becomes visible because
// there may be a new off the record profile.
model.get(INCOGNITO_COOKIE_CONTROLS_MANAGER).updateIfNecessary();
}
view.setIncognitoDescriptionVisibility(isVisible);
} else if (propertyKey == IS_TAB_CAROUSEL_VISIBLE) {
view.setTabCarouselVisibility(model.get(IS_TAB_CAROUSEL_VISIBLE));
} else if (propertyKey == IS_VOICE_RECOGNITION_BUTTON_VISIBLE) {
......
......@@ -15,6 +15,7 @@ import static org.junit.Assert.assertTrue;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_TEXT_WATCHER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_MANAGER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_LEARN_MORE_CLICK_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO;
......@@ -36,7 +37,10 @@ import android.view.View;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.chromium.chrome.browser.ntp.IncognitoCookieControlsManager;
import org.chromium.chrome.tab_ui.R;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.components.browser_ui.styles.ChromeColors;
......@@ -57,10 +61,13 @@ public class TasksViewBinderTest extends DummyUiActivityTestCase {
private View.OnClickListener mViewOnClickListener = (v) -> {
mViewClicked.set(true);
};
@Mock
private IncognitoCookieControlsManager mCookieControlsManager;
@Override
public void setUpTest() throws Exception {
super.setUpTest();
MockitoAnnotations.initMocks(this);
TestThreadUtils.runOnUiThreadBlocking(() -> {
mTasksView = (TasksView) getActivity().getLayoutInflater().inflate(
......@@ -214,6 +221,7 @@ public class TasksViewBinderTest extends DummyUiActivityTestCase {
assertFalse(isViewVisible(R.id.incognito_description_layout_stub));
TestThreadUtils.runOnUiThreadBlocking(() -> {
mTasksViewPropertyModel.set(INCOGNITO_COOKIE_CONTROLS_MANAGER, mCookieControlsManager);
mTasksViewPropertyModel.set(IS_INCOGNITO_DESCRIPTION_INITIALIZED, true);
mTasksViewPropertyModel.set(IS_INCOGNITO_DESCRIPTION_VISIBLE, true);
});
......
......@@ -15,6 +15,7 @@ import static org.mockito.Mockito.verify;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_TEXT_WATCHER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_MANAGER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_LEARN_MORE_CLICK_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_INITIALIZED;
......@@ -40,6 +41,7 @@ import org.robolectric.annotation.Config;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.chrome.browser.ntp.FakeboxDelegate;
import org.chromium.chrome.browser.ntp.IncognitoCookieControlsManager;
import org.chromium.chrome.browser.omnibox.LocationBar;
import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler;
import org.chromium.ui.modelutil.PropertyModel;
......@@ -58,6 +60,8 @@ public class TasksSurfaceMediatorUnitTest {
private VoiceRecognitionHandler mVoiceRecognitionHandler;
@Mock
private View.OnClickListener mLearnMoreOnClickListener;
@Mock
private IncognitoCookieControlsManager mCookieControlsManager;
@Captor
private ArgumentCaptor<View.OnClickListener> mFakeboxClickListenerCaptor;
@Captor
......@@ -66,14 +70,16 @@ public class TasksSurfaceMediatorUnitTest {
private ArgumentCaptor<View.OnClickListener> mVoiceSearchButtonClickListenerCaptor;
@Captor
private ArgumentCaptor<View.OnClickListener> mLearnMoreOnClickListenerCaptor;
@Captor
private ArgumentCaptor<IncognitoCookieControlsManager> mCookieControlsManagerCaptor;
@Before
public void setUp() {
RecordUserAction.setDisabledForTests(true);
MockitoAnnotations.initMocks(this);
mMediator = new TasksSurfaceMediator(
mPropertyModel, mFakeboxDelegate, mLearnMoreOnClickListener, true);
mMediator = new TasksSurfaceMediator(mPropertyModel, mFakeboxDelegate,
mLearnMoreOnClickListener, mCookieControlsManager, true);
}
@After
......@@ -94,6 +100,8 @@ public class TasksSurfaceMediatorUnitTest {
mVoiceSearchButtonClickListenerCaptor.capture());
verify(mPropertyModel).set(eq(IS_FAKE_SEARCH_BOX_VISIBLE), eq(true));
verify(mPropertyModel).set(eq(IS_VOICE_RECOGNITION_BUTTON_VISIBLE), eq(false));
verify(mPropertyModel)
.set(eq(INCOGNITO_COOKIE_CONTROLS_MANAGER), mCookieControlsManagerCaptor.capture());
verify(mPropertyModel)
.set(eq(INCOGNITO_LEARN_MORE_CLICK_LISTENER),
mLearnMoreOnClickListenerCaptor.capture());
......
// Copyright 2020 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.ntp;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import org.chromium.base.ObserverList;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.settings.website.CookieControlsServiceBridge;
import org.chromium.chrome.browser.settings.website.CookieControlsServiceBridge.CookieControlsServiceObserver;
/**
* A manager for cookie controls related behaviour on the incognito description view.
* This class communicates with a native CookieControlsService and provides
* updates to its listening observers. In addition, it is expected that this
* class will be registered as an OnCheckedChangeListener for a corresponding
* cookie controls view.
*/
public class IncognitoCookieControlsManager
implements CookieControlsServiceObserver, OnCheckedChangeListener {
/**
* Interface for a class that wants to receive updates from this manager.
*/
public interface Observer {
/**
* Notifies that this manager has received an update.
* @param checked A boolean indicating whether the toggle indicating third-party cookies are
* currently being blocked should be checked or not.
* @param enforced A boolean indicating if third-party cookies being blocked is currently
* enforced by policy/cookie settings or not.
*/
void onUpdate(boolean checked, boolean enforced);
}
private CookieControlsServiceBridge mServiceBridge;
private final ObserverList<Observer> mObservers = new ObserverList<>();
private boolean mIsInitialized;
private boolean mShowCard;
/**
* Initializes the IncognitoCookieControlsManager explicitly.
*/
public void initialize() {
if (mIsInitialized) return;
if (ChromeFeatureList.isInitialized()
&& ChromeFeatureList.isEnabled(ChromeFeatureList.IMPROVED_COOKIE_CONTROLS)) {
mServiceBridge = new CookieControlsServiceBridge(this);
mShowCard = true;
}
mIsInitialized = true;
}
/**
* @param observer An observer to be notified of changes.
*/
public void addObserver(Observer observer) {
mObservers.addObserver(observer);
}
/**
* @param observer The observer to remove.
*/
public void removeObserver(Observer observer) {
mObservers.removeObserver(observer);
}
/**
* @return a boolean indicating if the card should be visible or not.
*/
public boolean shouldShowCookieControlsCard() {
return mShowCard;
}
/**
* Tells the bridge to update itself if necessary.
*/
public void updateIfNecessary() {
if (mShowCard) mServiceBridge.updateServiceIfNecessary();
}
@Override
public void sendCookieControlsUIChanges(boolean checked, boolean enforced) {
for (Observer obs : mObservers) {
obs.onUpdate(checked, enforced);
}
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mShowCard && (buttonView.getId() == R.id.cookie_controls_card_toggle)) {
mServiceBridge.handleCookieControlsToggleChanged(isChecked);
}
}
}
......@@ -26,7 +26,6 @@ import androidx.annotation.StringRes;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.ui.text.NoUnderlineClickableSpan;
import org.chromium.ui.text.SpanApplier;
import org.chromium.ui.widget.ChromeBulletSpan;
......@@ -121,7 +120,6 @@ public class IncognitoDescriptionView extends LinearLayout {
adjustIcon();
adjustLayout();
adjustLearnMore();
adjustCookieControlsCard();
}
/**
......@@ -291,14 +289,11 @@ public class IncognitoDescriptionView extends LinearLayout {
mSubtitle.setMovementMethod(LinkMovementMethod.getInstance());
}
/** Adjust the Cookie Controls Card. */
private void adjustCookieControlsCard() {
if (!ChromeFeatureList.isInitialized()
|| !ChromeFeatureList.isEnabled(ChromeFeatureList.IMPROVED_COOKIE_CONTROLS)) {
mCookieControlsCard.setVisibility(View.GONE);
return;
}
mCookieControlsCard.setVisibility(View.VISIBLE);
/**
* Adjust the Cookie Controls Card.
* @param showCard A boolean indicating if the card should be visible or not.
*/
public void showCookieControlsCard(boolean showCard) {
mCookieControlsCard.setVisibility(showCard ? View.VISIBLE : View.GONE);
}
}
......@@ -18,13 +18,10 @@ import org.chromium.chrome.R;
import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider;
import org.chromium.chrome.browser.help.HelpAndFeedback;
import org.chromium.chrome.browser.ntp.IncognitoNewTabPageView.IncognitoNewTabPageManager;
import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.ui.native_page.BasicNativePage;
import org.chromium.chrome.browser.ui.native_page.NativePageHost;
import org.chromium.chrome.browser.vr.VrModuleProvider;
import org.chromium.components.content_settings.CookieControlsMode;
import org.chromium.components.embedder_support.util.UrlConstants;
/**
......@@ -40,6 +37,8 @@ public class IncognitoNewTabPage
private boolean mIsLoaded;
private IncognitoNewTabPageManager mIncognitoNewTabPageManager;
private IncognitoCookieControlsManager mCookieControlsManager;
private IncognitoCookieControlsManager.Observer mCookieControlsObserver;
private final int mIncognitoNTPBackgroundColor;
......@@ -76,19 +75,31 @@ public class IncognitoNewTabPage
}
@Override
public void setThirdPartyCookieBlocking(boolean enable) {
@CookieControlsMode
int new_mode = enable ? CookieControlsMode.INCOGNITO_ONLY : CookieControlsMode.OFF;
PrefServiceBridge.getInstance().setInteger(Pref.COOKIE_CONTROLS_MODE, new_mode);
public void initCookieControlsManager() {
mCookieControlsManager = new IncognitoCookieControlsManager();
mCookieControlsManager.initialize();
mIncognitoNewTabPageView.setIncognitoCookieControlsCardVisibility(
mCookieControlsManager.shouldShowCookieControlsCard());
mCookieControlsObserver = new IncognitoCookieControlsManager.Observer() {
@Override
public void onUpdate(boolean checked, boolean enforced) {
// TODO(crbug.com/1040091): use enforced to support the case where this
// toggle is managed by organization or the normal 3PC blocking setting and
// update the UI accordingly.
mIncognitoNewTabPageView.setIncognitoCookieControlsToggleChecked(checked);
}
};
mCookieControlsManager.addObserver(mCookieControlsObserver);
mIncognitoNewTabPageView.setIncognitoCookieControlsToggleCheckedListener(
mCookieControlsManager);
mCookieControlsManager.updateIfNecessary();
}
@Override
public boolean shouldBlockThirdPartyCookies() {
// TODO(eokoyomon): add methods to CookieControlsBridge to implement this in order
// to be consistent with desktop cookie settings.
return PrefServiceBridge.getInstance().getBoolean(Pref.BLOCK_THIRD_PARTY_COOKIES)
|| (PrefServiceBridge.getInstance().getInteger(Pref.COOKIE_CONTROLS_MODE)
!= CookieControlsMode.OFF);
public void destroy() {
if (mCookieControlsManager != null) {
mCookieControlsManager.removeObserver(mCookieControlsObserver);
}
}
@Override
......@@ -131,6 +142,7 @@ public class IncognitoNewTabPage
public void destroy() {
assert !ViewCompat
.isAttachedToWindow(getView()) : "Destroy called before removed from window";
mIncognitoNewTabPageManager.destroy();
super.destroy();
}
......
......@@ -8,7 +8,6 @@ import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.FrameLayout;
......@@ -37,18 +36,14 @@ public class IncognitoNewTabPageView extends FrameLayout {
void loadIncognitoLearnMore();
/**
* Enables/disables cookie controls mode as set from incognito NTP. By default
* nothing happens.
* @param enable A boolean specifying the state of third party cookie blocking in
* incognito. True will enable third-party cookie blocking in incognito and false
* will disable this feature.
* Initializes the cookie controls manager for interaction with the cookie controls toggle.
* */
void setThirdPartyCookieBlocking(boolean enable);
void initCookieControlsManager();
/**
* Returns whether third-party cookies are currently being blocked.
* Cleans up the manager after it is finished being used.
* */
boolean shouldBlockThirdPartyCookies();
void destroy();
/**
* Called when the NTP has completely finished loading (all views will be inflated
......@@ -84,13 +79,6 @@ public class IncognitoNewTabPageView extends FrameLayout {
mManager.loadIncognitoLearnMore();
}
});
mDescriptionView.setCookieControlsToggleOnCheckedChangeListener(
new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mManager.setThirdPartyCookieBlocking(isChecked);
}
});
}
@Override
......@@ -109,7 +97,7 @@ public class IncognitoNewTabPageView extends FrameLayout {
*/
void initialize(IncognitoNewTabPageManager manager) {
mManager = manager;
mDescriptionView.setCookieControlsToggle(mManager.shouldBlockThirdPartyCookies());
mManager.initCookieControlsManager();
}
/** @return The IncognitoNewTabPageManager associated with this IncognitoNewTabPageView. */
......@@ -139,4 +127,28 @@ public class IncognitoNewTabPageView extends FrameLayout {
mSnapshotHeight = getHeight();
mSnapshotScrollY = mScrollView.getScrollY();
}
/**
* Set the visibility of the cookie controls card on the incognito description.
* @param isVisible Whether it's visible or not.
*/
void setIncognitoCookieControlsCardVisibility(boolean isVisible) {
mDescriptionView.showCookieControlsCard(isVisible);
}
/**
* Set the toggle on the cookie controls card.
* @param isChecked Whether it's checked or not.
*/
void setIncognitoCookieControlsToggleChecked(boolean isChecked) {
mDescriptionView.setCookieControlsToggle(isChecked);
}
/**
* Set the incognito cookie controls toggle checked change listener.
* @param listener The given checked change listener.
*/
void setIncognitoCookieControlsToggleCheckedListener(OnCheckedChangeListener listener) {
mDescriptionView.setCookieControlsToggleOnCheckedChangeListener(listener);
}
}
......@@ -6,7 +6,6 @@ package org.chromium.chrome.browser.settings.website;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.profiles.Profile;
/**
* Communicates between CookieControlsService (C++ backend) and observers in the Incognito NTP Java
......@@ -34,12 +33,11 @@ public class CookieControlsServiceBridge {
/**
* Initializes a CookieControlsServiceBridge instance.
* @param observer An observer to call with updates from the cookie controls service.
* @param profile The Profile instance to observe.
*/
public CookieControlsServiceBridge(CookieControlsServiceObserver observer, Profile profile) {
public CookieControlsServiceBridge(CookieControlsServiceObserver observer) {
mObserver = observer;
mNativeCookieControlsServiceBridge = CookieControlsServiceBridgeJni.get().init(
CookieControlsServiceBridge.this, profile);
mNativeCookieControlsServiceBridge =
CookieControlsServiceBridgeJni.get().init(CookieControlsServiceBridge.this);
}
/**
......@@ -63,6 +61,14 @@ public class CookieControlsServiceBridge {
mNativeCookieControlsServiceBridge, enable);
}
/**
* Starts a service to observe current profile.
*/
public void updateServiceIfNecessary() {
CookieControlsServiceBridgeJni.get().updateServiceIfNecessary(
mNativeCookieControlsServiceBridge);
}
@CalledByNative
private void sendCookieControlsUIChanges(boolean checked, boolean enforced) {
mObserver.sendCookieControlsUIChanges(checked, enforced);
......@@ -70,9 +76,10 @@ public class CookieControlsServiceBridge {
@NativeMethods
interface Natives {
long init(CookieControlsServiceBridge caller, Profile profile);
long init(CookieControlsServiceBridge caller);
void destroy(long nativeCookieControlsServiceBridge, CookieControlsServiceBridge caller);
void handleCookieControlsToggleChanged(
long nativeCookieControlsServiceBridge, boolean enable);
void updateServiceIfNecessary(long nativeCookieControlsServiceBridge);
}
}
......@@ -21,7 +21,6 @@ import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.test.ChromeActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
......@@ -99,15 +98,19 @@ public class CookieControlsServiceBridgeTest {
final String url = mTestServer.getURL("/chrome/test/data/android/cookie.html");
Tab tab = mActivityTestRule.loadUrlInNewTab(url, true); // incognito tab
// Test that the toggle switches on.
boolean expectedChecked = true;
mChecked = false;
int currentCallCount = mCallbackHelper.getCallCount();
// Create cookie settings bridge and wait for desired callbacks.
TestThreadUtils.runOnUiThreadBlocking(() -> {
mCookieControlsServiceBridge = new CookieControlsServiceBridge(
mCallbackHandler, Profile.fromWebContents(tab.getWebContents()));
mCookieControlsServiceBridge = new CookieControlsServiceBridge(mCallbackHandler);
mCookieControlsServiceBridge.updateServiceIfNecessary();
});
// Initial callback after the bridge is created.
mCallbackHelper.waitForCallback(currentCallCount, 1);
// Test that the toggle switches on.
boolean expectedChecked = true;
mChecked = false;
currentCallCount = mCallbackHelper.getCallCount();
setCookieControlsMode(CookieControlsMode.INCOGNITO_ONLY);
mCallbackHelper.waitForCallback(currentCallCount, 1);
Assert.assertEquals(expectedChecked, mChecked);
......@@ -148,8 +151,8 @@ public class CookieControlsServiceBridgeTest {
int currentCallCount = mCallbackHelper.getCallCount();
// Create cookie controls service bridge and wait for desired callbacks.
TestThreadUtils.runOnUiThreadBlocking(() -> {
mCookieControlsServiceBridge = new CookieControlsServiceBridge(
mCallbackHandler, Profile.fromWebContents(tab.getWebContents()));
mCookieControlsServiceBridge = new CookieControlsServiceBridge(mCallbackHandler);
mCookieControlsServiceBridge.updateServiceIfNecessary();
mCookieControlsServiceBridge.handleCookieControlsToggleChanged(true);
......@@ -157,7 +160,8 @@ public class CookieControlsServiceBridgeTest {
PrefServiceBridge.getInstance().getInteger(Pref.COOKIE_CONTROLS_MODE),
CookieControlsMode.INCOGNITO_ONLY);
});
mCallbackHelper.waitForCallback(currentCallCount, 1);
// One initial callback after creation, then another after the toggle change.
mCallbackHelper.waitForCallback(currentCallCount, 2);
Assert.assertEquals(expectedChecked, mChecked);
}
}
......@@ -7,7 +7,7 @@
#include <memory>
#include "chrome/android/chrome_jni_headers/CookieControlsServiceBridge_jni.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_android.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/cookie_controls/cookie_controls_service.h"
#include "chrome/browser/ui/cookie_controls/cookie_controls_service_factory.h"
......@@ -15,12 +15,20 @@ using base::android::JavaParamRef;
CookieControlsServiceBridge::CookieControlsServiceBridge(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& jprofile)
: jobject_(obj) {
Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
service_ = CookieControlsServiceFactory::GetForProfile(profile);
service_->AddObserver(this);
const JavaParamRef<jobject>& obj)
: jobject_(obj) {}
void CookieControlsServiceBridge::UpdateServiceIfNecessary() {
Profile* profile =
ProfileManager::GetLastUsedProfile()->GetOffTheRecordProfile();
CookieControlsService* new_service =
CookieControlsServiceFactory::GetForProfile(profile);
// Update the service only if it is for a new profile
if (new_service != service_) {
service_ = new_service;
service_->AddObserver(this);
SendCookieControlsUIChanges();
}
}
void CookieControlsServiceBridge::HandleCookieControlsToggleChanged(
......@@ -29,6 +37,10 @@ void CookieControlsServiceBridge::HandleCookieControlsToggleChanged(
service_->HandleCookieControlsToggleChanged(checked);
}
void CookieControlsServiceBridge::UpdateServiceIfNecessary(JNIEnv* env) {
UpdateServiceIfNecessary();
}
void CookieControlsServiceBridge::SendCookieControlsUIChanges() {
bool checked = service_->GetToggleCheckedValue();
bool enforced = service_->ShouldEnforceCookieControls();
......@@ -54,8 +66,6 @@ void CookieControlsServiceBridge::Destroy(JNIEnv* env,
static jlong JNI_CookieControlsServiceBridge_Init(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& jprofile) {
return reinterpret_cast<intptr_t>(
new CookieControlsServiceBridge(env, obj, jprofile));
const JavaParamRef<jobject>& obj) {
return reinterpret_cast<intptr_t>(new CookieControlsServiceBridge(env, obj));
}
......@@ -12,10 +12,8 @@
// in the Incognito NTP Java UI.
class CookieControlsServiceBridge : public CookieControlsService::Observer {
public:
CookieControlsServiceBridge(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& jprofile);
CookieControlsServiceBridge(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
~CookieControlsServiceBridge() override;
......@@ -24,6 +22,8 @@ class CookieControlsServiceBridge : public CookieControlsService::Observer {
void HandleCookieControlsToggleChanged(JNIEnv* env, jboolean checked);
void UpdateServiceIfNecessary(JNIEnv* env);
// CookieControlsService::Observer
void OnThirdPartyCookieBlockingPrefChanged() override;
void OnThirdPartyCookieBlockingPolicyChanged() override;
......@@ -32,6 +32,8 @@ class CookieControlsServiceBridge : public CookieControlsService::Observer {
// Updates cookie controls UI when third-party cookie blocking setting has
// changed.
void SendCookieControlsUIChanges();
// Starts a service to observe the current profile.
void UpdateServiceIfNecessary();
CookieControlsService* service_;
base::android::ScopedJavaGlobalRef<jobject> jobject_;
......
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