Skip to content

Commit

Permalink
prefetch: Call PrefetchStatusUpdated when prefetch status is set.
Browse files Browse the repository at this point in the history
This CL aims to address the cases when prefetch status is set but
SetPrefetchStatus is not used, because PrefetchStatusUpdated is
currently not called for those cases.

related doc: https://docs.google.com/document/d/11K2snJJd14NiuBUbBnO-0zsqIL2keMN-Wixd39acvb0/edit?usp=sharing

Bug: 1384419
Change-Id: Ib01a23a4ef2ec5436351e60d69de6ab71d083ba2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4531509
Commit-Queue: Huanpo Lin <robertlin@chromium.org>
Reviewed-by: Max Curran <curranmax@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1146874}
  • Loading branch information
Robert Lin authored and Chromium LUCI CQ committed May 20, 2023
1 parent 4331081 commit 92f3617
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 18 deletions.
78 changes: 60 additions & 18 deletions content/browser/preloading/prefetch/prefetch_container.cc
Expand Up @@ -120,33 +120,71 @@ PreloadingFailureReason ToPreloadingFailureReason(PrefetchStatus status) {
PreloadingFailureReason::kPreloadingFailureReasonCommonEnd));
}

absl::optional<PreloadingTriggeringOutcome> TriggeringOutcomeFromStatus(
PrefetchStatus prefetch_status) {
switch (prefetch_status) {
case PrefetchStatus::kPrefetchNotFinishedInTime:
return PreloadingTriggeringOutcome::kRunning;
case PrefetchStatus::kPrefetchSuccessful:
return PreloadingTriggeringOutcome::kReady;
case PrefetchStatus::kPrefetchResponseUsed:
return PreloadingTriggeringOutcome::kSuccess;
case PrefetchStatus::kPrefetchIsPrivacyDecoy:
case PrefetchStatus::kPrefetchFailedNetError:
case PrefetchStatus::kPrefetchFailedNon2XX:
case PrefetchStatus::kPrefetchFailedMIMENotSupported:
case PrefetchStatus::kPrefetchFailedInvalidRedirect:
case PrefetchStatus::kPrefetchFailedIneligibleRedirect:
case PrefetchStatus::kPrefetchFailedPerPageLimitExceeded:
case PrefetchStatus::kPrefetchEvicted:
return PreloadingTriggeringOutcome::kFailure;
case PrefetchStatus::kPrefetchHeldback:
case PrefetchStatus::kPrefetchAllowed:
case PrefetchStatus::kPrefetchNotStarted:
case PrefetchStatus::kPrefetchNotEligibleUserHasServiceWorker:
case PrefetchStatus::kPrefetchNotEligibleSchemeIsNotHttps:
case PrefetchStatus::kPrefetchNotEligibleNonDefaultStoragePartition:
case PrefetchStatus::kPrefetchNotEligibleHostIsNonUnique:
case PrefetchStatus::kPrefetchNotEligibleDataSaverEnabled:
case PrefetchStatus::kPrefetchNotEligibleBatterySaverEnabled:
case PrefetchStatus::kPrefetchNotEligiblePreloadingDisabled:
case PrefetchStatus::kPrefetchNotEligibleExistingProxy:
case PrefetchStatus::kPrefetchNotEligibleUserHasCookies:
case PrefetchStatus::kPrefetchIneligibleRetryAfter:
case PrefetchStatus::kPrefetchProxyNotAvailable:
case PrefetchStatus::kPrefetchNotEligibleBrowserContextOffTheRecord:
case PrefetchStatus::kPrefetchNotUsedCookiesChanged:
case PrefetchStatus::kPrefetchIsStale:
case PrefetchStatus::kPrefetchNotUsedProbeFailed:
case PrefetchStatus::
kPrefetchNotEligibleSameSiteCrossOriginPrefetchRequiredProxy:
return absl::nullopt;
}
return absl::nullopt;
}

