EarlyHints: Fix false alarms for unused early hints in devtools

Resources directly reused from the blink cache was not correctly marked
as used early hints. The CL eliminates the false alarm in the devtools.

Bug: 40222701
Change-Id: I76529ce0f5026f0186383e3d98fdd5d62c0f0199
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5340286
Commit-Queue: Jiacheng Guo <gjc@google.com>
Reviewed-by: Kouhei Ueno <kouhei@chromium.org>
Auto-Submit: Jiacheng Guo <gjc@google.com>
Reviewed-by: Kenichi Ishibashi <bashi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1269273}
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index 8d2f9b2..0075b08 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -786,12 +786,12 @@
     final_response.SetEncodedDataLength(0);
     // Resources loaded from memory cache should be reported the first time
     // they're used.
-    mojom::blink::ResourceTimingInfoPtr info = CreateResourceTimingInfo(
-        now,
+    KURL initial_url =
         resource->GetResourceRequest().GetRedirectInfo().has_value()
             ? resource->GetResourceRequest().GetRedirectInfo()->original_url
-            : resource->GetResourceRequest().Url(),
-        &final_response);
+            : resource->GetResourceRequest().Url();
+    mojom::blink::ResourceTimingInfoPtr info =
+        CreateResourceTimingInfo(now, initial_url, &final_response);
     info->response_end = now;
     info->render_blocking_status =
         render_blocking_behavior == RenderBlockingBehavior::kBlocking;
@@ -808,8 +808,12 @@
       }
     }
 
-    scheduled_resource_timing_reports_.push_back(ScheduledResourceTimingInfo{
-        std::move(info), resource->Options().initiator_info.name});
+    AtomicString initiator_type = resource->Options().initiator_info.name;
+    MarkEarlyHintConsumedAndOverrideInitiatorTypeIfNeeded(initial_url, resource,
+                                                          &initiator_type);
+    scheduled_resource_timing_reports_.push_back(
+        ScheduledResourceTimingInfo{std::move(info), initiator_type});
+
     if (!resource_timing_report_timer_.IsActive())
       resource_timing_report_timer_.StartOneShot(base::TimeDelta(), FROM_HERE);
   }
@@ -2031,8 +2035,9 @@
   // If preloads_ is not empty here, it's full of link
   // preloads, as speculative preloads should have already been cleared when
   // parsing finished.
-  if (preloads_.empty() && early_hints_preloaded_resources_.empty())
+  if (preloads_.empty() && unused_early_hints_preloaded_resources_.empty()) {
     return;
+  }
   unused_preloads_timer_ = PostDelayedCancellableTask(
       *freezable_task_runner_, FROM_HERE,
       WTF::BindOnce(&ResourceFetcher::WarnUnusedPreloads,
@@ -2078,7 +2083,7 @@
   base::UmaHistogramCounts100("Renderer.Preload.UnusedResourceCount",
                               unused_resource_count);
 
-  for (auto& pair : early_hints_preloaded_resources_) {
+  for (auto& pair : unused_early_hints_preloaded_resources_) {
     if (pair.value.state == EarlyHintsPreloadEntry::State::kWarnedUnused)
       continue;
 
@@ -2690,18 +2695,8 @@
           ? resource->GetResourceRequest().GetRedirectInfo()->original_url
           : resource->GetResourceRequest().Url();
 
-  auto pair = early_hints_preloaded_resources_.find(initial_url);
-  if (pair != early_hints_preloaded_resources_.end()) {
-    early_hints_preloaded_resources_.erase(pair);
-    const ResourceResponse& response = resource->GetResponse();
-    if (!response.NetworkAccessed() &&
-        (!response.WasFetchedViaServiceWorker() ||
-         response.IsServiceWorkerPassThrough())) {
-      initiator_type = AtomicString("early-hints");
-      resource->SetIsPreloadedByEarlyHints();
-    }
-  }
-
+  MarkEarlyHintConsumedAndOverrideInitiatorTypeIfNeeded(initial_url, resource,
+                                                        &initiator_type);
   mojom::blink::ResourceTimingInfoPtr info = CreateResourceTimingInfo(
       pending_info.start_time, initial_url, &resource->GetResponse());
   if (info->allow_timing_details) {
@@ -2801,6 +2796,26 @@
                               potentially_lcp_resource_priority_boosts_);
 }
 
+void ResourceFetcher::MarkEarlyHintConsumedAndOverrideInitiatorTypeIfNeeded(
+    const KURL& resource_initial_url,
+    Resource* resource,
+    AtomicString* origin_initiator_type) {
+  auto iter =
+      unused_early_hints_preloaded_resources_.find(resource_initial_url);
+  if (iter != unused_early_hints_preloaded_resources_.end()) {
+    unused_early_hints_preloaded_resources_.erase(iter);
+    const ResourceResponse& response = resource->GetResponse();
+    // The network service may not reuse the response fetched by the early hints
+    // due to cache control policies.
+    if (!response.NetworkAccessed() &&
+        (!response.WasFetchedViaServiceWorker() ||
+         response.IsServiceWorkerPassThrough())) {
+      *origin_initiator_type = AtomicString("early-hints");
+      resource->SetIsPreloadedByEarlyHints();
+    }
+  }
+}
+
 void ResourceFetcher::Trace(Visitor* visitor) const {
   visitor->Trace(context_);
   visitor->Trace(properties_);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
index 7f7699fb..3da6118 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -352,7 +352,7 @@
 
   void SetEarlyHintsPreloadedResources(
       HashMap<KURL, EarlyHintsPreloadEntry> resources) {
-    early_hints_preloaded_resources_ = std::move(resources);
+    unused_early_hints_preloaded_resources_ = std::move(resources);
   }
 
   // Access the UKMRecorder.
@@ -444,6 +444,11 @@
 
   void MaybeSaveResourceToStrongReference(Resource* resource);
 
+  void MarkEarlyHintConsumedAndOverrideInitiatorTypeIfNeeded(
+      const KURL& resource_inital_url,
+      Resource* resource,
+      AtomicString* origin_initiator_type);
+
   enum class RevalidationPolicy {
     kUse,
     kRevalidate,
@@ -606,7 +611,7 @@
   HeapHashSet<Member<ResourceLoader>> loaders_;
   HeapHashSet<Member<ResourceLoader>> non_blocking_loaders_;
 
-  HashMap<KURL, EarlyHintsPreloadEntry> early_hints_preloaded_resources_;
+  HashMap<KURL, EarlyHintsPreloadEntry> unused_early_hints_preloaded_resources_;
 
   std::unique_ptr<HashSet<String>> preloaded_urls_for_test_;