Update navigation.entries() and navigation.activation on prerender activation

We currently have plumbing for updating entries() on bfcache restore.
This reuses that plumbing for prerender activation.

This also ensures that we set `navigation.activation.from` correctly
in a prerendered document before activation (it should be the entry
that initiated the preload).

Bug: 1212819
Change-Id: I5835313b0d713e10802b3df442bb16e4d813f464
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5013956
Reviewed-by: Rakina Zata Amni <[email protected]>
Reviewed-by: Nasko Oskov <[email protected]>
Reviewed-by: Domenic Denicola <[email protected]>
Commit-Queue: Nate Chapin <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1226462}
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index eb0a0559..3e96978 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -62,6 +62,7 @@
 #include "content/browser/browser_url_handler_impl.h"
 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
+#include "content/browser/preloading/prerender/prerender_host.h"
 #include "content/browser/process_lock.h"
 #include "content/browser/renderer_host/back_forward_cache_impl.h"
 #include "content/browser/renderer_host/debug_urls.h"
@@ -4696,23 +4697,36 @@
 
   // If the previous entry is within the block of contiguous entries being
   // provided, then report it as the `previous_entry`.
-  if (GetLastCommittedEntryIndex() != -1 &&
-      GetLastCommittedEntryIndex() >= backmost_index &&
-      GetLastCommittedEntryIndex() <= forwardmost_index) {
-    if (auto* frame_entry = GetLastCommittedEntry()->GetFrameEntry(node)) {
-      url::Origin frame_entry_origin =
-          frame_entry->committed_origin().value_or(url::Origin::Resolve(
-              frame_entry->url(),
-              frame_entry->initiator_origin().value_or(url::Origin())));
-      // TODO(crbug.com/1209092): Move this into ToNavigationApiHistoryEntry()
-      // once we can be sure that entries with the same ISN will never be
-      // cross-origin.
-      if (pending_origin.IsSameOriginWith(frame_entry_origin)) {
-        entry_arrays->previous_entry = ToNavigationApiHistoryEntry(
-            frame_entry, pending_document_sequence_number);
-      }
+  FrameNavigationEntry* previous_entry = nullptr;
+  if (frame_tree_->is_prerendering()) {
+    int initiator_id = PrerenderHost::GetFromFrameTreeNode(*node)
+                           .initiator_frame_tree_node_id();
+    if (initiator_id != RenderFrameHost::kNoFrameTreeNodeId) {
+      auto* initiator_node = FrameTreeNode::GloballyFindByID(initiator_id);
+      previous_entry = initiator_node->frame_tree()
+                           .controller()
+                           .GetLastCommittedEntry()
+                           ->GetFrameEntry(initiator_node);
+    }
+  } else if (GetLastCommittedEntryIndex() != -1 &&
+             GetLastCommittedEntryIndex() >= backmost_index &&
+             GetLastCommittedEntryIndex() <= forwardmost_index) {
+    previous_entry = GetLastCommittedEntry()->GetFrameEntry(node);
+  }
+  if (previous_entry) {
+    url::Origin previous_entry_origin =
+        previous_entry->committed_origin().value_or(url::Origin::Resolve(
+            previous_entry->url(),
+            previous_entry->initiator_origin().value_or(url::Origin())));
+    // TODO(crbug.com/1209092): Move this into ToNavigationApiHistoryEntry()
+    // once we can be sure that entries with the same ISN will never be
+    // cross-origin.
+    if (pending_origin.IsSameOriginWith(previous_entry_origin)) {
+      entry_arrays->previous_entry = ToNavigationApiHistoryEntry(
+          previous_entry, pending_document_sequence_number);
     }
   }
+
   return entry_arrays;
 }
 
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 84ffb00..a50bb963 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -5930,7 +5930,8 @@
                                                                   : nullptr);
           rfh->GetAssociatedLocalFrame()
               ->SetNavigationApiHistoryEntriesForRestore(
-                  std::move(entry_arrays));
+                  std::move(entry_arrays),
+                  blink::mojom::NavigationApiEntryRestoreReason::kBFCache);
           return RenderFrameHost::FrameIterationAction::kContinue;
         });
 
@@ -6022,6 +6023,33 @@
     stored_page->SetViewTransitionState(
         std::exchange(commit_params_->view_transition_state, {}));
 
