Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion crates/trusted-server-core/src/integrations/gpt_bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
// and deliberately identical to the bundle scheduler — the impression is
// spent on a viewed tab, and the post-hydration guarantee holds whenever
// the request is actually issued.
ts.scheduleInitialAdInit = function (initialBids, initialSlots) {
ts.scheduleInitialAdInit = function (initialBids, initialSlots, initialAuctionDiagnostics) {
// The bundle may replace this scheduler after the fallback claims the initial
// pass. Keep the latch on the shared document API so replacement cannot reset it.
if ((ts.navGeneration || 0) !== 0 || ts.initialAdInitScheduled) return;
Expand All @@ -127,6 +127,9 @@
// would overwrite a committed SPA navigation's slots.
if (initialSlots !== undefined) ts.adSlots = initialSlots;
if (initialBids !== undefined) ts.bids = initialBids;
if (initialAuctionDiagnostics !== undefined) {
ts.auctionDiagnostics = initialAuctionDiagnostics;
}
var fire = function () {
if ((ts.navGeneration || 0) !== 0) return;
if (typeof ts.adInit === "function") ts.adInit();
Expand Down
38 changes: 37 additions & 1 deletion crates/trusted-server-core/src/integrations/gpt_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ pub enum GptDiagnosticsCookieAction {
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct GptDiagnosticsRequestDecision {
active: bool,
browser_session_active: bool,
clean_browser_path_and_query: Option<String>,
cookie_action: GptDiagnosticsCookieAction,
}
Expand All @@ -73,6 +74,16 @@ impl GptDiagnosticsRequestDecision {
self.active
}

/// Whether this request came from an activated diagnostics browser session.
///
/// Unlike [`Self::active`], this remains true for non-document requests such
/// as the SPA page-bids fetch. It is captured before the private activation
/// cookie is stripped from the request.
#[must_use]
pub(crate) fn browser_session_active(&self) -> bool {
self.browser_session_active
}

/// Whether the response must be private and non-storeable.
#[must_use]
pub fn requires_private_no_store(&self) -> bool {
Expand Down Expand Up @@ -121,6 +132,7 @@ impl GptDiagnosticsRequestDecision {
pub(crate) fn active_for_tests() -> Self {
Self {
active: true,
browser_session_active: true,
clean_browser_path_and_query: None,
cookie_action: GptDiagnosticsCookieAction::None,
}
Expand All @@ -143,6 +155,7 @@ mod head_seam_invariant_tests {
] {
out.push(GptDiagnosticsRequestDecision {
active,
browser_session_active: active,
clean_browser_path_and_query: clean.clone(),
cookie_action,
});
Expand Down Expand Up @@ -279,12 +292,19 @@ pub fn prepare_request(
replace_path_and_query(request, &clean_path)?;
}

let mut decision = GptDiagnosticsRequestDecision::default();
let mut decision = GptDiagnosticsRequestDecision {
browser_session_active: integration_enabled
&& directive == QueryDirective::Absent
&& cookie_state.occurrences == 1
&& cookie_state.canonical,
..GptDiagnosticsRequestDecision::default()
};
if integration_enabled && eligible_navigation && had_reserved_query {
decision.clean_browser_path_and_query = Some(clean_path);
match directive {
QueryDirective::Enable => {
decision.active = true;
decision.browser_session_active = true;
decision.cookie_action = GptDiagnosticsCookieAction::SetSession;
}
QueryDirective::Disable => {
Expand Down Expand Up @@ -542,6 +562,22 @@ mod tests {
assert_eq!(duplicate.headers()[header::COOKIE], "other=value");
}

#[test]
fn active_cookie_marks_non_document_requests_without_activating_document_behavior() {
let mut request = Request::builder()
.method(Method::GET)
.uri("https://publisher.example/_ts/page-bids?path=/article")
.header(header::COOKIE, "__Host-ts-console=1; other=value")
.body(EdgeBody::empty())
.expect("should build page-bids request");

let decision = prepare_request(&settings(true), &mut request).expect("should prepare");

assert!(!decision.active());
assert!(decision.browser_session_active());
assert_eq!(request.headers()[header::COOKIE], "other=value");
}

#[test]
fn invalid_duplicate_and_disable_directives_fail_closed() {
for query in [
Expand Down
Loading
Loading