Commit aad7e159 authored by Yao Xiao's avatar Yao Xiao Committed by Commit Bot

Add the remote permission check to FlocIdProvider

Bug: 1062736
Change-Id: I7ee810b21a120d0e45ccfa35c2c5e81cf7e57681
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2267757Reviewed-by: default avatarNicolas Ouellet-Payeur <nicolaso@chromium.org>
Reviewed-by: default avatarYao Xiao <yaoxia@chromium.org>
Reviewed-by: default avatarJosh Karlin <jkarlin@chromium.org>
Commit-Queue: Yao Xiao <yaoxia@chromium.org>
Cr-Commit-Position: refs/heads/master@{#782734}
parent 8fdb8930
......@@ -83,22 +83,9 @@ IN_PROC_BROWSER_TEST_F(FlocIdProviderBrowserTest, NoProviderInIncognitoMode) {
ASSERT_FALSE(incognito_floc_id_provider);
}
class MockFlocIdProvider : public FlocIdProviderImpl {
public:
using FlocIdProviderImpl::FlocIdProviderImpl;
bool IsSwaaNacAccountEnabled() override { return true; }
};
class MockFlocRemotePermissionService : public FlocRemotePermissionService {
public:
MockFlocRemotePermissionService(
const std::string& replacement_host,
const std::string& replacement_port,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
: FlocRemotePermissionService(std::move(url_loader_factory)),
replacement_host_(replacement_host),
replacement_port_(replacement_port) {}
using FlocRemotePermissionService::FlocRemotePermissionService;
GURL GetQueryFlocPermissionUrl() const override {
GURL query_url = FlocRemotePermissionService::GetQueryFlocPermissionUrl();
......@@ -112,6 +99,12 @@ class MockFlocRemotePermissionService : public FlocRemotePermissionService {
return query_url;
}
void SetReplacementHostAndPort(const std::string& replacement_host,
const std::string& replacement_port) {
replacement_host_ = replacement_host;
replacement_port_ = replacement_port;
}
private:
std::string replacement_host_;
std::string replacement_port_;
......@@ -164,11 +157,30 @@ class FlocIdProviderWithCustomizedServicesBrowserTest
return std::move(response);
}
void ConfigureReplacementHostAndPortForRemotePermissionService() {
MockFlocRemotePermissionService* remote_permission_service =
static_cast<MockFlocRemotePermissionService*>(
FlocRemotePermissionServiceFactory::GetForProfile(
browser()->profile()));
GURL test_host_base_url = https_server_.GetURL(test_host(), "/");
remote_permission_service->SetReplacementHostAndPort(
test_host_base_url.host(), test_host_base_url.port());
}
std::vector<GURL> GetHistoryUrls() {
ui_test_utils::HistoryEnumerator enumerator(browser()->profile());
return enumerator.urls();
}
void FinishOutstandingRemotePermissionQueries() {
base::RunLoop run_loop;
FlocRemotePermissionServiceFactory::GetForProfile(browser()->profile())
->QueryFlocPermission(
base::BindLambdaForTesting([&](bool success) { run_loop.Quit(); }),
PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
run_loop.Run();
}
void FinishOutstandingHistoryQueries() {
base::RunLoop run_loop;
base::CancelableTaskTracker tracker;
......@@ -217,12 +229,6 @@ class FlocIdProviderWithCustomizedServicesBrowserTest
base::BindRepeating(&FlocIdProviderWithCustomizedServicesBrowserTest::
CreateFlocRemotePermissionService,
base::Unretained(this)));
FlocIdProviderFactory::GetInstance()->SetTestingFactory(
context,
base::BindRepeating(&FlocIdProviderWithCustomizedServicesBrowserTest::
CreateFlocIdProvider,
base::Unretained(this)));
}
std::unique_ptr<KeyedService> CreateSyncService(
......@@ -245,28 +251,13 @@ class FlocIdProviderWithCustomizedServicesBrowserTest
content::BrowserContext* context) {
Profile* profile = static_cast<Profile*>(context);
GURL test_host_base_url = https_server_.GetURL(test_host(), "/");
auto remote_permission_service =
std::make_unique<MockFlocRemotePermissionService>(
test_host_base_url.host(), test_host_base_url.port(),
content::BrowserContext::GetDefaultStoragePartition(profile)
->GetURLLoaderFactoryForBrowserProcess());
return std::move(remote_permission_service);
}
std::unique_ptr<KeyedService> CreateFlocIdProvider(
content::BrowserContext* context) {
Profile* profile = static_cast<Profile*>(context);
auto floc_id_provider = std::make_unique<MockFlocIdProvider>(
ProfileSyncServiceFactory::GetForProfile(profile),
CookieSettingsFactory::GetForProfile(profile),
HistoryServiceFactory::GetForProfile(
profile, ServiceAccessType::IMPLICIT_ACCESS),
browser_sync::UserEventServiceFactory::GetForProfile(profile));
return std::move(floc_id_provider);
}
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<
......@@ -278,8 +269,11 @@ IN_PROC_BROWSER_TEST_F(FlocIdProviderWithCustomizedServicesBrowserTest,
FlocIdValue_OneNavigation) {
net::IPAddress::ConsiderLoopbackIPToBePubliclyRoutableForTesting();
ConfigureReplacementHostAndPortForRemotePermissionService();
std::string cookies_to_set = "/set-cookie?user_id=123";
ui_test_utils::NavigateToURL(
browser(), https_server_.GetURL(test_host(), "/title1.html"));
browser(), https_server_.GetURL(test_host(), cookies_to_set));
EXPECT_EQ(1u, GetHistoryUrls().size());
......@@ -289,6 +283,7 @@ IN_PROC_BROWSER_TEST_F(FlocIdProviderWithCustomizedServicesBrowserTest,
sync_service()->SetActiveDataTypes(syncer::ModelTypeSet::All());
sync_service()->FireStateChanged();
FinishOutstandingRemotePermissionQueries();
FinishOutstandingHistoryQueries();
// Expect that the FlocIdComputed user event is recorded.
......@@ -306,46 +301,28 @@ IN_PROC_BROWSER_TEST_F(FlocIdProviderWithCustomizedServicesBrowserTest,
event.floc_id());
}
// TODO(yaoxia): Once the service is being used by the FlocIdProvider, we can
// remove this standalone test and rely on the above FlocIdValue_OneNavigation
// test for the same test guarantee.
IN_PROC_BROWSER_TEST_F(FlocIdProviderWithCustomizedServicesBrowserTest,
RemotePermissionService_Success) {
std::string cookies_to_set = "/set-cookie?user_id=123";
ui_test_utils::NavigateToURL(
browser(), https_server_.GetURL(test_host(), cookies_to_set));
FlocRemotePermissionService* remote_permission_service =
FlocRemotePermissionServiceFactory::GetForProfile(browser()->profile());
CookieNotSent_RemotePermissionDenied) {
net::IPAddress::ConsiderLoopbackIPToBePubliclyRoutableForTesting();
base::RunLoop run_loop;
remote_permission_service->QueryFlocPermission(
base::BindLambdaForTesting([&](bool success) {
ASSERT_TRUE(success);
run_loop.Quit();
}),
PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
ConfigureReplacementHostAndPortForRemotePermissionService();
run_loop.Run();
}
IN_PROC_BROWSER_TEST_F(FlocIdProviderWithCustomizedServicesBrowserTest,
RemotePermissionService_NoCookie_PermissionDenied) {
ui_test_utils::NavigateToURL(
browser(), https_server_.GetURL(test_host(), "/title1.html"));
FlocRemotePermissionService* remote_permission_service =
FlocRemotePermissionServiceFactory::GetForProfile(browser()->profile());
EXPECT_EQ(1u, GetHistoryUrls().size());
EXPECT_EQ(GetFlocId().ToDebugHeaderValue(), FlocId().ToDebugHeaderValue());
// Turn on sync-history to trigger the start of the 1st floc session.
sync_service()->SetActiveDataTypes(syncer::ModelTypeSet::All());
sync_service()->FireStateChanged();
base::RunLoop run_loop;
remote_permission_service->QueryFlocPermission(
base::BindLambdaForTesting([&](bool success) {
ASSERT_FALSE(success);
run_loop.Quit();
}),
PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
FinishOutstandingRemotePermissionQueries();
FinishOutstandingHistoryQueries();
run_loop.Run();
// Expect that the FlocIdComputed user event is not recorded.
ASSERT_EQ(0u, user_event_service()->GetRecordedUserEvents().size());
}
} // namespace federated_learning
......@@ -7,6 +7,8 @@
#include "base/memory/singleton.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/federated_learning/floc_id_provider_impl.h"
#include "chrome/browser/federated_learning/floc_remote_permission_service.h"
#include "chrome/browser/federated_learning/floc_remote_permission_service_factory.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
......@@ -36,6 +38,7 @@ FlocIdProviderFactory::FlocIdProviderFactory()
BrowserContextDependencyManager::GetInstance()) {
DependsOn(ProfileSyncServiceFactory::GetInstance());
DependsOn(CookieSettingsFactory::GetInstance());
DependsOn(FlocRemotePermissionServiceFactory::GetInstance());
DependsOn(HistoryServiceFactory::GetInstance());
DependsOn(browser_sync::UserEventServiceFactory::GetInstance());
}
......@@ -56,6 +59,11 @@ KeyedService* FlocIdProviderFactory::BuildServiceInstanceFor(
if (!cookie_settings)
return nullptr;
FlocRemotePermissionService* floc_remote_permission_service =
FlocRemotePermissionServiceFactory::GetForProfile(profile);
if (!floc_remote_permission_service)
return nullptr;
history::HistoryService* history_service =
HistoryServiceFactory::GetForProfile(profile,
ServiceAccessType::IMPLICIT_ACCESS);
......@@ -68,7 +76,8 @@ KeyedService* FlocIdProviderFactory::BuildServiceInstanceFor(
return nullptr;
return new FlocIdProviderImpl(sync_service, std::move(cookie_settings),
history_service, user_event_service);
floc_remote_permission_service, history_service,
user_event_service);
}
} // namespace federated_learning
......@@ -7,6 +7,7 @@
#include <unordered_set>
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/federated_learning/floc_remote_permission_service.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/net/profile_network_context_service.h"
#include "chrome/browser/net/profile_network_context_service_factory.h"
......@@ -33,10 +34,12 @@ constexpr int kQueryHistoryWindowInDays = 7;
FlocIdProviderImpl::FlocIdProviderImpl(
syncer::SyncService* sync_service,
scoped_refptr<content_settings::CookieSettings> cookie_settings,
FlocRemotePermissionService* floc_remote_permission_service,
history::HistoryService* history_service,
syncer::UserEventService* user_event_service)
: sync_service_(sync_service),
cookie_settings_(std::move(cookie_settings)),
floc_remote_permission_service_(floc_remote_permission_service),
history_service_(history_service),
user_event_service_(user_event_service) {
sync_service_->AddObserver(this);
......@@ -83,9 +86,39 @@ bool FlocIdProviderImpl::AreThirdPartyCookiesAllowed() {
return !cookie_settings_->ShouldBlockThirdPartyCookies();
}
bool FlocIdProviderImpl::IsSwaaNacAccountEnabled() {
// TODO(yaoxia): Fetch and validate the swaa/nac/account_type bits.
return false;
void FlocIdProviderImpl::IsSwaaNacAccountEnabled(
CanComputeFlocIdCallback callback) {
net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation =
net::DefinePartialNetworkTrafficAnnotation(
"floc_id_provider_impl", "floc_remote_permission_service",
R"(
semantics {
description:
"Queries google to find out if user has enabled 'web and app "
"activity' and 'ad personalization', and if the account type is "
"NOT a child account. Those permission bits will be checked before "
"computing the FLoC (Federated Learning of Cohorts) ID - an "
"anonymous similarity hash value of user’s navigation history. "
"This ensures that the FLoC ID is derived from data that Google "
"already owns and the user has explicitly granted permission on "
"what they will be used for."
trigger:
"This request is sent at each time a FLoC (Federated Learning of "
"Cohorts) ID is to be computed. A FLoC ID is an anonymous "
"similarity hash value of user’s navigation history. It'll be "
"computed at the start of each browser profile session and will be "
"refreshed every 24 hours during that session."
data:
"Google credentials if user is signed in."
}
policy {
setting:
"This feature cannot be disabled in settings, but disabling sync "
"or third-party cookies will prevent it."
})");
floc_remote_permission_service_->QueryFlocPermission(
std::move(callback), partial_traffic_annotation);
}
void FlocIdProviderImpl::Shutdown() {
......@@ -118,13 +151,12 @@ void FlocIdProviderImpl::CalculateFloc() {
void FlocIdProviderImpl::CheckCanComputeFlocId(
CanComputeFlocIdCallback callback) {
if (!IsSyncHistoryEnabled() || !AreThirdPartyCookiesAllowed() ||
!IsSwaaNacAccountEnabled()) {
if (!IsSyncHistoryEnabled() || !AreThirdPartyCookiesAllowed()) {
std::move(callback).Run(false);
return;
}
std::move(callback).Run(true);
IsSwaaNacAccountEnabled(std::move(callback));
}
void FlocIdProviderImpl::OnCheckCanComputeFlocIdCompleted(
......
......@@ -23,6 +23,8 @@ class UserEventService;
namespace federated_learning {
class FlocRemotePermissionService;
// A service that regularly computes the floc id and logs it in a user event.
//
// A floc session starts when sync & sync-history is first enabled. We validate
......@@ -47,6 +49,7 @@ class FlocIdProviderImpl : public FlocIdProvider,
FlocIdProviderImpl(
syncer::SyncService* sync_service,
scoped_refptr<content_settings::CookieSettings> cookie_settings,
FlocRemotePermissionService* floc_remote_permission_service,
history::HistoryService* history_service,
syncer::UserEventService* user_event_service);
~FlocIdProviderImpl() override;
......@@ -58,7 +61,7 @@ class FlocIdProviderImpl : public FlocIdProvider,
virtual void NotifyFlocIdUpdated(EventLoggingAction);
virtual bool IsSyncHistoryEnabled();
virtual bool AreThirdPartyCookiesAllowed();
virtual bool IsSwaaNacAccountEnabled();
virtual void IsSwaaNacAccountEnabled(CanComputeFlocIdCallback callback);
private:
friend class FlocIdProviderUnitTest;
......@@ -84,6 +87,7 @@ class FlocIdProviderImpl : public FlocIdProvider,
syncer::SyncService* sync_service_;
scoped_refptr<content_settings::CookieSettings> cookie_settings_;
FlocRemotePermissionService* floc_remote_permission_service_;
history::HistoryService* history_service_;
syncer::UserEventService* user_event_service_;
......
......@@ -38,7 +38,9 @@ class MockFlocIdProvider : public FlocIdProviderImpl {
return third_party_cookies_allowed_;
}
bool IsSwaaNacAccountEnabled() override { return swaa_nac_account_enabled_; }
void IsSwaaNacAccountEnabled(CanComputeFlocIdCallback callback) override {
std::move(callback).Run(swaa_nac_account_enabled_);
}
size_t floc_id_notification_count() const {
return floc_id_notification_count_;
......@@ -82,7 +84,8 @@ class FlocIdProviderUnitTest : public testing::Test {
floc_id_provider_ = std::make_unique<MockFlocIdProvider>(
test_sync_service_.get(), /*cookie_settings=*/nullptr,
history_service_.get(), fake_user_event_service_.get());
/*floc_remote_permission_service=*/nullptr, history_service_.get(),
fake_user_event_service_.get());
task_environment_.RunUntilIdle();
}
......
......@@ -65,11 +65,26 @@ class RequestImpl : public FlocRemotePermissionService::Request {
DCHECK(resource_request->SendsCookies());
// TODO(yaoxia): Once we have a client, incorporate
// |partial_traffic_annotation_| to make an actual
// CompleteNetworkTrafficAnnotation.
net::NetworkTrafficAnnotationTag traffic_annotation =
net::CompleteNetworkTrafficAnnotation("floc_remote_permission_service",
partial_traffic_annotation_,
R"(
semantics {
sender: "Federated Learning of Cohorts Remote Permission Service"
destination: GOOGLE_OWNED_SERVICE
}
policy {
cookies_allowed: YES
cookies_store: "user"
chrome_policy {
SyncDisabled {
SyncDisabled: true
}
}
})");
simple_url_loader_ = network::SimpleURLLoader::Create(
std::move(resource_request), MISSING_TRAFFIC_ANNOTATION);
std::move(resource_request), traffic_annotation);
simple_url_loader_->SetRetryOptions(kMaxRetries,
network::SimpleURLLoader::RETRY_ON_5XX);
simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
......
......@@ -12,4 +12,3 @@ mutable_tag,chrome/browser/media/router/providers/openscreen/platform/udp_socket
test_annotation,components/safe_search_api/stub_url_checker.cc
test_annotation,net/quic/quic_chromium_client_session_peer.cc
test_annotation,net/tools/quic/quic_http_proxy_backend_stream.cc
missing,chrome/browser/federated_learning/floc_remote_permission_service.cc
......@@ -106,6 +106,8 @@ Refer to README.md for content description and update process.
<item id="family_info" hash_code="30913825" type="0" deprecated="2019-07-30" content_hash_code="25369370" file_path=""/>
<item id="favicon_loader" hash_code="112189210" type="0" content_hash_code="70773116" os_list="linux,windows" file_path="content/renderer/loader/web_url_loader_impl.cc"/>
<item id="feed_image_fetcher" hash_code="87439531" type="0" deprecated="2019-01-04" content_hash_code="26756208" file_path=""/>
<item id="floc_id_provider_impl" hash_code="103052331" type="1" second_id="13704791" content_hash_code="41421380" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="3" file_path="chrome/browser/federated_learning/floc_id_provider_impl.cc"/>
<item id="floc_remote_permission_service" hash_code="13704791" type="2" content_hash_code="86293622" os_list="linux,windows" semantics_fields="1,5" policy_fields="1,2,4" file_path="chrome/browser/federated_learning/floc_remote_permission_service.cc"/>
<item id="gaia_auth_check_connection_info" hash_code="4598626" type="0" content_hash_code="57347000" os_list="linux,windows" file_path="google_apis/gaia/gaia_auth_fetcher.cc"/>
<item id="gaia_auth_exchange_cookies" hash_code="134289752" type="0" deprecated="2018-09-11" content_hash_code="66433230" file_path=""/>
<item id="gaia_auth_exchange_device_id" hash_code="39877119" type="0" content_hash_code="61857947" os_list="linux,windows" file_path="google_apis/gaia/gaia_auth_fetcher.cc"/>
......
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