Skip to content

Commit

Permalink
[Merge to M116] Private Aggregation: Test attestation in Shared Storage
Browse files Browse the repository at this point in the history
We add a chrome/ layer browser test to verify that site attestation
works as intended for the Private Aggregation API in Shared Storage.

(cherry picked from commit 7b435c1)

Bug: 1448875,1455135,1218540
Change-Id: I78621e82b95c31a17889bbeae9d48ee5c305523f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4629671
Reviewed-by: Avi Drissman <avi@chromium.org>
Reviewed-by: Alex Turner <alexmt@chromium.org>
Commit-Queue: Cammie Smith Barnes <cammie@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1161325}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4654847
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Avi Drissman <avi@chromium.org>
Auto-Submit: Cammie Smith Barnes <cammie@chromium.org>
Cr-Commit-Position: refs/branch-heads/5845@{chromium#187}
Cr-Branched-From: 5a5dff6-refs/heads/main@{#1160321}
  • Loading branch information
pythagoraskitty authored and Chromium LUCI CQ committed Jun 28, 2023
1 parent 1d9949f commit b47eef5
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 17 deletions.
237 changes: 220 additions & 17 deletions chrome/browser/storage/shared_storage_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ constexpr char kWorkletNumPerPageHistogram[] =
"Storage.SharedStorage.Worklet.NumPerPage";
constexpr char kTimingRemainingBudgetHistogram[] =
"Storage.SharedStorage.Worklet.Timing.RemainingBudget";
constexpr char kPrivateAggregationSendHistogramReportHistogram[] =
"PrivacySandbox.PrivateAggregation.Host.SendHistogramReportResult";

const double kBudgetAllowed = 5.0;

Expand Down Expand Up @@ -207,14 +209,19 @@ content::RenderFrameHost* CreateIframe(content::RenderFrameHost* parent_rfh,

privacy_sandbox::PrivacySandboxAttestationsMap
MakeSharedStoragePrivacySandboxAttestationsMap(
const std::vector<GURL>& enrollee_urls) {
const std::vector<GURL>& enrollee_urls,
bool enroll_for_private_aggregation = false) {
privacy_sandbox::PrivacySandboxAttestationsMap attestations_map;
for (const auto& url : enrollee_urls) {
attestations_map[net::SchemefulSite(url)] = base::EnumSet<
privacy_sandbox::PrivacySandboxAttestationsGatedAPI,
privacy_sandbox::PrivacySandboxAttestationsGatedAPI::kTopics,
privacy_sandbox::PrivacySandboxAttestationsGatedAPI::kMaxValue>(
{privacy_sandbox::PrivacySandboxAttestationsGatedAPI::kSharedStorage});
auto attestations_set =
privacy_sandbox::PrivacySandboxAttestationsGatedAPISet(
{privacy_sandbox::PrivacySandboxAttestationsGatedAPI::
kSharedStorage});
if (enroll_for_private_aggregation) {
attestations_set.Put(privacy_sandbox::PrivacySandboxAttestationsGatedAPI::
kPrivateAggregation);
}
for (const GURL& url : enrollee_urls) {
attestations_map[net::SchemefulSite(url)] = attestations_set;
}
return attestations_map;
}
Expand Down Expand Up @@ -316,7 +323,9 @@ class SharedStorageChromeBrowserTestBase : public PlatformBrowserTest {
->SetAttestationsForTesting(attestations_map);
}

void MaybeEnrollMainHost(const GURL& main_url) {
// Unless overridden to do otherwise, enrolls the main host to attest for
// Shared Storage exactly when `ShouldEnrollMainHost()` is true.
virtual void MaybeEnrollMainHost(const GURL& main_url) {
privacy_sandbox::PrivacySandboxAttestationsMap attestations_map =
ShouldEnrollMainHost()
? MakeSharedStoragePrivacySandboxAttestationsMap(
Expand Down Expand Up @@ -366,7 +375,8 @@ class SharedStorageChromeBrowserTestBase : public PlatformBrowserTest {
bool ExecuteScriptInWorklet(
const content::ToRenderFrameHost& execution_target,
const std::string& script,
const std::string& last_script_message) {
const std::string& last_script_message,
bool use_select_url = false) {
content::WebContentsConsoleObserver add_module_console_observer(
GetActiveWebContents());
add_module_console_observer.SetFilter(
Expand Down Expand Up @@ -406,17 +416,70 @@ class SharedStorageChromeBrowserTestBase : public PlatformBrowserTest {
script_console_observer.SetFilter(MakeFilter(
{last_script_message, ExpectedSharedStorageDisabledMessage()}));

content::EvalJsResult result = content::EvalJs(execution_target, R"(
if (!use_select_url) {
content::EvalJsResult result = content::EvalJs(execution_target, R"(
sharedStorage.run('test-operation');
)");

EXPECT_TRUE(script_console_observer.Wait());
EXPECT_EQ(1u, script_console_observer.messages().size());

EXPECT_EQ(
last_script_message,
base::UTF16ToUTF8(script_console_observer.messages()[0].message));

return result.error.empty();
}
EXPECT_TRUE(
ExecJs(GetActiveWebContents(),
content::JsReplace("window.resolveSelectURLToConfig = $1;",
ResolveSelectURLToConfig())));

// Construct and add the `TestSelectURLFencedFrameConfigObserver` to shared
// storage worklet host manager.
content::StoragePartition* storage_partition =
content::ToRenderFrameHost(GetActiveWebContents())
.render_frame_host()
->GetStoragePartition();
content::TestSelectURLFencedFrameConfigObserver config_observer(
storage_partition);
content::EvalJsResult result = EvalJs(GetActiveWebContents(), R"(
(async function() {
window.select_url_result = await sharedStorage.selectURL(
'test-operation',
[{url: "fenced_frames/title0.html"},
{url: "fenced_frames/title1.html"},
],
{resolveToConfig: resolveSelectURLToConfig}
);
if (resolveSelectURLToConfig &&
!(select_url_result instanceof FencedFrameConfig)) {
throw new Error('selectURL() did not return a FencedFrameConfig.');
}
return window.select_url_result;
})()
)");

EXPECT_TRUE(script_console_observer.Wait());
EXPECT_EQ(1u, script_console_observer.messages().size());

EXPECT_EQ(last_script_message,
base::UTF16ToUTF8(script_console_observer.messages()[0].message));

return result.error.empty();
if (!result.error.empty()) {
return false;
}

absl::optional<GURL> observed_urn_uuid = config_observer.GetUrnUuid();
EXPECT_TRUE(observed_urn_uuid.has_value());
EXPECT_TRUE(blink::IsValidUrnUuidURL(observed_urn_uuid.value()));
GURL urn_uuid = observed_urn_uuid.value();

if (!ResolveSelectURLToConfig()) {
EXPECT_EQ(result.ExtractString(), observed_urn_uuid->spec());
}

return true;
}

double RemainingBudget(const content::ToRenderFrameHost& execution_target,
Expand Down Expand Up @@ -466,6 +529,11 @@ class SharedStorageChromeBrowserTestBase : public PlatformBrowserTest {
virtual bool EnforceAttestations() const { return false; }
virtual bool ShouldEnrollMainHost() const { return true; }

bool SuccessExpected() {
return (ShouldEnrollMainHost() || !EnforceAttestations()) &&
EnablePrivacySandbox() && AllowThirdPartyCookies();
}

std::string ExpectedSharedStorageDisabledMessage() {
return "Error: " + content::GetSharedStorageDisabledMessage();
}
Expand Down Expand Up @@ -531,12 +599,6 @@ class SharedStoragePrefBrowserTest
}
bool EnforceAttestations() const override { return std::get<3>(GetParam()); }
bool ShouldEnrollMainHost() const override { return std::get<4>(GetParam()); }

bool SuccessExpected() {
return (ShouldEnrollMainHost() || !EnforceAttestations()) &&
EnablePrivacySandbox() && AllowThirdPartyCookies();
}

void AddSimpleModuleWithPermissionBypassed(
const content::ToRenderFrameHost& execution_target) {
content::WebContentsConsoleObserver add_module_console_observer(
Expand Down Expand Up @@ -2717,4 +2779,145 @@ IN_PROC_BROWSER_TEST_F(
EXPECT_EQ(3, histogram_tester_.GetTotalSum(kWorkletNumPerPageHistogram));
}

using SharedStoragePrivateAggregationChromeBrowserParams = std::tuple<
/*enforce_attestations=*/bool,
/*should_enroll_main_host=*/bool>;

class SharedStoragePrivateAggregationChromeBrowserTest
: public SharedStorageChromeBrowserTestBase,
public testing::WithParamInterface<
SharedStoragePrivateAggregationChromeBrowserParams> {
public:
SharedStoragePrivateAggregationChromeBrowserTest() {
fenced_frame_api_change_feature_.InitWithFeatureState(
blink::features::kFencedFramesAPIChanges, ResolveSelectURLToConfig());
fenced_frame_feature_.InitAndEnableFeature(blink::features::kFencedFrames);
attestation_feature_.InitWithFeatureState(
privacy_sandbox::kEnforcePrivacySandboxAttestations,
EnforceAttestations());
private_aggregation_feature_.InitAndEnableFeature(
blink::features::kPrivateAggregationApi);
}

~SharedStoragePrivateAggregationChromeBrowserTest() override = default;

bool ResolveSelectURLToConfig() const override { return true; }
bool EnforceAttestations() const override { return std::get<0>(GetParam()); }
bool ShouldEnrollMainHost() const override { return std::get<1>(GetParam()); }

// This always enrolls the main host for Shared Storage, but only enrolls the
// main host for Private Aggregation exactly when `ShouldEnrollMainHost()` is
// true.
void MaybeEnrollMainHost(const GURL& main_url) override {
privacy_sandbox::PrivacySandboxAttestationsMap attestations_map =
MakeSharedStoragePrivacySandboxAttestationsMap(
std::vector<GURL>({main_url}),
/*enroll_for_private_aggregation=*/ShouldEnrollMainHost());
SetAttestationsMap(attestations_map);
}

private:
base::test::ScopedFeatureList shared_storage_feature_;
base::test::ScopedFeatureList fenced_frame_api_change_feature_;
base::test::ScopedFeatureList fenced_frame_feature_;
base::test::ScopedFeatureList attestation_feature_;
base::test::ScopedFeatureList private_aggregation_feature_;
};

INSTANTIATE_TEST_SUITE_P(
All,
SharedStoragePrivateAggregationChromeBrowserTest,
testing::Combine(testing::Bool(), testing::Bool()),
[](const testing::TestParamInfo<
SharedStoragePrivateAggregationChromeBrowserTest::ParamType>& info) {
return base::StrCat(
{"Attestations", std::get<0>(info.param) ? "Enforced" : "Unenforced",
"_MainHost", std::get<1>(info.param) ? "Enrolled" : "Unenrolled"});
});

IN_PROC_BROWSER_TEST_P(SharedStoragePrivateAggregationChromeBrowserTest,
ContributeToHistogramViaRun) {
// This always enrolls the main host for Shared Storage, but only enrolls the
// main host for Private Aggregation exactly when `ShouldEnrollMainHost()` is
// true.
Set3rdPartyCookieAndMainHostAttestationSettingsThenNavigateToMainHostPage();

EXPECT_TRUE(ExecuteScriptInWorklet(GetActiveWebContents(), R"(
privateAggregation.contributeToHistogram({bucket: 1n, value: 2});
console.log('Finished script');
)",
"Finished script"));

// Navigate away to record `kWorkletNumPerPageHistogram` histogram.
EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(),
GURL(url::kAboutBlankURL)));
WaitForHistograms({kWorkletNumPerPageHistogram,
kPrivateAggregationSendHistogramReportHistogram});
histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1);
histogram_tester_.ExpectUniqueSample(
kPrivateAggregationSendHistogramReportHistogram,
SuccessExpected()
? content::GetPrivateAggregationSendHistogramSuccessValue()
: content::GetPrivateAggregationSendHistogramApiDisabledValue(),
1);
}

IN_PROC_BROWSER_TEST_P(SharedStoragePrivateAggregationChromeBrowserTest,
ContributeToHistogramViaSelectURL) {
// This always enrolls the main host for Shared Storage, but only enrolls the
// main host for Private Aggregation exactly when `ShouldEnrollMainHost()` is
// true.
Set3rdPartyCookieAndMainHostAttestationSettingsThenNavigateToMainHostPage();

EXPECT_TRUE(ExecuteScriptInWorklet(GetActiveWebContents(), R"(
privateAggregation.contributeToHistogram({bucket: 1n, value: 2});
console.log('Finished script');
return 1;
)",
"Finished script",
/*use_select_url=*/true));

// Navigate away to record `kWorkletNumPerPageHistogram` histogram.
EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(),
GURL(url::kAboutBlankURL)));
WaitForHistograms({kWorkletNumPerPageHistogram,
kPrivateAggregationSendHistogramReportHistogram});
histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1);
histogram_tester_.ExpectUniqueSample(
kPrivateAggregationSendHistogramReportHistogram,
SuccessExpected()
? content::GetPrivateAggregationSendHistogramSuccessValue()
: content::GetPrivateAggregationSendHistogramApiDisabledValue(),
1);
}

IN_PROC_BROWSER_TEST_P(SharedStoragePrivateAggregationChromeBrowserTest,
WithContextId_NoPrivateAggregationJS) {
// This always enrolls the main host for Shared Storage, but only enrolls the
// main host for Private Aggregation exactly when `ShouldEnrollMainHost()` is
// true.
Set3rdPartyCookieAndMainHostAttestationSettingsThenNavigateToMainHostPage();
AddSimpleModule(GetActiveWebContents());

content::EvalJsResult result = content::EvalJs(GetActiveWebContents(), R"(
sharedStorage.run('test-operation',
{data: {},
privateAggregationConfig: {contextId:
'example_id'}});
)");

// Navigate away to record `kWorkletNumPerPageHistogram` histogram.
EXPECT_TRUE(content::NavigateToURL(GetActiveWebContents(),
GURL(url::kAboutBlankURL)));
WaitForHistograms({kWorkletNumPerPageHistogram,
kPrivateAggregationSendHistogramReportHistogram});
histogram_tester_.ExpectUniqueSample(kWorkletNumPerPageHistogram, 1, 1);
histogram_tester_.ExpectUniqueSample(
kPrivateAggregationSendHistogramReportHistogram,
SuccessExpected()
? content::GetPrivateAggregationSendHistogramSuccessValue()
: content::GetPrivateAggregationSendHistogramApiDisabledValue(),
1);
}

} // namespace storage
3 changes: 3 additions & 0 deletions content/public/test/DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,8 @@ specific_include_rules = {
],
"test_shared_storage_header_observer.h": [
"+content/browser/shared_storage/shared_storage_header_observer.h"
],
"shared_storage_test_utils.h": [
"+content/browser/private_aggregation/private_aggregation_host.h"
]
}
11 changes: 11 additions & 0 deletions content/public/test/shared_storage_test_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -313,4 +313,15 @@ bool operator==(const SharedStorageWriteOperationAndResult& a,
a.result == b.result;
}

PrivateAggregationHost::SendHistogramReportResult
GetPrivateAggregationSendHistogramSuccessValue() {
return PrivateAggregationHost::SendHistogramReportResult::kSuccess;
}

PrivateAggregationHost::SendHistogramReportResult
GetPrivateAggregationSendHistogramApiDisabledValue() {
return PrivateAggregationHost::SendHistogramReportResult::
kApiDisabledInSettings;
}

} // namespace content
7 changes: 7 additions & 0 deletions content/public/test/shared_storage_test_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <string>

#include "components/services/storage/shared_storage/shared_storage_manager.h"
#include "content/browser/private_aggregation/private_aggregation_host.h"
#include "services/network/public/mojom/optional_bool.mojom.h"
#include "services/network/public/mojom/url_loader_network_service_observer.mojom.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
Expand Down Expand Up @@ -105,6 +106,12 @@ struct SharedStorageWriteOperationAndResult {
bool operator==(const SharedStorageWriteOperationAndResult& a,
const SharedStorageWriteOperationAndResult& b);

PrivateAggregationHost::SendHistogramReportResult
GetPrivateAggregationSendHistogramSuccessValue();

PrivateAggregationHost::SendHistogramReportResult
GetPrivateAggregationSendHistogramApiDisabledValue();

} // namespace content

#endif // CONTENT_PUBLIC_TEST_SHARED_STORAGE_TEST_UTILS_H_

0 comments on commit b47eef5

Please sign in to comment.