+    // Update navigation API entries. A prerendered page has only a single
+    // history entry, but now it has access to a full back/forward list.
+    rfh->ForEachRenderFrameHostWithAction([this, &stored_page](
+                                              RenderFrameHostImpl* rfh) {
+      // Currently, prerender activation only happens for DIFFERENT_DOCUMENT
+      // navigations. If that ever changes, `reason` calculation will need to be
+      // updated (and new NavigationApiEntryRestoreReason values added).
+      DCHECK_EQ(common_params_->navigation_type,
+                blink::mojom::NavigationType::DIFFERENT_DOCUMENT);
+      blink::mojom::NavigationApiEntryRestoreReason reason =
+          common_params_->should_replace_current_entry
+              ? blink::mojom::NavigationApiEntryRestoreReason::
+                    kPrerenderActivationReplace
+              : blink::mojom::NavigationApiEntryRestoreReason::
+                    kPrerenderActivationPush;
+      // |this| is given as a parameter to
+      // GetNavigationApiHistoryEntryVectors() only for the frame being
+      // committed (i.e., the top frame).
+      auto entry_arrays =
+          rfh->frame_tree()->controller().GetNavigationApiHistoryEntryVectors(
+              rfh->frame_tree_node(),
+              stored_page->render_frame_host() == rfh ? this : nullptr);
+      rfh->GetAssociatedLocalFrame()->SetNavigationApiHistoryEntriesForRestore(
+          std::move(entry_arrays), reason);
+      return RenderFrameHost::FrameIterationAction::kContinue;
+    });
+
     // Move the StoredPage into RenderFrameHostManager, in
     // preparation for committing. This entry may be used for prerendering.
     frame_tree_node_->render_manager()->ActivatePrerender(
diff --git a/content/public/test/fake_local_frame.cc b/content/public/test/fake_local_frame.cc
index ad5be22..f0ee1ae1 100644
--- a/content/public/test/fake_local_frame.cc
+++ b/content/public/test/fake_local_frame.cc
@@ -186,7 +186,8 @@
     base::OnceCallback<void(blink::mojom::OpenGraphMetadataPtr)>) {}
 
 void FakeLocalFrame::SetNavigationApiHistoryEntriesForRestore(
-    blink::mojom::NavigationApiHistoryEntryArraysPtr entry_arrays) {}
+    blink::mojom::NavigationApiHistoryEntryArraysPtr entry_arrays,
+    blink::mojom::NavigationApiEntryRestoreReason restore_reason) {}
 
 void FakeLocalFrame::NotifyNavigationApiOfDisposedEntries(
     const std::vector<std::string>& keys) {}
diff --git a/content/public/test/fake_local_frame.h b/content/public/test/fake_local_frame.h
index 6cc4e78..c00d9ffa 100644
--- a/content/public/test/fake_local_frame.h
+++ b/content/public/test/fake_local_frame.h
@@ -141,7 +141,8 @@
   void GetOpenGraphMetadata(
       base::OnceCallback<void(blink::mojom::OpenGraphMetadataPtr)>) override;
   void SetNavigationApiHistoryEntriesForRestore(
-      blink::mojom::NavigationApiHistoryEntryArraysPtr entry_arrays) override;
+      blink::mojom::NavigationApiHistoryEntryArraysPtr entry_arrays,
+      blink::mojom::NavigationApiEntryRestoreReason restore_reason) override;
   void NotifyNavigationApiOfDisposedEntries(
       const std::vector<std::string>& keys) override;
   void TraverseCancelled(const std::string& navigation_api_key,
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom
index 0c95a61e..9dde108 100644
--- a/third_party/blink/public/mojom/frame/frame.mojom
+++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -177,6 +177,12 @@
   kFencedframe
 };
 
+enum NavigationApiEntryRestoreReason {
+  kBFCache,
+  kPrerenderActivationPush,
+  kPrerenderActivationReplace
+};
+
 // The maximum number of characters of the document's title that we're willing
 // to accept in the browser process.
 const uint16 kMaxTitleChars = 4096; // 4 * 1024;