// Please follow go/preloading-dashboard-updates if a new outcome enum or a
// failure reason enum is added.
absl::optional<PreloadingTriggeringOutcome>
SetTriggeringOutcomeAndFailureReasonFromStatus(
void SetTriggeringOutcomeAndFailureReasonFromStatus(
PreloadingAttempt* attempt,
FrameTreeNode* ftn,
const GURL& url,
absl::optional<PrefetchStatus> old_prefetch_status,
PrefetchStatus new_prefetch_status) {
if (old_prefetch_status &&
old_prefetch_status.value() == PrefetchStatus::kPrefetchResponseUsed) {
// Skip this update if the triggering outcome has already been updated
// to kSuccess.
return absl::nullopt;
return;
}

absl::optional<PreloadingTriggeringOutcome> preloading_trigger_outcome;
if (attempt) {
switch (new_prefetch_status) {
case PrefetchStatus::kPrefetchNotFinishedInTime:
preloading_trigger_outcome = PreloadingTriggeringOutcome::kRunning;
attempt->SetTriggeringOutcome(PreloadingTriggeringOutcome::kRunning);
break;
case PrefetchStatus::kPrefetchSuccessful:
// A successful prefetch means the response is ready to be used for the
// next navigation.
preloading_trigger_outcome = PreloadingTriggeringOutcome::kReady;
attempt->SetTriggeringOutcome(PreloadingTriggeringOutcome::kReady);
break;
case PrefetchStatus::kPrefetchResponseUsed:
Expand All @@ -160,7 +198,6 @@ SetTriggeringOutcomeAndFailureReasonFromStatus(
// before the body is fully received.
attempt->SetTriggeringOutcome(PreloadingTriggeringOutcome::kReady);
}
preloading_trigger_outcome = PreloadingTriggeringOutcome::kSuccess;
attempt->SetTriggeringOutcome(PreloadingTriggeringOutcome::kSuccess);
break;
// A decoy is considered eligible because a network request is made for
Expand All @@ -177,7 +214,6 @@ SetTriggeringOutcomeAndFailureReasonFromStatus(
// the initial prefetch succeeded, consider introducing a different
// PreloadingTriggerOutcome for eviction.
case PrefetchStatus::kPrefetchEvicted:
preloading_trigger_outcome = PreloadingTriggeringOutcome::kFailure;
attempt->SetFailureReason(
ToPreloadingFailureReason(new_prefetch_status));
break;
Expand Down Expand Up @@ -214,7 +250,6 @@ SetTriggeringOutcomeAndFailureReasonFromStatus(
NOTIMPLEMENTED();
}
}
return preloading_trigger_outcome;
}

std::string GetEagernessHistogramSuffix(
Expand Down Expand Up @@ -324,16 +359,14 @@ PrefetchContainer::~PrefetchContainer() {
builder.Record(ukm::UkmRecorder::Get());
}

void PrefetchContainer::SetPrefetchStatus(PrefetchStatus prefetch_status) {
void PrefetchContainer::SetPrefetchStatusWithoutUpdatingTriggeringOutcome(
PrefetchStatus prefetch_status) {
prefetch_status_ = prefetch_status;
FrameTreeNode* ftn = FrameTreeNode::From(
RenderFrameHostImpl::FromID(referring_render_frame_host_id_));

absl::optional<PreloadingTriggeringOutcome> preloading_trigger_outcome =
SetTriggeringOutcomeAndFailureReasonFromStatus(
attempt_.get(), ftn, prefetch_url_,
/*old_prefetch_status=*/prefetch_status_,
/*new_prefetch_status=*/prefetch_status);
prefetch_status_ = prefetch_status;
TriggeringOutcomeFromStatus(prefetch_status);

if (initiator_devtools_navigation_token_.has_value() &&
preloading_trigger_outcome.has_value()) {
Expand All @@ -343,6 +376,14 @@ void PrefetchContainer::SetPrefetchStatus(PrefetchStatus prefetch_status) {
}
}

void PrefetchContainer::SetPrefetchStatus(PrefetchStatus prefetch_status) {
SetTriggeringOutcomeAndFailureReasonFromStatus(
attempt_.get(), prefetch_url_,
/*old_prefetch_status=*/prefetch_status_,
/*new_prefetch_status=*/prefetch_status);
SetPrefetchStatusWithoutUpdatingTriggeringOutcome(prefetch_status);
}

PrefetchStatus PrefetchContainer::GetPrefetchStatus() const {
DCHECK(prefetch_status_);
return prefetch_status_.value();
Expand Down Expand Up @@ -423,7 +464,7 @@ void PrefetchContainer::OnEligibilityCheckComplete(
if (!is_eligible) {
// Expect a reason (status) if not eligible.
DCHECK(status.has_value());
prefetch_status_ = status;
SetPrefetchStatusWithoutUpdatingTriggeringOutcome(status.value());
}

if (attempt_) {
Expand Down Expand Up @@ -647,7 +688,8 @@ void PrefetchContainer::OnPrefetchProbeResult(
break;
case PrefetchProbeResult::kDNSProbeFailure:
case PrefetchProbeResult::kTLSProbeFailure:
prefetch_status_ = PrefetchStatus::kPrefetchNotUsedProbeFailed;
SetPrefetchStatusWithoutUpdatingTriggeringOutcome(
PrefetchStatus::kPrefetchNotUsedProbeFailed);
break;
default:
NOTIMPLEMENTED();
Expand Down
5 changes: 5 additions & 0 deletions content/browser/preloading/prefetch/prefetch_container.h
Expand Up @@ -303,6 +303,11 @@ class CONTENT_EXPORT PrefetchContainer {
const network::mojom::URLResponseHead* head);

private:
// Update |prefetch_status_| and report prefetch status to
// DevTools without updating TriggeringOutcome.
void SetPrefetchStatusWithoutUpdatingTriggeringOutcome(
PrefetchStatus prefetch_status);

// Holds the state for the request for a single URL in the context of the
// broader prefetch. A prefetch can request multiple URLs due to redirects.
class SinglePrefetch {
Expand Down

0 comments on commit 92f3617

Please sign in to comment.