Commit 69926c86 authored by Ehimare Okoyomon's avatar Ehimare Okoyomon Committed by Commit Bot

Create CookieSettingsBridge to connect CookieControlsService to java

Implement a bridge to connect Java UI to the CookieControlsService for
a consistent backend with the web implementation.

Bug: 1040091
Change-Id: I023e96d39c14aad20d3d82ff46e560916e595115
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2035894
Commit-Queue: Ehimare Okoyomon <eokoyomon@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Reviewed-by: default avatarChristian Dullweber <dullweber@chromium.org>
Reviewed-by: default avatarNatalie Chouinard <chouinard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#738765}
parent 1fd0446b
......@@ -2790,6 +2790,7 @@ generate_jni("chrome_jni_headers") {
"java/src/org/chromium/chrome/browser/settings/privacy/BrowsingDataCounterBridge.java",
"java/src/org/chromium/chrome/browser/settings/privacy/PrivacyPreferencesManager.java",
"java/src/org/chromium/chrome/browser/settings/website/CookieControlsBridge.java",
"java/src/org/chromium/chrome/browser/settings/website/CookieControlsServiceBridge.java",
"java/src/org/chromium/chrome/browser/settings/website/WebsitePreferenceBridge.java",
"java/src/org/chromium/chrome/browser/sharing/SharingJNIBridge.java",
"java/src/org/chromium/chrome/browser/sharing/SharingServiceProxy.java",
......
......@@ -1464,6 +1464,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/settings/website/ContentSettingException.java",
"java/src/org/chromium/chrome/browser/settings/website/ContentSettingsResources.java",
"java/src/org/chromium/chrome/browser/settings/website/CookieControlsBridge.java",
"java/src/org/chromium/chrome/browser/settings/website/CookieControlsServiceBridge.java",
"java/src/org/chromium/chrome/browser/settings/website/LocalStorageInfo.java",
"java/src/org/chromium/chrome/browser/settings/website/LocationCategory.java",
"java/src/org/chromium/chrome/browser/settings/website/ManageSpaceActivity.java",
......
......@@ -423,6 +423,7 @@ chrome_test_java_sources = [
"javatests/src/org/chromium/chrome/browser/settings/privacy/ClearBrowsingDataFragmentTest.java",
"javatests/src/org/chromium/chrome/browser/settings/privacy/PrivacyPreferencesManagerNativeTest.java",
"javatests/src/org/chromium/chrome/browser/settings/website/CookieControlsBridgeTest.java",
"javatests/src/org/chromium/chrome/browser/settings/website/CookieControlsServiceBridgeTest.java",
"javatests/src/org/chromium/chrome/browser/settings/website/ManageSpaceActivityTest.java",
"javatests/src/org/chromium/chrome/browser/settings/website/PermissionInfoTest.java",
"javatests/src/org/chromium/chrome/browser/settings/website/SiteSettingsTest.java",
......
// 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.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
* UI.
*/
public class CookieControlsServiceBridge {
/**
* Interface for a class that wants to receive cookie controls updates from
* CookieControlsServiceBridge.
*/
public interface CookieControlsServiceObserver {
/**
* Called when there is an update in the cookie controls that should be reflected in the UI.
* @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.
*/
public void sendCookieControlsUIChanges(boolean checked, boolean enforced);
}
private long mNativeCookieControlsServiceBridge;
private CookieControlsServiceObserver mObserver;
/**
* 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) {
mObserver = observer;
mNativeCookieControlsServiceBridge = CookieControlsServiceBridgeJni.get().init(
CookieControlsServiceBridge.this, profile);
}
/**
* Destroys the native counterpart of this class.
*/
public void destroy() {
if (mNativeCookieControlsServiceBridge != 0) {
CookieControlsServiceBridgeJni.get().destroy(
mNativeCookieControlsServiceBridge, CookieControlsServiceBridge.this);
mNativeCookieControlsServiceBridge = 0;
}
}
/**
* Updates the CookieControlsService on the status of the toggle, and thus the state of
* third-party cookie blocking in incognito.
* @param enable A boolean indicating whether the toggle has been switched on or off.
*/
public void handleCookieControlsToggleChanged(boolean enable) {
CookieControlsServiceBridgeJni.get().handleCookieControlsToggleChanged(
mNativeCookieControlsServiceBridge, enable);
}
@CalledByNative
private void sendCookieControlsUIChanges(boolean checked, boolean enforced) {
mObserver.sendCookieControlsUIChanges(checked, enforced);
}
@NativeMethods
interface Natives {
long init(CookieControlsServiceBridge caller, Profile profile);
void destroy(long nativeCookieControlsServiceBridge, CookieControlsServiceBridge caller);
void handleCookieControlsToggleChanged(
long nativeCookieControlsServiceBridge, boolean enable);
}
}
per-file CookieControls*=dullweber@chromium.org
# COMPONENT: UI>Browser>Mobile>Settings
// 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.settings.website;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags;
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.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.test.ChromeActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
import org.chromium.components.content_settings.CookieControlsMode;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.net.test.EmbeddedTestServer;
/**
* Integration tests for CookieControlsServiceBridge.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@EnableFeatures(ChromeFeatureList.IMPROVED_COOKIE_CONTROLS)
public class CookieControlsServiceBridgeTest {
private class TestCallbackHandler
implements CookieControlsServiceBridge.CookieControlsServiceObserver {
private CallbackHelper mHelper;
public TestCallbackHandler(CallbackHelper helper) {
mHelper = helper;
}
@Override
public void sendCookieControlsUIChanges(boolean checked, boolean enforced) {
mChecked = checked;
mEnforced = enforced;
mHelper.notifyCalled();
}
}
@Rule
public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
new ChromeActivityTestRule<>(ChromeActivity.class);
private EmbeddedTestServer mTestServer;
private CallbackHelper mCallbackHelper;
private TestCallbackHandler mCallbackHandler;
private CookieControlsServiceBridge mCookieControlsServiceBridge;
private boolean mChecked;
private boolean mEnforced;
@Before
public void setUp() throws Exception {
mCallbackHelper = new CallbackHelper();
mCallbackHandler = new TestCallbackHandler(mCallbackHelper);
mActivityTestRule.startMainActivityOnBlankPage();
mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
}
@After
public void tearDown() {
mTestServer.stopAndDestroyServer();
}
private void setThirdPartyCookieBlocking(boolean enabled) {
TestThreadUtils.runOnUiThreadBlocking(() -> {
PrefServiceBridge.getInstance().setBoolean(Pref.BLOCK_THIRD_PARTY_COOKIES, enabled);
});
}
private void setCookieControlsMode(@CookieControlsMode int mode) {
TestThreadUtils.runOnUiThreadBlocking(() -> {
PrefServiceBridge.getInstance().setInteger(Pref.COOKIE_CONTROLS_MODE, mode);
});
}
/**
* Test changing the bridge triggers callback for correct toggle state.
*/
@Test
@SmallTest
public void testCookieSettingsCheckedChanges() throws Exception {
setThirdPartyCookieBlocking(false);
setCookieControlsMode(CookieControlsMode.OFF);
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()));
});
setCookieControlsMode(CookieControlsMode.INCOGNITO_ONLY);
mCallbackHelper.waitForCallback(currentCallCount, 1);
Assert.assertEquals(expectedChecked, mChecked);
// Test that the toggle switches off.
expectedChecked = false;
mChecked = true;
currentCallCount = mCallbackHelper.getCallCount();
setCookieControlsMode(CookieControlsMode.OFF);
mCallbackHelper.waitForCallback(currentCallCount, 1);
Assert.assertEquals(expectedChecked, mChecked);
// Test that the toggle switches back on and enforced (by settings)
expectedChecked = true;
mChecked = false;
boolean expectedEnforced = true;
mEnforced = false;
currentCallCount = mCallbackHelper.getCallCount();
setThirdPartyCookieBlocking(true);
mCallbackHelper.waitForCallback(currentCallCount, 1);
Assert.assertEquals(expectedChecked, mChecked);
Assert.assertEquals(expectedEnforced, mEnforced);
}
/**
* Test the ability to set the cookie controls mode pref through the bridge.
*/
@Test
@SmallTest
public void testCookieBridgeWithTPCookiesDisabled() throws Exception {
setThirdPartyCookieBlocking(false);
setCookieControlsMode(CookieControlsMode.OFF);
final String url = mTestServer.getURL("/chrome/test/data/android/cookie.html");
Tab tab = mActivityTestRule.loadUrlInNewTab(url, true); // incognito tab.
boolean expectedChecked = true;
mChecked = false;
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.handleCookieControlsToggleChanged(true);
Assert.assertEquals("CookieControlsMode should be incognito_only",
PrefServiceBridge.getInstance().getInteger(Pref.COOKIE_CONTROLS_MODE),
CookieControlsMode.INCOGNITO_ONLY);
});
mCallbackHelper.waitForCallback(currentCallCount, 1);
Assert.assertEquals(expectedChecked, mChecked);
}
}
file://chrome/android/java/src/org/chromium/chrome/browser/settings/website/OWNERS
......@@ -2614,6 +2614,8 @@ jumbo_static_library("browser") {
"android/preferences/clipboard_android.h",
"android/preferences/cookie_controls_bridge.cc",
"android/preferences/cookie_controls_bridge.h",
"android/preferences/cookie_controls_service_bridge.cc",
"android/preferences/cookie_controls_service_bridge.h",
"android/preferences/pref_change_registrar_android.cc",
"android/preferences/pref_change_registrar_android.h",
"android/preferences/pref_service_bridge.cc",
......
twellington@chromium.org
chouinard@chromium.org
per-file cookie_controls*=dullweber@chromium.org
# COMPONENT: UI>Browser>Mobile>Settings
// 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.
#include "chrome/browser/android/preferences/cookie_controls_service_bridge.h"
#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/ui/cookie_controls/cookie_controls_service.h"
#include "chrome/browser/ui/cookie_controls/cookie_controls_service_factory.h"
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);
}
void CookieControlsServiceBridge::HandleCookieControlsToggleChanged(
JNIEnv* env,
jboolean checked) {
service_->HandleCookieControlsToggleChanged(checked);
}
void CookieControlsServiceBridge::SendCookieControlsUIChanges() {
bool checked = service_->GetToggleCheckedValue();
bool enforced = service_->ShouldEnforceCookieControls();
JNIEnv* env = base::android::AttachCurrentThread();
Java_CookieControlsServiceBridge_sendCookieControlsUIChanges(
env, jobject_, checked, enforced);
}
void CookieControlsServiceBridge::OnThirdPartyCookieBlockingPrefChanged() {
SendCookieControlsUIChanges();
}
void CookieControlsServiceBridge::OnThirdPartyCookieBlockingPolicyChanged() {
SendCookieControlsUIChanges();
}
CookieControlsServiceBridge::~CookieControlsServiceBridge() = default;
void CookieControlsServiceBridge::Destroy(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
delete this;
}
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));
}
// 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.
#ifndef CHROME_BROWSER_ANDROID_PREFERENCES_COOKIE_CONTROLS_SERVICE_BRIDGE_H_
#define CHROME_BROWSER_ANDROID_PREFERENCES_COOKIE_CONTROLS_SERVICE_BRIDGE_H_
#include "base/android/jni_weak_ref.h"
#include "chrome/browser/ui/cookie_controls/cookie_controls_service.h"
// Communicates between CookieControlsService (C++ backend) and observers
// 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() override;
// Called by the Java counterpart when it is getting garbage collected.
void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
void HandleCookieControlsToggleChanged(JNIEnv* env, jboolean checked);
// CookieControlsService::Observer
void OnThirdPartyCookieBlockingPrefChanged() override;
void OnThirdPartyCookieBlockingPolicyChanged() override;
private:
// Updates cookie controls UI when third-party cookie blocking setting has
// changed.
void SendCookieControlsUIChanges();
CookieControlsService* service_;
base::android::ScopedJavaGlobalRef<jobject> jobject_;
DISALLOW_COPY_AND_ASSIGN(CookieControlsServiceBridge);
};
#endif // CHROME_BROWSER_ANDROID_PREFERENCES_COOKIE_CONTROLS_SERVICE_BRIDGE_H_
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