@@ -1080,7 +1086,8 @@
   // to this frame, and that subset may have changed while the page was in
   // bfcache.
   SetNavigationApiHistoryEntriesForRestore(
-      NavigationApiHistoryEntryArrays entry_arrays);
+      NavigationApiHistoryEntryArrays entry_arrays,
+      NavigationApiEntryRestoreReason restore_reason);
 
   // Updates navigation.entries() when entries are disposed from the session
   // history.
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
index f6bf6ab..1f23f15 100644
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -1138,8 +1138,10 @@
 }
 
 void LocalFrameMojoHandler::SetNavigationApiHistoryEntriesForRestore(
-    mojom::blink::NavigationApiHistoryEntryArraysPtr entry_arrays) {
-  frame_->DomWindow()->navigation()->SetEntriesForRestore(entry_arrays);
+    mojom::blink::NavigationApiHistoryEntryArraysPtr entry_arrays,
+    mojom::blink::NavigationApiEntryRestoreReason restore_reason) {
+  frame_->DomWindow()->navigation()->SetEntriesForRestore(entry_arrays,
+                                                          restore_reason);
 }
 
 void LocalFrameMojoHandler::NotifyNavigationApiOfDisposedEntries(
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
index 1804ed1b..88dc4a3 100644
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
@@ -195,7 +195,8 @@
   void GetOpenGraphMetadata(GetOpenGraphMetadataCallback callback) final;
 
   void SetNavigationApiHistoryEntriesForRestore(
-      mojom::blink::NavigationApiHistoryEntryArraysPtr) final;
+      mojom::blink::NavigationApiHistoryEntryArraysPtr,
+      mojom::blink::NavigationApiEntryRestoreReason) final;
   void NotifyNavigationApiOfDisposedEntries(
       const WTF::Vector<WTF::String>&) final;
   void TraverseCancelled(const String& navigation_api_key,
diff --git a/third_party/blink/renderer/core/navigation_api/navigation_api.cc b/third_party/blink/renderer/core/navigation_api/navigation_api.cc
index 89f9d0c..14cdd73b 100644
--- a/third_party/blink/renderer/core/navigation_api/navigation_api.cc
+++ b/third_party/blink/renderer/core/navigation_api/navigation_api.cc
@@ -38,6 +38,7 @@
 #include "third_party/blink/renderer/core/navigation_api/navigation_destination.h"
 #include "third_party/blink/renderer/core/navigation_api/navigation_history_entry.h"
 #include "third_party/blink/renderer/core/navigation_api/navigation_transition.h"
+#include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/timing/soft_navigation_heuristics.h"
 #include "third_party/blink/renderer/platform/bindings/exception_context.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -127,8 +128,10 @@
       previous_history_entry = MakeEntryFromItem(*previous_item);
     }
   }
