Skip to content

Commit 47771ff

Browse files
yaoxiachromiumChromium LUCI CQ
authored and
Chromium LUCI CQ
committed
[Topics] fix permissions policy behavior for fetch()
The permissions policy should follow the algorithm in https://www.w3.org/TR/permissions-policy/#algo-is-feature-enabled plus the proposed update in w3c/webappsec-permissions-policy#499. This CL: - Removes the renderer side check that checks the policy against request initiator context's origin. (I misunderstood the spec before). This also means that on permissions error, we won’t throw an exception in any case, but will just skip adding the topics header. - Calls IsFeatureEnabledForSubresourceRequest() to align with the proposed update. This has no behavior difference for now as the default feature state is `EnableForAll`, but this would fix the behavior had the default state been switched to `EnableForSelf`. The distinction was already tested in PermissionsPolicyTest.ProposedTestIsBrowsingTopicsFeatureEnabledForSubresourceRequest, thus no test for this change / we cannot easily override the default feature state outside blink. - Enforce resource_request.browsing_topics at mojom boundary at BrowsingTopicsURLLoaderService::CreateLoaderAndStart(). Bug: 1401483 Change-Id: Ibea86eb1d63997955d9ce9de8a81762c2c047318 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4111963 Reviewed-by: Josh Karlin <[email protected]> Reviewed-by: Daniel Cheng <[email protected]> Commit-Queue: Yao Xiao <[email protected]> Cr-Commit-Position: refs/heads/main@{#1087639}
1 parent afd8be5 commit 47771ff

File tree

6 files changed

+76
-57
lines changed

6 files changed

+76
-57
lines changed

chrome/browser/browsing_topics/browsing_topics_service_browsertest.cc

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,24 +1133,4 @@ IN_PROC_BROWSER_TEST_F(BrowsingTopicsBrowserTest, Fetch_Success) {
11331133
content::JsReplace("fetch($1, {browsingTopics: true})", fetch_url)));
11341134
}
11351135

1136-
IN_PROC_BROWSER_TEST_F(BrowsingTopicsBrowserTest,
1137-
Fetch_PermissionsPolicyDisabledInInitiatorContext) {
1138-
GURL main_frame_url = https_server_.GetURL(
1139-
"a.test", "/browsing_topics/empty_page_browsing_topics_none.html");
1140-
1141-
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
1142-
1143-
GURL fetch_url =
1144-
https_server_.GetURL("a.test", "/browsing_topics/empty_page.html");
1145-
1146-
content::EvalJsResult result = EvalJs(
1147-
web_contents()->GetPrimaryMainFrame(),
1148-
content::JsReplace("fetch($1, {browsingTopics: true})", fetch_url));
1149-
1150-
EXPECT_THAT(
1151-
result.error,
1152-
testing::HasSubstr("The \"browsing-topics\" Permissions Policy denied "
1153-
"the use of fetch(<url>, {browsingTopics: true})."));
1154-
}
1155-
11561136
} // namespace browsing_topics

