diff --git a/content/browser/devtools/devtools_trust_token_browsertest.cc b/content/browser/devtools/devtools_trust_token_browsertest.cc index 366e0b56e0cf0..ad2cb4b9ac9f1 100644 --- a/content/browser/devtools/devtools_trust_token_browsertest.cc +++ b/content/browser/devtools/devtools_trust_token_browsertest.cc @@ -160,6 +160,20 @@ IN_PROC_BROWSER_TEST_F(DevToolsTrustTokenBrowsertest, IframeEndToEnd) { Attach(); SendCommandSync("Network.enable"); + // 3) Request and redeem a token, then use the redeemed token in a Signing + // request. + std::string command = R"( + (async () => { + await fetch('/issue', {trustToken: {type: 'token-request'}}); + await fetch('/redeem', {trustToken: {type: 'token-redemption'}}); + return 'Success'; })(); )"; + + // We use EvalJs here, not ExecJs, because EvalJs waits for promises to + // resolve. + EXPECT_EQ( + "Success", + EvalJs(shell(), JsReplace(command, IssuanceOriginFromHost("a.test")))); + // 3) Request and redeem a token, then use the redeemed token in a Signing // request. auto execute_op_via_iframe = [&](base::StringPiece path, @@ -176,8 +190,6 @@ IN_PROC_BROWSER_TEST_F(DevToolsTrustTokenBrowsertest, IframeEndToEnd) { load_observer.WaitForNavigationFinished(); }; - execute_op_via_iframe("/issue", R"({"type": "token-request"})"); - execute_op_via_iframe("/redeem", R"({"type": "token-redemption"})"); execute_op_via_iframe("/sign", JsReplace( R"({"type": "send-redemption-record", "issuers": [$1]})", diff --git a/content/browser/network/trust_token_browsertest.cc b/content/browser/network/trust_token_browsertest.cc index 29000d9ecdc97..86f35fa79a54f 100644 --- a/content/browser/network/trust_token_browsertest.cc +++ b/content/browser/network/trust_token_browsertest.cc @@ -7,16 +7,11 @@ #include #include -#include "base/base64.h" -#include "base/containers/contains.h" #include "base/run_loop.h" -#include "base/strings/escape.h" -#include "base/strings/strcat.h" #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" #include "base/test/bind.h" #include "base/test/scoped_feature_list.h" -#include "base/threading/thread_restrictions.h" #include "build/build_config.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/network_service_instance.h" @@ -28,17 +23,12 @@ #include "content/public/test/url_loader_interceptor.h" #include "content/public/test/url_loader_monitor.h" #include "content/shell/browser/shell.h" -#include "crypto/sha2.h" -#include "net/base/filename_util.h" #include "net/dns/mock_host_resolver.h" -#include "net/test/embedded_test_server/http_request.h" -#include "net/test/embedded_test_server/http_response.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" #include "services/network/public/cpp/resource_request.h" #include "services/network/public/cpp/trust_token_http_headers.h" #include "services/network/public/cpp/trust_token_parameterization.h" -#include "services/network/public/mojom/trust_tokens.mojom.h" #include "services/network/test/trust_token_request_handler.h" #include "services/network/test/trust_token_test_server_handler_registration.h" #include "services/network/test/trust_token_test_util.h" @@ -246,12 +236,23 @@ IN_PROC_BROWSER_TEST_F(TrustTokenBrowsertest, XhrEndToEnd) { HasHeader(network::kTrustTokensSecTrustTokenVersionHeader)))); } -IN_PROC_BROWSER_TEST_F(TrustTokenBrowsertest, IframeEndToEnd) { +IN_PROC_BROWSER_TEST_F(TrustTokenBrowsertest, IframeSendRedemptionRecord) { ProvideRequestHandlerKeyCommitmentsToNetworkService({"a.test"}); + std::string command = R"( + (async () => { + await fetch("/issue", {trustToken: {type: 'token-request'}}); + await fetch("/redeem", {trustToken: {type: 'token-redemption'}}); + return "Success"; + })())"; + GURL start_url = server_.GetURL("a.test", "/page_with_iframe.html"); ASSERT_TRUE(NavigateToURL(shell(), start_url)); + EXPECT_EQ( + "Success", + EvalJs(shell(), JsReplace(command, IssuanceOriginFromHost("a.test")))); + auto execute_op_via_iframe = [&](base::StringPiece path, base::StringPiece trust_token) { // It's important to set the trust token arguments before updating src, as @@ -266,8 +267,6 @@ IN_PROC_BROWSER_TEST_F(TrustTokenBrowsertest, IframeEndToEnd) { load_observer.WaitForNavigationFinished(); }; - execute_op_via_iframe("/issue", R"({"type": "token-request"})"); - execute_op_via_iframe("/redeem", R"({"type": "token-redemption"})"); execute_op_via_iframe("/sign", JsReplace( R"({"type": "send-redemption-record", "issuers": [$1]})", @@ -280,6 +279,54 @@ IN_PROC_BROWSER_TEST_F(TrustTokenBrowsertest, IframeEndToEnd) { HasHeader(network::kTrustTokensSecTrustTokenVersionHeader)))); } +IN_PROC_BROWSER_TEST_F(TrustTokenBrowsertest, + IframeCanOnlySendRedemptionRecord) { + ProvideRequestHandlerKeyCommitmentsToNetworkService({"a.test"}); + + GURL start_url = server_.GetURL("a.test", "/page_with_iframe.html"); + ASSERT_TRUE(NavigateToURL(shell(), start_url)); + + auto fail_to_execute_op_via_iframe = [&](base::StringPiece path, + base::StringPiece trust_token) { + // It's important to set the trust token arguments before updating src, as + // the latter triggers a load. + EXPECT_TRUE(ExecJs( + shell(), JsReplace( + R"( const myFrame = document.getElementById("test_iframe"); + myFrame.trustToken = $1; + myFrame.src = $2;)", + trust_token, path))); + TestNavigationObserver load_observer(shell()->web_contents()); + load_observer.WaitForNavigationFinished(); + }; + + fail_to_execute_op_via_iframe("/issue", R"({"type": "token-request"})"); + std::string command = JsReplace(R"( + (async () => { + return await document.hasPrivateToken($1, 'private-state-token'); + })();)", + IssuanceOriginFromHost("a.test")); + + EXPECT_EQ(false, EvalJs(shell(), command)); + + fail_to_execute_op_via_iframe("/redeem", R"({"type": "token-redemption"})"); + command = JsReplace(R"( + (async () => { + return document.hasRedemptionRecord($1, 'private-state-token'); + })();)", + IssuanceOriginFromHost("a.test")); + EXPECT_EQ(false, EvalJs(shell(), command)); + + fail_to_execute_op_via_iframe("/bad", R"({"type": "bad-type"})"); + command = JsReplace(R"( + (async () => { + return await document.hasPrivateToken($1, 'private-state-token') + || document.hasRedemptionRecord($1, 'private-state-token'); + })();)", + IssuanceOriginFromHost("a.test")); + EXPECT_EQ(false, EvalJs(shell(), command)); +} + IN_PROC_BROWSER_TEST_F(TrustTokenBrowsertest, HasTrustTokenAfterIssuance) { ProvideRequestHandlerKeyCommitmentsToNetworkService({"a.test"}); diff --git a/content/browser/network/trust_token_origin_trial_browsertest.cc b/content/browser/network/trust_token_origin_trial_browsertest.cc index 6bc2b57106af1..e166412172c6a 100644 --- a/content/browser/network/trust_token_origin_trial_browsertest.cc +++ b/content/browser/network/trust_token_origin_trial_browsertest.cc @@ -305,6 +305,7 @@ INSTANTIATE_TEST_SUITE_P(ExecutingAllOperations, IN_PROC_BROWSER_TEST_P(TrustTokenOriginTrialBrowsertest, ProvidesParamsOnlyWhenAllowed) { TestDescription test_description = std::get<1>(GetParam()); + Interface interface = std::get<0>(GetParam()); URLLoaderInterceptor interceptor(base::BindLambdaForTesting( [this](URLLoaderInterceptor::RequestParams* params) { @@ -338,12 +339,15 @@ IN_PROC_BROWSER_TEST_P(TrustTokenOriginTrialBrowsertest, trust_token_params); std::string command; - switch (std::get<0>(GetParam()) /* interface */) { + switch (interface) { case Interface::kFetch: command = JsReplace("fetch($1, {trustToken: ", kTrustTokenUrl) + expected_params_and_serialization.serialized_params + "});"; break; case Interface::kIframe: + if (test_description.op != Op::kSigning) { + return; + } command = JsReplace( "let iframe = document.createElement('iframe');" "iframe.src = $1;" diff --git a/content/browser/network/trust_token_parameters_browsertest.cc b/content/browser/network/trust_token_parameters_browsertest.cc index a4bf80c038a48..e72529eb10cfb 100644 --- a/content/browser/network/trust_token_parameters_browsertest.cc +++ b/content/browser/network/trust_token_parameters_browsertest.cc @@ -107,6 +107,13 @@ IN_PROC_BROWSER_TEST_P(TrustTokenParametersBrowsertest, network::SerializeTrustTokenParametersAndConstructExpectation( GetParam()); + // In the iframe interface to private state tokens, we only accept the + // kSigning variant, i.e. the send-redemption-record operation. + if (expected_params_and_serialization.params->type != + network::mojom::TrustTokenOperationType::kSigning) { + return; + } + GURL url(embedded_test_server()->GetURL("/title1.html")); GURL trust_token_url(embedded_test_server()->GetURL("/title2.html")); diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc index 5aebabbffca75..3f139d0984b7b 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.cc +++ b/third_party/blink/renderer/core/html/html_iframe_element.cc @@ -509,17 +509,20 @@ HTMLIFrameElement::ConstructTrustTokenParams() const { return nullptr; } - // Trust token redemption and signing (but not issuance) require that the - // trust-token-redemption permissions policy be present. - bool operation_requires_permissions_policy = - parsed_params->type == - network::mojom::blink::TrustTokenOperationType::kRedemption || - parsed_params->type == - network::mojom::blink::TrustTokenOperationType::kSigning; - - if (operation_requires_permissions_policy && - (!GetExecutionContext()->IsFeatureEnabled( - mojom::blink::PermissionsPolicyFeature::kTrustTokenRedemption))) { + // Only the send-redemption-record (the kSigning variant) operation is + // valid in the iframe context. + if (parsed_params->type != + network::mojom::blink::TrustTokenOperationType::kSigning) { + GetDocument().AddConsoleMessage(MakeGarbageCollected( + mojom::blink::ConsoleMessageSource::kOther, + mojom::blink::ConsoleMessageLevel::kError, + "Trust Tokens: Attempted a trusttoken operation which isn't " + "send-redemption-record in an iframe.")); + return nullptr; + } + + if (!GetExecutionContext()->IsFeatureEnabled( + mojom::blink::PermissionsPolicyFeature::kTrustTokenRedemption)) { GetExecutionContext()->AddConsoleMessage( MakeGarbageCollected( mojom::blink::ConsoleMessageSource::kOther, @@ -529,18 +532,6 @@ HTMLIFrameElement::ConstructTrustTokenParams() const { return nullptr; } - if (parsed_params->type == - network::mojom::blink::TrustTokenOperationType::kIssuance && - !IsTrustTokenIssuanceAvailableInExecutionContext( - *GetExecutionContext())) { - GetDocument().AddConsoleMessage(MakeGarbageCollected( - mojom::blink::ConsoleMessageSource::kOther, - mojom::blink::ConsoleMessageLevel::kError, - "Private State Tokens issuance is disabled except in " - "contexts with the PrivateStateTokens Origin Trial enabled.")); - return nullptr; - } - return parsed_params; } diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/iframe-request-trust-token.html b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/iframe-request-trust-token.html index 018434a701e0a..2e6b22c00e431 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/iframe-request-trust-token.html +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/iframe-request-trust-token.html @@ -1 +1 @@ - + diff --git a/third_party/blink/web_tests/virtual/trust-tokens/http/tests/inspector-protocol/trust-tokens/trust-token-params-iframe-expected.txt b/third_party/blink/web_tests/virtual/trust-tokens/http/tests/inspector-protocol/trust-tokens/trust-token-params-iframe-expected.txt index d27c0680f5921..69174e98cea46 100644 --- a/third_party/blink/web_tests/virtual/trust-tokens/http/tests/inspector-protocol/trust-tokens/trust-token-params-iframe-expected.txt +++ b/third_party/blink/web_tests/virtual/trust-tokens/http/tests/inspector-protocol/trust-tokens/trust-token-params-iframe-expected.txt @@ -1,4 +1,4 @@ Check that TrustTokenParams are included when an iframe requests a trust token' Main frame navigation not expected to contain trustTokenParams. -Included trustTokenParams in request: {"type":"Issuance","refreshPolicy":"UseCached"} +Included trustTokenParams in request: {"type":"Signing","refreshPolicy":"UseCached","issuers":["https://issuer.example"]} diff --git a/third_party/blink/web_tests/wpt_internal/trust-tokens/trust-token-api-e2e-iframe.https.html b/third_party/blink/web_tests/wpt_internal/trust-tokens/trust-token-api-e2e-iframe.https.html index 1c666fda30a60..19e788bac7bf8 100644 --- a/third_party/blink/web_tests/wpt_internal/trust-tokens/trust-token-api-e2e-iframe.https.html +++ b/third_party/blink/web_tests/wpt_internal/trust-tokens/trust-token-api-e2e-iframe.https.html @@ -9,44 +9,23 @@