1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
content / browser / interest_group / ad_auction_url_loader_interceptor.cc [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/interest_group/ad_auction_url_loader_interceptor.h"
#include <string>
#include <vector>
#include "base/metrics/histogram_functions.h"
#include "content/browser/interest_group/ad_auction_headers_util.h"
#include "content/browser/interest_group/ad_auction_page_data.h"
#include "content/public/browser/page_user_data.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/weak_document_ptr.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/redirect_info.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/url_response_head.mojom-forward.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace content {
AdAuctionURLLoaderInterceptor::AdAuctionURLLoaderInterceptor(
WeakDocumentPtr document,
const network::ResourceRequest& resource_request)
: document_(document),
resource_request_(resource_request),
request_origin_(url::Origin::Create(resource_request.url)) {
CHECK(resource_request_->ad_auction_headers);
}
AdAuctionURLLoaderInterceptor::~AdAuctionURLLoaderInterceptor() = default;
void AdAuctionURLLoaderInterceptor::WillStartRequest(
net::HttpRequestHeaders& headers) {
// Due to the race between the subresource requests and navigations, this
// request may arrive before the commit confirmation is received (i.e.
// NavigationRequest::DidCommitNavigation()), or after the document is
// destroyed. We consider those cases to be ineligible for ad auction headers.
RenderFrameHostImpl* request_initiator_frame =
static_cast<RenderFrameHostImpl*>(document_.AsRenderFrameHostIfValid());
if (!request_initiator_frame) {
base::UmaHistogramEnumeration(
"Ads.InterestGroup.NetHeaderResponse.StartRequestOutcome",
AdAuctionHeadersIsEligibleOutcomeForMetrics::kNoInitiatorFrame);
return;
}
if (!IsAdAuctionHeadersEligible(*request_initiator_frame,
*resource_request_)) {
return;
}
ad_auction_headers_eligible_ = true;
headers.SetHeader(kAdAuctionRequestHeaderKey, "?1");
// Pre-warm the data-decoder.
AdAuctionPageData* ad_auction_page_data =
PageUserData<AdAuctionPageData>::GetOrCreateForPage(
request_initiator_frame->GetPage());
ad_auction_page_data->GetDecoderFor(request_origin_)->GetService();
}
void AdAuctionURLLoaderInterceptor::OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
network::mojom::URLResponseHeadPtr& head) {
ad_auction_headers_eligible_ = false;
RemoveAdAuctionResponseHeaders(head->headers);
}
void AdAuctionURLLoaderInterceptor::WillFollowRedirect(
const std::optional<GURL>& new_url,
std::vector<std::string>& removed_headers,
net::HttpRequestHeaders& modified_headers) {
CHECK(!ad_auction_headers_eligible_);
removed_headers.push_back(kAdAuctionRequestHeaderKey);
}
void AdAuctionURLLoaderInterceptor::OnReceiveResponse(
network::mojom::URLResponseHeadPtr& head) {
RenderFrameHost* request_initiator_frame =
document_.AsRenderFrameHostIfValid();
if (ad_auction_headers_eligible_ && request_initiator_frame) {
ProcessAdAuctionResponseHeaders(
request_origin_, request_initiator_frame->GetPage(), head->headers);
} else {
RemoveAdAuctionResponseHeaders(head->headers);
}
}
} // namespace content