content/browser/browsing_topics/browsing_topics_url_loader.cc

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ namespace {
2626
bool GetTopicsHeaderValueForSubresourceRequest(
2727
WeakDocumentPtr request_initiator_document,
2828
const GURL& url,
29+
const network::ResourceRequest& request,
2930
std::string& header_value) {
3031
DCHECK(header_value.empty());
3132

@@ -71,12 +72,13 @@ bool GetTopicsHeaderValueForSubresourceRequest(
7172
static_cast<RenderFrameHostImpl*>(request_initiator_frame)
7273
->permissions_policy();
7374

74-
if (!permissions_policy->IsFeatureEnabledForOrigin(
75-
blink::mojom::PermissionsPolicyFeature::kBrowsingTopics, origin) ||
76-
!permissions_policy->IsFeatureEnabledForOrigin(
75+
if (!permissions_policy->IsFeatureEnabledForSubresourceRequest(
76+
blink::mojom::PermissionsPolicyFeature::kBrowsingTopics, origin,
77+
request) ||
78+
!permissions_policy->IsFeatureEnabledForSubresourceRequest(
7779
blink::mojom::PermissionsPolicyFeature::
7880
kBrowsingTopicsBackwardCompatible,
79-
origin)) {
81+
origin, request)) {
8082
return false;
8183
}
8284

@@ -119,24 +121,21 @@ BrowsingTopicsURLLoader::BrowsingTopicsURLLoader(
119121
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory)
120122
: document_(std::move(document)),
121123
url_(resource_request.url),
124+
request_(resource_request),
122125
forwarding_client_(std::move(client)) {
123126
DCHECK(network_loader_factory);
124127

125-
network::ResourceRequest new_resource_request = resource_request;
126-
127128
std::string header_value;
128129
topics_eligible_ = GetTopicsHeaderValueForSubresourceRequest(
129-
document_, new_resource_request.url, header_value);
130+
document_, request_.url, request_, header_value);
130131

131132
if (topics_eligible_) {
132-
new_resource_request.headers.SetHeader(kBrowsingTopicsRequestHeaderKey,
133-
header_value);
133+
request_.headers.SetHeader(kBrowsingTopicsRequestHeaderKey, header_value);
134134
}
135135

136136
network_loader_factory->CreateLoaderAndStart(
137-
loader_.BindNewPipeAndPassReceiver(), request_id, options,
138-
new_resource_request, client_receiver_.BindNewPipeAndPassRemote(),
139-
traffic_annotation);
137+
loader_.BindNewPipeAndPassReceiver(), request_id, options, request_,
138+
client_receiver_.BindNewPipeAndPassRemote(), traffic_annotation);
140139

141140
client_receiver_.set_disconnect_handler(
142141
base::BindOnce(&BrowsingTopicsURLLoader::OnNetworkConnectionError,
@@ -159,8 +158,8 @@ void BrowsingTopicsURLLoader::FollowRedirect(
159158
new_removed_headers.push_back(kBrowsingTopicsRequestHeaderKey);
160159

161160
std::string header_value;
162-
topics_eligible_ =
163-
GetTopicsHeaderValueForSubresourceRequest(document_, url_, header_value);
161+
topics_eligible_ = GetTopicsHeaderValueForSubresourceRequest(
162+
document_, url_, request_, header_value);
164163

165164
if (topics_eligible_) {
166165
new_modified_headers.SetHeader(kBrowsingTopicsRequestHeaderKey,

content/browser/browsing_topics/browsing_topics_url_loader.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ class CONTENT_EXPORT BrowsingTopicsURLLoader
100100
// The current request or redirect URL.
101101
GURL url_;
102102

103+
// The initial request state. This will be used to derive the opt-in
104+
// permissions policy features for each request/redirect.
105+
network::ResourceRequest request_;
106+
103107
// Whether the ongoing request or redirect is eligible for topics. Set to the
104108
// desired state when a request/redirect is made. Reset to false when the
105109
// corresponding response is received.

content/browser/browsing_topics/browsing_topics_url_loader_service.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ void BrowsingTopicsURLLoaderService::CreateLoaderAndStart(
6262
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
6363
DCHECK_CURRENTLY_ON(BrowserThread::UI);
6464

65+
if (!resource_request.browsing_topics) {
66+
loader_factory_receivers_.ReportBadMessage(
67+
"Unexpected `resource_request` in "
68+
"BrowsingTopicsURLLoaderService::CreateLoaderAndStart(): no "
69+
"resource_request.browsing_topics");
70+
return;
71+
}
72+
6573
const std::unique_ptr<BindContext>& current_context =
6674
loader_factory_receivers_.current_context();
6775

content/browser/browsing_topics/browsing_topics_url_loader_service_unittest.cc

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44

55
#include "content/browser/browsing_topics/browsing_topics_url_loader_service.h"
66

7+
#include "base/test/bind.h"
8+
#include "base/test/scoped_feature_list.h"
79
#include "content/public/browser/browser_context.h"
810
#include "content/public/browser/navigation_entry.h"
911
#include "content/public/test/navigation_simulator.h"
1012
#include "content/public/test/test_utils.h"
1113
#include "content/public/test/web_contents_tester.h"
1214
#include "content/test/test_render_frame_host.h"
1315
#include "content/test/test_render_view_host.h"
16+
#include "mojo/public/cpp/system/functions.h"
1417
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
1518
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
1619
#include "services/network/test/test_url_loader_factory.h"
@@ -88,6 +91,10 @@ class TopicsInterceptingContentBrowserClient : public ContentBrowserClient {
8891

8992
class BrowsingTopicsURLLoaderServiceTest : public RenderViewHostTestHarness {
9093
public:
94+
BrowsingTopicsURLLoaderServiceTest() {
95+
scoped_feature_list_.InitAndEnableFeature(blink::features::kBrowsingTopics);
96+
}
97+
9198
void SetUp() override {
9299
content::RenderViewHostTestHarness::SetUp();
93100

@@ -137,9 +144,11 @@ class BrowsingTopicsURLLoaderServiceTest : public RenderViewHostTestHarness {
137144
return head;
138145
}
139146

140-
network::ResourceRequest CreateResourceRequest(const GURL& url) {
147+
network::ResourceRequest CreateResourceRequest(const GURL& url,
148+
bool browsing_topics = true) {
141149
network::ResourceRequest request;
142150
request.url = url;
151+
request.browsing_topics = browsing_topics;
143152
return request;
144153
}
145154

@@ -172,6 +181,8 @@ class BrowsingTopicsURLLoaderServiceTest : public RenderViewHostTestHarness {
172181
}
173182

174183
private:
184+
base::test::ScopedFeatureList scoped_feature_list_;
185+
175186
TopicsInterceptingContentBrowserClient browser_client_;
176187
raw_ptr<ContentBrowserClient> original_client_ = nullptr;
177188

@@ -979,4 +990,43 @@ TEST_F(BrowsingTopicsURLLoaderServiceTest, BindContextClearedDueToDisconnect) {
979990
EXPECT_FALSE(bind_context);
980991
}
981992

993+
TEST_F(BrowsingTopicsURLLoaderServiceTest, ReportBadMessageOnInvalidRequest) {
994+
NavigatePage(GURL("https://google.com"));
995+
996+
mojo::Remote<network::mojom::URLLoaderFactory> remote_url_loader_factory;
997+
network::TestURLLoaderFactory proxied_url_loader_factory;
998+
mojo::Remote<network::mojom::URLLoader> remote_loader;
999+
mojo::PendingReceiver<network::mojom::URLLoaderClient> client;
1000+
1001+
base::WeakPtr<BrowsingTopicsURLLoaderService::BindContext> bind_context =
1002+
CreateFactory(proxied_url_loader_factory, remote_url_loader_factory);
1003+
bind_context->OnDidCommitNavigation(
1004+
web_contents()->GetPrimaryMainFrame()->GetWeakDocumentPtr());
1005+
1006+
std::string received_error;
1007+
mojo::SetDefaultProcessErrorHandler(base::BindLambdaForTesting(
1008+
[&](const std::string& error) { received_error = error; }));
1009+
1010+
// Invoke CreateLoaderAndStart() with a ResourceRequest invalid for this
1011+
// factory. This will trigger a ReportBadMessage.
1012+
remote_url_loader_factory->CreateLoaderAndStart(
1013+
remote_loader.BindNewPipeAndPassReceiver(),
1014+
/*request_id=*/0, /*options=*/0,
1015+
CreateResourceRequest(GURL("https://foo1.com"),
1016+
/*browsing_topics=*/false),
1017+
client.InitWithNewPipeAndPassRemote(),
1018+
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
1019+
remote_url_loader_factory.FlushForTesting();
1020+
1021+
EXPECT_FALSE(remote_url_loader_factory.is_connected());
1022+
EXPECT_EQ(0, proxied_url_loader_factory.NumPending());
1023+
EXPECT_EQ(
1024+
"Unexpected `resource_request` in "
1025+
"BrowsingTopicsURLLoaderService::CreateLoaderAndStart(): no "
1026+
"resource_request.browsing_topics",
1027+
received_error);
1028+
1029+
mojo::SetDefaultProcessErrorHandler(base::NullCallback());
1030+
}
1031+
9821032
} // namespace content

third_party/blink/renderer/core/fetch/request.cc

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -541,28 +541,6 @@ Request* Request::CreateRequestWithRequestOrString(
541541
return nullptr;
542542
}
543543

544-
// Check the permissions policy on `execution_context` as part of the
545-
// "Should request be allowed to use feature?" algorithm
546-
// (https://www.w3.org/TR/permissions-policy/#algo-should-request-be-allowed-to-use-feature).
547-
// The check against request’s origin is done in `BrowsingTopicsURLLoader`
548-
// that is able to cover redirects.
549-
if (!execution_context->IsFeatureEnabled(
550-
mojom::blink::PermissionsPolicyFeature::kBrowsingTopics)) {
551-
exception_state.ThrowTypeError(
552-
"The \"browsing-topics\" Permissions Policy denied the use of "
553-
"fetch(<url>, {browsingTopics: true}).");
554-
return nullptr;
555-
}
556-
557-
if (!execution_context->IsFeatureEnabled(
558-
mojom::blink::PermissionsPolicyFeature::
559-
kBrowsingTopicsBackwardCompatible)) {
560-
exception_state.ThrowTypeError(
561-
"The \"interest-cohort\" Permissions Policy denied the use of "
562-
"fetch(<url>, {browsingTopics: true}).");
563-
return nullptr;
564-
}
565-
566544
request->SetBrowsingTopics(init->browsingTopics());
567545
}
568546

0 commit comments

Comments
 (0)