OOPIF: Support session restore by combining/splitting frame PageStates.

In OOPIF-enabled modes, each FrameNavigationEntry has a per-frame
PageState object.  The states for each frame in the tree need to be
combined into a single PageState for GetPageState, and a single
PageState needs to be split into individual FrameNavigationEntries for
SetPageState.

Because GetPageState is const and returns a const ref, we need to
cache the combined PageState each time it could change.

BUG=545219
TEST=Close and restore a tab or session with OOPIFs.

Review URL: https://codereview.chromium.org/1496483002

Cr-Commit-Position: refs/heads/master@{#363025}
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc
index 194a0e8..bf5dcff6 100644
--- a/content/browser/frame_host/navigation_controller_impl.cc
+++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -1847,11 +1847,12 @@
     return;
 
   // Schedule a load in this frame if the new item isn't for the same item
-  // sequence number in the same SiteInstance.
-  // TODO(creis): Handle null SiteInstances during session restore.
+  // sequence number in the same SiteInstance. Newly restored items may not have
+  // a SiteInstance yet, in which case it will be assigned on first commit.
   if (!old_item ||
       new_item->item_sequence_number() != old_item->item_sequence_number() ||
-      new_item->site_instance() != old_item->site_instance()) {
+      (new_item->site_instance() != nullptr &&
+       new_item->site_instance() != old_item->site_instance())) {
     if (old_item &&
         new_item->document_sequence_number() ==
             old_item->document_sequence_number()) {