-  activation_->Update(currentEntry(), previous_history_entry,
-                      DetermineNavigationType(load_type));
+  String navigation_type = window_->GetFrame()->GetPage()->IsPrerendering()
+                               ? "push"
+                               : DetermineNavigationType(load_type);
+  activation_->Update(currentEntry(), previous_history_entry, navigation_type);
 }
 
 NavigationHistoryEntry* NavigationApi::GetExistingEntryFor(const String& key,
@@ -304,7 +307,8 @@
 }
 
 void NavigationApi::SetEntriesForRestore(
-    const mojom::blink::NavigationApiHistoryEntryArraysPtr& entry_arrays) {
+    const mojom::blink::NavigationApiHistoryEntryArraysPtr& entry_arrays,
+    mojom::blink::NavigationApiEntryRestoreReason restore_reason) {
   // If this window HasEntriesAndEventsDisabled(), we shouldn't attempt to
   // restore anything.
   if (HasEntriesAndEventsDisabled())
@@ -325,9 +329,27 @@
       base::checked_cast<wtf_size_t>(entry_arrays->back_entries.size());
   keys_to_indices_.clear();
   PopulateKeySet();
+
+  String navigation_type;
+  switch (restore_reason) {
+    case mojom::blink::NavigationApiEntryRestoreReason::kBFCache:
+      navigation_type = "traverse";
+      break;
+    case mojom::blink::NavigationApiEntryRestoreReason::
+        kPrerenderActivationPush:
+      navigation_type = "push";
+      break;
+    case mojom::blink::NavigationApiEntryRestoreReason::
+        kPrerenderActivationReplace:
+      navigation_type = "replace";
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
   activation_->Update(currentEntry(),
                       GetEntryForRestore(entry_arrays->previous_entry),
-                      "traverse");
+                      navigation_type);
 
   // |new_entries| now contains the previous entries_. Find the ones that are no
   // longer in entries_ so they can be disposed.
diff --git a/third_party/blink/renderer/core/navigation_api/navigation_api.h b/third_party/blink/renderer/core/navigation_api/navigation_api.h
index c9f8be4..19e9c38 100644
--- a/third_party/blink/renderer/core/navigation_api/navigation_api.h
+++ b/third_party/blink/renderer/core/navigation_api/navigation_api.h
@@ -53,7 +53,8 @@
                               HistoryItem* previous_entry);
   void UpdateForNavigation(HistoryItem&, WebFrameLoadType);
   void SetEntriesForRestore(
-      const mojom::blink::NavigationApiHistoryEntryArraysPtr&);
+      const mojom::blink::NavigationApiHistoryEntryArraysPtr&,
+      mojom::blink::NavigationApiEntryRestoreReason);
 
   // The entries indicated by |keys| have been removed from the session history
   // in the browser process and should be disposed. In many cases, this won't
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/navigation-api-location-replace.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/navigation-api-location-replace.html
new file mode 100644
index 0000000..e3ecf1b7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/navigation-api-location-replace.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js"></script>
+<script src="../resources/utils.js"></script>
+<script src="resources/utils.js"></script>
+
+<body>
+<script>
+setup(() => assertSpeculationRulesIsSupported());
+
+promise_test(async t => {
+  const rcHelper = new RemoteContextHelper();
+  const referrerRC = await rcHelper.addWindow(undefined, { features: 'noopener' });
+  assert_equals(await referrerRC.executeScript(() => navigation.entries().length), 1);
+  let referrerRCCurrentId = await referrerRC.executeScript(() => navigation.currentEntry.id);
+
+  const prerenderedRC = await addPrerenderRC(referrerRC);
+  let activationStateBeforeActivation = await prerenderedRC.executeScript(() => {
+    return {
+     entries: navigation.entries().map(e => ({ id: e.id, })),
+     activationEntryId: navigation.activation.entry?.id,
+     activationFromId: navigation.activation.from?.id,
+     activationNavigationType : navigation.activation.navigationType,
+    }
+  });
+  assert_equals(activationStateBeforeActivation.entries.length, 1);
+  assert_equals(activationStateBeforeActivation.activationFromId, referrerRCCurrentId);
+  assert_equals(activationStateBeforeActivation.activationEntryId, activationStateBeforeActivation.entries[0].id);
+  assert_equals(activationStateBeforeActivation.activationNavigationType, "push");
+
+  // Save the current entry before activation.
+  await prerenderedRC.executeScript(() => window.currentEntryBeforeActivation = navigation.currentEntry);
+
+  await activatePrerenderRC(referrerRC, prerenderedRC, url => {
+    location.replace(url);
+  });
+
+  let activationStateAfterActivation = await prerenderedRC.executeScript(() => {
+    return {
+     entries: navigation.entries().map(e => ({ id: e.id, })),
+     activationEntryId: navigation.activation.entry?.id,
+     activationFromId: navigation.activation.from?.id,
+     activationNavigationType : navigation.activation.navigationType,
+    }
+  });
+  assert_equals(activationStateAfterActivation.entries.length, 1);
+  assert_equals(activationStateAfterActivation.activationFromId, referrerRCCurrentId);
+  assert_equals(activationStateAfterActivation.activationEntryId, activationStateAfterActivation.entries[0].id);
+  assert_equals(activationStateAfterActivation.activationNavigationType, "replace");
+
+  let currentEntryIdentity = await prerenderedRC.executeScript(() => {
+    return window.currentEntryBeforeActivation === navigation.currentEntry &&
+           navigation.currentEntry === navigation.entries()[navigation.entries().length - 1];
+  });
+  assert_true(currentEntryIdentity);
+},`navigation.entries() and navigation.activation should be updated on activation and handle replacing correctly`);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/navigation-api-multiple-entries.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/navigation-api-multiple-entries.html
new file mode 100644
index 0000000..e8e0f87
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/navigation-api-multiple-entries.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js"></script>
+<script src="../resources/utils.js"></script>
+<script src="resources/utils.js"></script>
+
+<body>
+<script>
+setup(() => assertSpeculationRulesIsSupported());
+
+promise_test(async t => {
+  const rcHelper = new RemoteContextHelper();
+
+  const referrerRC1 = await rcHelper.addWindow(undefined, { features: 'noopener' });
+  const referrerRC2 = await referrerRC1.navigateToNew();
+  const referrerRC3 = await referrerRC2.navigateToNew();
+  assert_equals(await referrerRC3.executeScript(() => navigation.entries().length), 3);
+
+  let referrerRC3CurrentId = await referrerRC3.executeScript(() => navigation.currentEntry.id);
+
+  const prerenderedRC = await addPrerenderRC(referrerRC3);
+  let activationStateBeforeActivation = await prerenderedRC.executeScript(() => {
+    return {
+     entries: navigation.entries().map(e => ({ id: e.id, })),
+     activationEntryId: navigation.activation.entry?.id,
+     activationFromId: navigation.activation.from?.id,
+     activationNavigationType : navigation.activation.navigationType,
+    }
+  });
+  assert_equals(activationStateBeforeActivation.entries.length, 1);
+  assert_equals(activationStateBeforeActivation.activationFromId, referrerRC3CurrentId);
+  assert_equals(activationStateBeforeActivation.activationEntryId, activationStateBeforeActivation.entries[0].id);
+  assert_equals(activationStateBeforeActivation.activationNavigationType, "push");
+
+  await activatePrerenderRC(referrerRC3, prerenderedRC);
+
+  let activationStateAfterActivation = await prerenderedRC.executeScript(() => {
+    return {
+     entries: navigation.entries().map(e => ({ id: e.id, })),
+     activationEntryId: navigation.activation.entry?.id,
+     activationFromId: navigation.activation.from?.id,
+     activationNavigationType : navigation.activation.navigationType,
+    }
+  });
+  assert_equals(activationStateAfterActivation.entries.length, 4);
+  assert_equals(activationStateAfterActivation.activationFromId, activationStateAfterActivation.entries[2].id);
+  assert_equals(activationStateAfterActivation.activationEntryId, activationStateAfterActivation.entries[3].id);
+  assert_equals(activationStateAfterActivation.activationNavigationType, "push");
+},`navigation.entries() and navigation.activation should be updated on activation - multiple entries`);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/navigation-api.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/navigation-api.html
new file mode 100644
index 0000000..fd25e94
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/navigation-api.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js"></script>
+<script src="../resources/utils.js"></script>
+<script src="resources/utils.js"></script>
+
+<body>
+<script>
+setup(() => assertSpeculationRulesIsSupported());
+
+promise_test(async t => {
+  const rcHelper = new RemoteContextHelper();
+  const referrerRC = await rcHelper.addWindow(undefined, { features: 'noopener' });
+  assert_equals(await referrerRC.executeScript(() => navigation.entries().length), 1);
+  let referrerRCCurrentId = await referrerRC.executeScript(() => navigation.currentEntry.id);
+
+  const prerenderedRC = await addPrerenderRC(referrerRC);
+  let activationStateBeforeActivation = await prerenderedRC.executeScript(() => {
+    return {
+     entries: navigation.entries().map(e => ({ id: e.id, })),
+     activationEntryId: navigation.activation.entry?.id,
+     activationFromId: navigation.activation.from?.id,
+     activationNavigationType : navigation.activation.navigationType,
+    }
+  });
+  assert_equals(activationStateBeforeActivation.entries.length, 1);
+  assert_equals(activationStateBeforeActivation.activationFromId, referrerRCCurrentId);
+  assert_equals(activationStateBeforeActivation.activationEntryId, activationStateBeforeActivation.entries[0].id);
+  assert_equals(activationStateBeforeActivation.activationNavigationType, "push");
+
+  // Save the current entry before activation.
+  await prerenderedRC.executeScript(() => window.currentEntryBeforeActivation = navigation.currentEntry);
+
+  await activatePrerenderRC(referrerRC, prerenderedRC);
+
+  let activationStateAfterActivation = await prerenderedRC.executeScript(() => {
+    return {
+     entries: navigation.entries().map(e => ({ id: e.id, })),
+     activationEntryId: navigation.activation.entry?.id,
+     activationFromId: navigation.activation.from?.id,
+     activationNavigationType : navigation.activation.navigationType,
+    }
+  });
+  assert_equals(activationStateAfterActivation.entries.length, 2);
+  assert_equals(activationStateAfterActivation.activationFromId, activationStateAfterActivation.entries[0].id);
+  assert_equals(activationStateAfterActivation.activationFromId, referrerRCCurrentId);
+  assert_equals(activationStateAfterActivation.activationEntryId, activationStateAfterActivation.entries[1].id);
+  assert_equals(activationStateAfterActivation.activationNavigationType, "push");
+
+  let currentEntryIdentity = await prerenderedRC.executeScript(() => {
+    return window.currentEntryBeforeActivation === navigation.currentEntry &&
+           navigation.currentEntry === navigation.entries()[navigation.entries().length - 1];
+  });
+  assert_true(currentEntryIdentity);
+},`navigation.entries() and navigation.activation should be updated on activation`);
+</script>