Commit f329fe80 authored by Christian Dullweber's avatar Christian Dullweber Committed by Commit Bot

Add cookie controls UI to PageInfo

Add a toggle and description for 3p cookie blocking to PageInfo.

Screenshot in https://crbug.com/1040091#c9
Note: Placement in PageInfo is temporary, see slides in bug for future
plans.

Bug: 1040091
Change-Id: Ibda0d763d71c115054129d3131ff9400107a0504
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2014935
Commit-Queue: Christian Dullweber <dullweber@chromium.org>
Reviewed-by: default avatarElly Fong-Jones <ellyjones@chromium.org>
Reviewed-by: default avatarBoris Sazonov <bsazonov@chromium.org>
Cr-Commit-Position: refs/heads/master@{#741396}
parent cfe0df76
...@@ -1208,6 +1208,7 @@ chrome_java_sources = [ ...@@ -1208,6 +1208,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/page_info/CertificateChainHelper.java", "java/src/org/chromium/chrome/browser/page_info/CertificateChainHelper.java",
"java/src/org/chromium/chrome/browser/page_info/CertificateViewer.java", "java/src/org/chromium/chrome/browser/page_info/CertificateViewer.java",
"java/src/org/chromium/chrome/browser/page_info/ConnectionInfoPopup.java", "java/src/org/chromium/chrome/browser/page_info/ConnectionInfoPopup.java",
"java/src/org/chromium/chrome/browser/page_info/CookieControlsView.java",
"java/src/org/chromium/chrome/browser/page_info/PageInfoController.java", "java/src/org/chromium/chrome/browser/page_info/PageInfoController.java",
"java/src/org/chromium/chrome/browser/page_info/PageInfoDialog.java", "java/src/org/chromium/chrome/browser/page_info/PageInfoDialog.java",
"java/src/org/chromium/chrome/browser/page_info/PageInfoView.java", "java/src/org/chromium/chrome/browser/page_info/PageInfoView.java",
......
...@@ -297,6 +297,7 @@ chrome_test_java_sources = [ ...@@ -297,6 +297,7 @@ chrome_test_java_sources = [
"javatests/src/org/chromium/chrome/browser/omnibox/suggestions/VoiceSuggestionProviderTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/suggestions/VoiceSuggestionProviderTest.java",
"javatests/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandlerTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandlerTest.java",
"javatests/src/org/chromium/chrome/browser/page_info/ConnectionInfoPopupTest.java", "javatests/src/org/chromium/chrome/browser/page_info/ConnectionInfoPopupTest.java",
"javatests/src/org/chromium/chrome/browser/page_info/CookieControlsViewTest.java",
"javatests/src/org/chromium/chrome/browser/page_info/PageInfoControllerTest.java", "javatests/src/org/chromium/chrome/browser/page_info/PageInfoControllerTest.java",
"javatests/src/org/chromium/chrome/browser/partnercustomizations/BasePartnerBrowserCustomizationIntegrationTestRule.java", "javatests/src/org/chromium/chrome/browser/partnercustomizations/BasePartnerBrowserCustomizationIntegrationTestRule.java",
"javatests/src/org/chromium/chrome/browser/partnercustomizations/BasePartnerBrowserCustomizationUnitTestRule.java", "javatests/src/org/chromium/chrome/browser/partnercustomizations/BasePartnerBrowserCustomizationUnitTestRule.java",
......
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/new_tab_otr_third_party_cookie"
android:textAppearance="@style/TextAppearance.TextLarge.Primary" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="3dp"
android:paddingTop="8dp"
android:text="@string/new_tab_otr_third_party_cookie_sublabel"
android:textAppearance="@style/TextAppearance.TextMedium.Primary" />
</LinearLayout>
<android.support.v7.widget.SwitchCompat
android:id="@+id/cookie_controls_block_cookies_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" />
</LinearLayout>
<TextView
android:id="@+id/cookie_controls_blocked_cookies_text"
android:layout_width="match_parent"
android:paddingTop="16dp"
android:layout_height="wrap_content"
android:drawablePadding="16dp"
android:drawableStart="@drawable/permission_cookie"
android:text="@string/cookie_controls_blocked_cookies"
android:textAppearance="@style/TextAppearance.TextMedium.Primary" />
</merge>
...@@ -105,6 +105,14 @@ ...@@ -105,6 +105,14 @@
android:paddingEnd="@dimen/page_info_popup_padding_sides" > android:paddingEnd="@dimen/page_info_popup_padding_sides" >
</LinearLayout> </LinearLayout>
<org.chromium.chrome.browser.page_info.CookieControlsView
android:id="@+id/page_info_cookie_controls_view"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:paddingTop="12dp"
android:paddingStart="@dimen/page_info_popup_padding_sides"
android:paddingEnd="@dimen/page_info_popup_padding_sides"/>
<org.chromium.ui.widget.ButtonCompat <org.chromium.ui.widget.ButtonCompat
android:id="@+id/page_info_site_settings_button" android:id="@+id/page_info_site_settings_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
......
// 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.page_info;
import android.content.Context;
import android.support.v7.widget.SwitchCompat;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.chromium.base.Callback;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.settings.website.CookieControlsControllerStatus;
/**
* View showing a toggle and a description for third-party cookie blocking for a site.
*/
public class CookieControlsView
extends LinearLayout implements CompoundButton.OnCheckedChangeListener {
private final SwitchCompat mSwitch;
private final TextView mBlockedText;
private boolean mLastSwitchState;
private CookieControlsParams mParams;
/** Parameters to configure the cookie controls view. */
public static class CookieControlsParams {
// Called when the cookie controls UI is closed.
public Runnable onUiClosingCallback;
// Called when the toggle controlling third-party cookie blocking changes.
public Callback<Boolean> onCheckedChangedCallback;
}
public CookieControlsView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setOrientation(VERTICAL);
setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
LayoutInflater.from(context).inflate(R.layout.cookie_controls_view, this, true);
mBlockedText = findViewById(R.id.cookie_controls_blocked_cookies_text);
mSwitch = findViewById(R.id.cookie_controls_block_cookies_switch);
mSwitch.setOnCheckedChangeListener(this);
}
void setParams(CookieControlsParams params) {
mParams = params;
}
// FrameLayout:
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mParams.onUiClosingCallback.run();
}
public void setCookieBlockingStatus(@CookieControlsControllerStatus int status) {
mLastSwitchState = status == CookieControlsControllerStatus.ENABLED;
mSwitch.setChecked(mLastSwitchState);
mSwitch.setEnabled(status != CookieControlsControllerStatus.DISABLED);
}
public void setBlockedCookiesCount(int blockedCookies) {
mBlockedText.setText(String.format(
getContext().getString(R.string.cookie_controls_blocked_cookies), blockedCookies));
}
// CompoundButton.OnCheckedChangeListener:
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked == mLastSwitchState) return;
assert buttonView == mSwitch;
mParams.onCheckedChangedCallback.onResult(isChecked);
}
}
...@@ -40,6 +40,8 @@ import org.chromium.chrome.browser.previews.PreviewsAndroidBridge; ...@@ -40,6 +40,8 @@ import org.chromium.chrome.browser.previews.PreviewsAndroidBridge;
import org.chromium.chrome.browser.previews.PreviewsUma; import org.chromium.chrome.browser.previews.PreviewsUma;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.settings.website.ContentSettingValues; import org.chromium.chrome.browser.settings.website.ContentSettingValues;
import org.chromium.chrome.browser.settings.website.CookieControlsBridge;
import org.chromium.chrome.browser.settings.website.CookieControlsControllerStatus;
import org.chromium.chrome.browser.ssl.SecurityStateModel; import org.chromium.chrome.browser.ssl.SecurityStateModel;
import org.chromium.chrome.browser.util.UrlUtilities; import org.chromium.chrome.browser.util.UrlUtilities;
import org.chromium.chrome.browser.vr.VrModuleProvider; import org.chromium.chrome.browser.vr.VrModuleProvider;
...@@ -71,8 +73,9 @@ import java.util.Date; ...@@ -71,8 +73,9 @@ import java.util.Date;
/** /**
* Java side of Android implementation of the page info UI. * Java side of Android implementation of the page info UI.
*/ */
public class PageInfoController public class PageInfoController implements ModalDialogProperties.Controller,
implements ModalDialogProperties.Controller, SystemSettingsActivityRequiredListener { SystemSettingsActivityRequiredListener,
CookieControlsBridge.CookieControlsObserver {
@IntDef({OpenedFromSource.MENU, OpenedFromSource.TOOLBAR, OpenedFromSource.VR}) @IntDef({OpenedFromSource.MENU, OpenedFromSource.TOOLBAR, OpenedFromSource.VR})
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
public @interface OpenedFromSource { public @interface OpenedFromSource {
...@@ -144,6 +147,9 @@ public class PageInfoController ...@@ -144,6 +147,9 @@ public class PageInfoController
// task is pending. // task is pending.
private Runnable mPendingRunAfterDismissTask; private Runnable mPendingRunAfterDismissTask;
// Bridge updating the CookieControlsView when cookie settings change.
private CookieControlsBridge mBridge;
/** /**
* Creates the PageInfoController, but does not display it. Also initializes the corresponding * Creates the PageInfoController, but does not display it. Also initializes the corresponding
* C++ object and saves a pointer to it. * C++ object and saves a pointer to it.
...@@ -155,7 +161,7 @@ public class PageInfoController ...@@ -155,7 +161,7 @@ public class PageInfoController
* @param offlinePageState State of the WebContents showing offline page. * @param offlinePageState State of the WebContents showing offline page.
* @param previewPageState State of the WebContents showing the preview. * @param previewPageState State of the WebContents showing the preview.
* @param publisher The name of the content publisher, if any. * @param publisher The name of the content publisher, if any.
* @param offlinePageLoadUrlDelegate {@link offlinePageLoadUrlDelegate} * @param offlinePageLoadUrlDelegate {@link OfflinePageLoadUrlDelegate}
* defined by the caller. * defined by the caller.
*/ */
protected PageInfoController(ChromeActivity activity, WebContents webContents, protected PageInfoController(ChromeActivity activity, WebContents webContents,
...@@ -167,6 +173,7 @@ public class PageInfoController ...@@ -167,6 +173,7 @@ public class PageInfoController
mSecurityLevel = securityLevel; mSecurityLevel = securityLevel;
mOfflinePageState = offlinePageState; mOfflinePageState = offlinePageState;
mPreviewPageState = previewPageState; mPreviewPageState = previewPageState;
Profile profile = Profile.fromWebContents(webContents);
PageInfoViewParams viewParams = new PageInfoViewParams(); PageInfoViewParams viewParams = new PageInfoViewParams();
if (mOfflinePageState != OfflinePageState.NOT_OFFLINE_PAGE) { if (mOfflinePageState != OfflinePageState.NOT_OFFLINE_PAGE) {
...@@ -207,7 +214,7 @@ public class PageInfoController ...@@ -207,7 +214,7 @@ public class PageInfoController
if (mSecurityLevel == ConnectionSecurityLevel.SECURE) { if (mSecurityLevel == ConnectionSecurityLevel.SECURE) {
OmniboxUrlEmphasizer.EmphasizeComponentsResponse emphasizeResponse = OmniboxUrlEmphasizer.EmphasizeComponentsResponse emphasizeResponse =
OmniboxUrlEmphasizer.parseForEmphasizeComponents( OmniboxUrlEmphasizer.parseForEmphasizeComponents(
Profile.fromWebContents(webContents), displayUrlBuilder.toString()); profile, displayUrlBuilder.toString());
if (emphasizeResponse.schemeLength > 0) { if (emphasizeResponse.schemeLength > 0) {
displayUrlBuilder.setSpan( displayUrlBuilder.setSpan(
new TextAppearanceSpan(activity, R.style.TextAppearance_RobotoMediumStyle), new TextAppearanceSpan(activity, R.style.TextAppearance_RobotoMediumStyle),
...@@ -216,12 +223,11 @@ public class PageInfoController ...@@ -216,12 +223,11 @@ public class PageInfoController
} }
final boolean useDarkColors = !activity.getNightModeStateProvider().isInNightMode(); final boolean useDarkColors = !activity.getNightModeStateProvider().isInNightMode();
OmniboxUrlEmphasizer.emphasizeUrl(displayUrlBuilder, activity.getResources(), OmniboxUrlEmphasizer.emphasizeUrl(displayUrlBuilder, activity.getResources(), profile,
Profile.fromWebContents(webContents), mSecurityLevel, mIsInternalPage, mSecurityLevel, mIsInternalPage, useDarkColors, /*emphasizeScheme=*/true);
useDarkColors, /*emphasizeScheme=*/true);
viewParams.url = displayUrlBuilder; viewParams.url = displayUrlBuilder;
viewParams.urlOriginLength = OmniboxUrlEmphasizer.getOriginEndIndex( viewParams.urlOriginLength =
displayUrlBuilder.toString(), Profile.fromWebContents(webContents)); OmniboxUrlEmphasizer.getOriginEndIndex(displayUrlBuilder.toString(), profile);
if (SiteSettingsHelper.isSiteSettingsAvailable(webContents)) { if (SiteSettingsHelper.isSiteSettingsAvailable(webContents)) {
viewParams.siteSettingsButtonClickCallback = () -> { viewParams.siteSettingsButtonClickCallback = () -> {
...@@ -231,8 +237,10 @@ public class PageInfoController ...@@ -231,8 +237,10 @@ public class PageInfoController
SiteSettingsHelper.showSiteSettings(activity, mFullUrl); SiteSettingsHelper.showSiteSettings(activity, mFullUrl);
}); });
}; };
viewParams.cookieControlsShown = CookieControlsBridge.isCookieControlsEnabled(profile);
} else { } else {
viewParams.siteSettingsButtonShown = false; viewParams.siteSettingsButtonShown = false;
viewParams.cookieControlsShown = false;
} }
initPreviewUiParams(activity, viewParams); initPreviewUiParams(activity, viewParams);
...@@ -273,6 +281,14 @@ public class PageInfoController ...@@ -273,6 +281,14 @@ public class PageInfoController
mPermissionParamsListBuilder = new PermissionParamsListBuilder( mPermissionParamsListBuilder = new PermissionParamsListBuilder(
activity, mWindowAndroid, mFullUrl, this, mView::setPermissions); activity, mWindowAndroid, mFullUrl, this, mView::setPermissions);
mBridge = new CookieControlsBridge(this, webContents);
CookieControlsView.CookieControlsParams cookieControlsParams =
new CookieControlsView.CookieControlsParams();
cookieControlsParams.onUiClosingCallback = mBridge::onUiClosing;
cookieControlsParams.onCheckedChangedCallback =
mBridge::setThirdPartyCookieBlockingEnabledForSite;
mView.getCookieControlsView().setParams(cookieControlsParams);
// This needs to come after other member initialization. // This needs to come after other member initialization.
mNativePageInfoController = PageInfoControllerJni.get().init(this, mWebContents); mNativePageInfoController = PageInfoControllerJni.get().init(this, mWebContents);
mWebContentsObserver = new WebContentsObserver(webContents) { mWebContentsObserver = new WebContentsObserver(webContents) {
...@@ -586,6 +602,16 @@ public class PageInfoController ...@@ -586,6 +602,16 @@ public class PageInfoController
offlinePageLoadUrlDelegate); offlinePageLoadUrlDelegate);
} }
@Override
public void onCookieBlockingStatusChanged(int status) {
mView.getCookieControlsView().setCookieBlockingStatus(status);
}
@Override
public void onBlockedCookiesCountChanged(@CookieControlsControllerStatus int blockedCookies) {
mView.getCookieControlsView().setBlockedCookiesCount(blockedCookies);
}
@NativeMethods @NativeMethods
interface Natives { interface Natives {
long init(PageInfoController controller, WebContents webContents); long init(PageInfoController controller, WebContents webContents);
......
...@@ -161,6 +161,7 @@ public class PageInfoView extends FrameLayout implements OnClickListener, OnLong ...@@ -161,6 +161,7 @@ public class PageInfoView extends FrameLayout implements OnClickListener, OnLong
public boolean openOnlineButtonShown = true; public boolean openOnlineButtonShown = true;
public boolean previewUIShown = true; public boolean previewUIShown = true;
public boolean separatorShown = true; public boolean separatorShown = true;
public boolean cookieControlsShown = true;
public Runnable urlTitleClickCallback; public Runnable urlTitleClickCallback;
public Runnable urlTitleLongClickCallback; public Runnable urlTitleLongClickCallback;
...@@ -203,6 +204,7 @@ public class PageInfoView extends FrameLayout implements OnClickListener, OnLong ...@@ -203,6 +204,7 @@ public class PageInfoView extends FrameLayout implements OnClickListener, OnLong
private final TextView mPreviewStaleTimestamp; private final TextView mPreviewStaleTimestamp;
private final TextView mPreviewLoadOriginal; private final TextView mPreviewLoadOriginal;
private final LinearLayout mPermissionsList; private final LinearLayout mPermissionsList;
private final CookieControlsView mCookieControlsView;
private final View mSeparator; private final View mSeparator;
private final Button mInstantAppButton; private final Button mInstantAppButton;
private final Button mSiteSettingsButton; private final Button mSiteSettingsButton;
...@@ -221,6 +223,8 @@ public class PageInfoView extends FrameLayout implements OnClickListener, OnLong ...@@ -221,6 +223,8 @@ public class PageInfoView extends FrameLayout implements OnClickListener, OnLong
mPreviewStaleTimestamp = (TextView) findViewById(R.id.page_info_stale_preview_timestamp); mPreviewStaleTimestamp = (TextView) findViewById(R.id.page_info_stale_preview_timestamp);
mPreviewLoadOriginal = (TextView) findViewById(R.id.page_info_preview_load_original); mPreviewLoadOriginal = (TextView) findViewById(R.id.page_info_preview_load_original);
mPermissionsList = (LinearLayout) findViewById(R.id.page_info_permissions_list); mPermissionsList = (LinearLayout) findViewById(R.id.page_info_permissions_list);
mCookieControlsView =
(CookieControlsView) findViewById(R.id.page_info_cookie_controls_view);
mSeparator = (View) findViewById(R.id.page_info_separator); mSeparator = (View) findViewById(R.id.page_info_separator);
mInstantAppButton = (Button) findViewById(R.id.page_info_instant_app_button); mInstantAppButton = (Button) findViewById(R.id.page_info_instant_app_button);
mSiteSettingsButton = (Button) findViewById(R.id.page_info_site_settings_button); mSiteSettingsButton = (Button) findViewById(R.id.page_info_site_settings_button);
...@@ -258,6 +262,11 @@ public class PageInfoView extends FrameLayout implements OnClickListener, OnLong ...@@ -258,6 +262,11 @@ public class PageInfoView extends FrameLayout implements OnClickListener, OnLong
if (!TextUtils.isEmpty(params.previewStaleTimestamp)) { if (!TextUtils.isEmpty(params.previewStaleTimestamp)) {
mPreviewStaleTimestamp.setText(params.previewStaleTimestamp); mPreviewStaleTimestamp.setText(params.previewStaleTimestamp);
} }
initializePageInfoViewChild(mCookieControlsView, params.cookieControlsShown, 0f, null);
}
public CookieControlsView getCookieControlsView() {
return mCookieControlsView;
} }
public void setPermissions(List<PermissionParams> permissionParamsList) { public void setPermissions(List<PermissionParams> permissionParamsList) {
...@@ -363,7 +372,7 @@ public class PageInfoView extends FrameLayout implements OnClickListener, OnLong ...@@ -363,7 +372,7 @@ public class PageInfoView extends FrameLayout implements OnClickListener, OnLong
* Create a list of all the views which we want to individually fade in. * Create a list of all the views which we want to individually fade in.
*/ */
private List<View> collectAnimatableViews() { private List<View> collectAnimatableViews() {
List<View> animatableViews = new ArrayList<View>(); List<View> animatableViews = new ArrayList<>();
animatableViews.add(mUrlTitle); animatableViews.add(mUrlTitle);
animatableViews.add(mConnectionSummary); animatableViews.add(mConnectionSummary);
animatableViews.add(mConnectionMessage); animatableViews.add(mConnectionMessage);
...@@ -376,6 +385,7 @@ public class PageInfoView extends FrameLayout implements OnClickListener, OnLong ...@@ -376,6 +385,7 @@ public class PageInfoView extends FrameLayout implements OnClickListener, OnLong
animatableViews.add(mPermissionsList.getChildAt(i)); animatableViews.add(mPermissionsList.getChildAt(i));
} }
animatableViews.add(mSiteSettingsButton); animatableViews.add(mSiteSettingsButton);
animatableViews.add(mCookieControlsView);
return animatableViews; return animatableViews;
} }
......
...@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.settings.website; ...@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.settings.website;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
/** /**
...@@ -15,7 +16,7 @@ public class CookieControlsBridge { ...@@ -15,7 +16,7 @@ public class CookieControlsBridge {
/** /**
* Interface for a class that wants to receive cookie updates from CookieControlsBridge. * Interface for a class that wants to receive cookie updates from CookieControlsBridge.
*/ */
public interface CookieControlsView { public interface CookieControlsObserver {
/** /**
* Called when the cookie blocking status for the current page changes. * Called when the cookie blocking status for the current page changes.
* @param status An enum indicating the cookie blocking status. * @param status An enum indicating the cookie blocking status.
...@@ -30,19 +31,32 @@ public class CookieControlsBridge { ...@@ -30,19 +31,32 @@ public class CookieControlsBridge {
} }
private long mNativeCookieControlsBridge; private long mNativeCookieControlsBridge;
private CookieControlsView mObserver; private CookieControlsObserver mObserver;
/** /**
* Initializes a CookieControlsBridge instance. * Initializes a CookieControlsBridge instance.
* @param observer An observer to call with updates from the cookie controller. * @param observer An observer to call with updates from the cookie controller.
* @param webContents The WebContents instance to observe. * @param webContents The WebContents instance to observe.
*/ */
public CookieControlsBridge(CookieControlsView observer, WebContents webContents) { public CookieControlsBridge(CookieControlsObserver observer, WebContents webContents) {
mObserver = observer; mObserver = observer;
mNativeCookieControlsBridge = mNativeCookieControlsBridge =
CookieControlsBridgeJni.get().init(CookieControlsBridge.this, webContents); CookieControlsBridgeJni.get().init(CookieControlsBridge.this, webContents);
} }
public void setThirdPartyCookieBlockingEnabledForSite(boolean blockCookies) {
if (mNativeCookieControlsBridge != 0) {
CookieControlsBridgeJni.get().setThirdPartyCookieBlockingEnabledForSite(
mNativeCookieControlsBridge, blockCookies);
}
}
public void onUiClosing() {
if (mNativeCookieControlsBridge != 0) {
CookieControlsBridgeJni.get().onUiClosing(mNativeCookieControlsBridge);
}
}
/** /**
* Destroys the native counterpart of this class. * Destroys the native counterpart of this class.
*/ */
...@@ -54,6 +68,10 @@ public class CookieControlsBridge { ...@@ -54,6 +68,10 @@ public class CookieControlsBridge {
} }
} }
public static boolean isCookieControlsEnabled(Profile profile) {
return CookieControlsBridgeJni.get().isCookieControlsEnabled(profile);
}
@CalledByNative @CalledByNative
private void onCookieBlockingStatusChanged(@CookieControlsControllerStatus int status) { private void onCookieBlockingStatusChanged(@CookieControlsControllerStatus int status) {
mObserver.onCookieBlockingStatusChanged(status); mObserver.onCookieBlockingStatusChanged(status);
...@@ -68,5 +86,9 @@ public class CookieControlsBridge { ...@@ -68,5 +86,9 @@ public class CookieControlsBridge {
interface Natives { interface Natives {
long init(CookieControlsBridge caller, WebContents webContents); long init(CookieControlsBridge caller, WebContents webContents);
void destroy(long nativeCookieControlsBridge, CookieControlsBridge caller); void destroy(long nativeCookieControlsBridge, CookieControlsBridge caller);
void setThirdPartyCookieBlockingEnabledForSite(
long nativeCookieControlsBridge, boolean blockCookies);
void onUiClosing(long nativeCookieControlsBridge);
boolean isCookieControlsEnabled(Profile profile);
} }
} }
// 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.page_info;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isChecked;
import static android.support.test.espresso.matcher.ViewMatchers.isNotChecked;
import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.matcher.ViewMatchers;
import android.support.test.filters.MediumTest;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeActivity;
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.test.ChromeActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.content_public.common.ContentSwitches;
import org.chromium.net.test.EmbeddedTestServer;
import org.chromium.ui.test.util.DisableAnimationsTestRule;
/**
* Tests for CookieControlsView.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags
.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
ContentSwitches.HOST_RESOLVER_RULES + "=MAP * 127.0.0.1"})
@Features.
EnableFeatures(ChromeFeatureList.IMPROVED_COOKIE_CONTROLS_FOR_THIRD_PARTY_COOKIE_BLOCKING)
public class CookieControlsViewTest {
@Rule
public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
new ChromeActivityTestRule<>(ChromeActivity.class);
@ClassRule
public static DisableAnimationsTestRule disableAnimationsRule = new DisableAnimationsTestRule();
private final String mPath = "/chrome/test/data/android/simple.html";
private EmbeddedTestServer mTestServer;
private void loadUrlAndOpenPageInfo(String url) {
mActivityTestRule.loadUrl(url);
onView(withId(R.id.location_bar_status_icon)).perform(click());
}
private void setThirdPartyCookieBlocking(boolean value) {
TestThreadUtils.runOnUiThreadBlocking(() -> {
PrefServiceBridge.getInstance().setBoolean(Pref.BLOCK_THIRD_PARTY_COOKIES, value);
});
}
@Before
public void setUp() throws InterruptedException {
mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
mActivityTestRule.startMainActivityOnBlankPage();
}
@After
public void tearDown() {
mTestServer.destroy();
}
/**
* Tests that CookieControlsView is hidden on a blank page.
*/
@Test
@MediumTest
public void testHiddenOnBlankPage() {
setThirdPartyCookieBlocking(true);
onView(withId(R.id.location_bar_status_icon)).perform(click());
onView(withId(R.id.page_info_cookie_controls_view))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)));
}
/**
* Tests that CookieControlsView is hidden if third-party cookie blocking is off.
*/
@Test
@MediumTest
public void testHiddenWhenDisabled() {
setThirdPartyCookieBlocking(false);
loadUrlAndOpenPageInfo(mTestServer.getURLWithHostName("foo.com", mPath));
onView(withId(R.id.page_info_cookie_controls_view))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)));
}
/**
* Tests that CookieControlsView can be instantiated and shown.
*/
@Test
@MediumTest
public void testShow() {
setThirdPartyCookieBlocking(true);
loadUrlAndOpenPageInfo(mTestServer.getURLWithHostName("foo.com", mPath));
onView(withId(R.id.page_info_cookie_controls_view))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)));
}
/**
* Tests that CookieControlsView updates on navigations.
*/
@Test
@MediumTest
public void testUpdate() {
setThirdPartyCookieBlocking(true);
loadUrlAndOpenPageInfo(mTestServer.getURLWithHostName("foo.com", mPath));
int switch_id = R.id.cookie_controls_block_cookies_switch;
onView(withId(switch_id)).check(matches(isChecked()));
onView(withId(switch_id)).perform(click());
onView(withId(switch_id)).check(matches(isNotChecked()));
// Load a different page.
loadUrlAndOpenPageInfo(mTestServer.getURLWithHostName("bar.com", mPath));
onView(withId(switch_id)).check(matches(isChecked()));
// Go back to foo.com.
loadUrlAndOpenPageInfo(mTestServer.getURLWithHostName("foo.com", mPath));
onView(withId(switch_id)).check(matches(isNotChecked()));
}
}
...@@ -39,7 +39,7 @@ import org.chromium.net.test.EmbeddedTestServer; ...@@ -39,7 +39,7 @@ import org.chromium.net.test.EmbeddedTestServer;
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@EnableFeatures(ChromeFeatureList.IMPROVED_COOKIE_CONTROLS) @EnableFeatures(ChromeFeatureList.IMPROVED_COOKIE_CONTROLS)
public class CookieControlsBridgeTest { public class CookieControlsBridgeTest {
private class TestCallbackHandler implements CookieControlsBridge.CookieControlsView { private class TestCallbackHandler implements CookieControlsBridge.CookieControlsObserver {
private CallbackHelper mHelper; private CallbackHelper mHelper;
public TestCallbackHandler(CallbackHelper helper) { public TestCallbackHandler(CallbackHelper helper) {
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
#include <memory> #include <memory>
#include "chrome/android/chrome_jni_headers/CookieControlsBridge_jni.h" #include "chrome/android/chrome_jni_headers/CookieControlsBridge_jni.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/profiles/profile_android.h"
#include "components/content_settings/core/browser/cookie_settings.h"
using base::android::JavaParamRef; using base::android::JavaParamRef;
...@@ -47,6 +50,16 @@ void CookieControlsBridge::OnBlockedCookiesCountChanged(int blocked_cookies) { ...@@ -47,6 +50,16 @@ void CookieControlsBridge::OnBlockedCookiesCountChanged(int blocked_cookies) {
env, jobject_, blocked_cookies_.value_or(0)); env, jobject_, blocked_cookies_.value_or(0));
} }
void CookieControlsBridge::SetThirdPartyCookieBlockingEnabledForSite(
JNIEnv* env,
bool block_cookies) {
controller_->OnCookieBlockingEnabledForSite(block_cookies);
}
void CookieControlsBridge::OnUiClosing(JNIEnv* env) {
controller_->OnUiClosing();
}
CookieControlsBridge::~CookieControlsBridge() = default; CookieControlsBridge::~CookieControlsBridge() = default;
void CookieControlsBridge::Destroy(JNIEnv* env, void CookieControlsBridge::Destroy(JNIEnv* env,
...@@ -54,6 +67,14 @@ void CookieControlsBridge::Destroy(JNIEnv* env, ...@@ -54,6 +67,14 @@ void CookieControlsBridge::Destroy(JNIEnv* env,
delete this; delete this;
} }
jboolean JNI_CookieControlsBridge_IsCookieControlsEnabled(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jprofile) {
Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
return CookieSettingsFactory::GetForProfile(profile)
->IsCookieControlsEnabled();
}
static jlong JNI_CookieControlsBridge_Init( static jlong JNI_CookieControlsBridge_Init(
JNIEnv* env, JNIEnv* env,
const JavaParamRef<jobject>& obj, const JavaParamRef<jobject>& obj,
......
...@@ -26,6 +26,11 @@ class CookieControlsBridge : public CookieControlsView { ...@@ -26,6 +26,11 @@ class CookieControlsBridge : public CookieControlsView {
// Called by the Java counterpart when it is getting garbage collected. // Called by the Java counterpart when it is getting garbage collected.
void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
void SetThirdPartyCookieBlockingEnabledForSite(JNIEnv* env,
bool block_cookies);
void OnUiClosing(JNIEnv* env);
// CookieControlsView: // CookieControlsView:
void OnStatusChanged(CookieControlsController::Status status, void OnStatusChanged(CookieControlsController::Status status,
int blocked_cookies) override; int blocked_cookies) override;
......
...@@ -2225,6 +2225,11 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p ...@@ -2225,6 +2225,11 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<ph name="BEGIN_LINK">&lt;link&gt;</ph>Load original page<ph name="END_LINK">&lt;/link&gt;</ph> from <ph name="DOMAIN_NAME">%1$s<ex>google.com</ex></ph> <ph name="BEGIN_LINK">&lt;link&gt;</ph>Load original page<ph name="END_LINK">&lt;/link&gt;</ph> from <ph name="DOMAIN_NAME">%1$s<ex>google.com</ex></ph>
</message> </message>
<!-- Cookie controls UI -->
<message name="IDS_COOKIE_CONTROLS_BLOCKED_COOKIES" desc="Text showing the number of blocked cookies on a site.">
Blocked cookies (<ph name="COUNT">%1$s<ex>12</ex></ph>)
</message>
<!-- Sad tab page --> <!-- Sad tab page -->
<message name="IDS_SAD_TAB_SUGGESTIONS" desc="The help message displayed on the sad tab page after a tab crashes."> <message name="IDS_SAD_TAB_SUGGESTIONS" desc="The help message displayed on the sad tab page after a tab crashes.">
If you’re seeing this frequently, try these <ph name="BEGIN_LINK">&lt;link&gt;</ph>suggestions<ph name="END_LINK">&lt;/link&gt;</ph>. If you’re seeing this frequently, try these <ph name="BEGIN_LINK">&lt;link&gt;</ph>suggestions<ph name="END_LINK">&lt;/link&gt;</ph>.
......
...@@ -37,10 +37,10 @@ CookieControlsController::CookieControlsController( ...@@ -37,10 +37,10 @@ CookieControlsController::CookieControlsController(
base::Unretained(this))); base::Unretained(this)));
} }
CookieControlsController::~CookieControlsController() {} CookieControlsController::~CookieControlsController() = default;
void CookieControlsController::OnBubbleUiClosing( void CookieControlsController::OnUiClosing() {
content::WebContents* web_contents) { auto* web_contents = GetWebContents();
if (should_reload_ && web_contents && !web_contents->IsBeingDestroyed()) if (should_reload_ && web_contents && !web_contents->IsBeingDestroyed())
web_contents->GetController().Reload(content::ReloadType::NORMAL, true); web_contents->GetController().Reload(content::ReloadType::NORMAL, true);
should_reload_ = false; should_reload_ = false;
......
...@@ -43,8 +43,8 @@ class CookieControlsController { ...@@ -43,8 +43,8 @@ class CookieControlsController {
// Called when the web_contents has changed. // Called when the web_contents has changed.
void Update(content::WebContents* web_contents); void Update(content::WebContents* web_contents);
// Called when CookieControlsBubbleView is closing. // Called when CookieControlsView is closing.
void OnBubbleUiClosing(content::WebContents* web_contents); void OnUiClosing();
// Called when the user clicks on the button to enable/disable cookie // Called when the user clicks on the button to enable/disable cookie
// blocking. // blocking.
......
...@@ -267,7 +267,7 @@ void CookieControlsBubbleView::WindowClosing() { ...@@ -267,7 +267,7 @@ void CookieControlsBubbleView::WindowClosing() {
if (this_bubble) if (this_bubble)
g_instance = nullptr; g_instance = nullptr;
controller_->OnBubbleUiClosing(web_contents()); controller_->OnUiClosing();
} }
void CookieControlsBubbleView::OnDialogAccepted() { void CookieControlsBubbleView::OnDialogAccepted() {
......
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