Prerender: Introduce PrerenderCancellationReason

I think a nested cancellation reason is needed, as many final status
actually cover more than one cases, and a detailed reason is expected
to be recorded in UMA and sent to devtools.
For example:
- MojoBinderPolicy covers many interfaces.
- kInactivePageRestriction covers many disallow activation reasons.
- [To be added] navigation parameters might mismatch, and we will fail
  the activation, wanting to know the parameter that causes the
  failure.

Currently, we are handling these reasons in the following way:
1. introduce another function to record the detailed reason.
2. when cancelling prerendering for reason X, we:
  2.1 Call the function to record metrics.
  2.2 Send a message to devtools
  2.3 Add an exception into the place where we send messages to
      devtools to ignore reason X.
3. Cancel prerendering

With PrerenderCancellationReason, we can:
1. Keep as many as metric logics inside prerender_metrics.cc, rather
than exposing many recording functions.
2. Make it simpler to send the detailed reasons to devtools without
adding many exceptions.

Bug: 1377230
Change-Id: I7114929915fee7d03c74e891498a293caec615b4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3898651
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
Reviewed-by: Rakina Zata Amni <rakina@chromium.org>
Reviewed-by: Asami Doi <asamidoi@chromium.org>
Commit-Queue: Lingqi Chi <lingqi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1074452}
diff --git a/content/browser/preloading/prerender/prerender_host_registry.cc b/content/browser/preloading/prerender/prerender_host_registry.cc
index bf95f96..b15906c 100644
--- a/content/browser/preloading/prerender/prerender_host_registry.cc
+++ b/content/browser/preloading/prerender/prerender_host_registry.cc
@@ -394,6 +394,13 @@
 
 bool PrerenderHostRegistry::CancelHost(int frame_tree_node_id,
                                        PrerenderFinalStatus final_status) {
+  return CancelHost(frame_tree_node_id,
+                    PrerenderCancellationReason(final_status));
+}
+
+bool PrerenderHostRegistry::CancelHost(
+    int frame_tree_node_id,
+    const PrerenderCancellationReason& reason) {
   TRACE_EVENT1("navigation", "PrerenderHostRegistry::CancelHost",
                "frame_tree_node_id", frame_tree_node_id);
 
@@ -406,6 +413,9 @@
   if (iter == prerender_host_by_frame_tree_node_id_.end())
     return false;
 
+  reason.ReportMetrics(iter->second->trigger_type(),
+                       iter->second->embedder_histogram_suffix());
+
   // Remove the prerender host from the host map so that it's not used for
   // activation during asynchronous deletion.
 
@@ -413,7 +423,8 @@
   prerender_host_by_frame_tree_node_id_.erase(iter);
 
   // Asynchronously delete the prerender host.
-  ScheduleToDeleteAbandonedHost(std::move(prerender_host), final_status);
+  ScheduleToDeleteAbandonedHost(std::move(prerender_host),
+                                reason.final_status());
 
   // Start another prerender if the running prerender is cancelled.
   if (running_prerender_host_id_ == frame_tree_node_id) {