[ios] WebStateList owns all WebState it manages.

Flip the Tab and WebState ownership relationship so that WebState owns
(indirectly via the LegacyTabHelper tab helper) the Tab. This required:
-   Changing Contextual Seach and pre-renderer to own WebStates.
-   Adding observers and delegates for WebStateList events to create
    and cleanup the Tab when a WebState is added or detached from the
    WebStateList.

Change the WebStateList API to take WebState via std::unique_ptr<> to
enforce correct use of the API.

BUG=546222

Review-Url: https://codereview.chromium.org/2775623002
Cr-Commit-Position: refs/heads/master@{#461750}
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index c0a8f15..e85bb3be 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -172,6 +172,8 @@
 #include "ios/public/provider/chrome/browser/voice/voice_search_controller.h"
 #include "ios/public/provider/chrome/browser/voice/voice_search_controller_delegate.h"
 #include "ios/public/provider/chrome/browser/voice/voice_search_provider.h"
+#import "ios/shared/chrome/browser/tabs/web_state_list.h"
+#import "ios/shared/chrome/browser/tabs/web_state_opener.h"
 #include "ios/web/public/active_state_manager.h"
 #include "ios/web/public/navigation_item.h"
 #import "ios/web/public/navigation_manager.h"
@@ -3663,19 +3665,27 @@
   }
 
   if (url == [_preloadController prerenderedURL]) {
+    std::unique_ptr<web::WebState> newWebState =
+        [_preloadController releasePrerenderContents];
+    DCHECK(newWebState);
+
     Tab* oldTab = [_model currentTab];
-    Tab* newTab = [_preloadController releasePrerenderContents];
+    Tab* newTab = LegacyTabHelper::GetTabForWebState(newWebState.get());
     DCHECK(oldTab);
     DCHECK(newTab);
+
     bool canPruneItems =
         [newTab navigationManager]->CanPruneAllButLastCommittedItem();
+
     if (oldTab && newTab && canPruneItems) {
       [oldTab recordStateInHistory];
       [newTab navigationManager]->CopyStateFromAndPrune(
           [oldTab navigationManager]);
       [[newTab nativeAppNavigationController]
           copyStateFrom:[oldTab nativeAppNavigationController]];
-      [_model replaceTab:oldTab withTab:newTab];
+
+      [_model webStateList]->ReplaceWebStateAt([_model indexOfTab:oldTab],
+                                               std::move(newWebState));
 
       // Set isPrerenderTab to NO after replacing the tab. This will allow the
       // BrowserViewController to detect that a pre-rendered tab is switched in,
@@ -3683,7 +3693,6 @@
       newTab.isPrerenderTab = NO;
 
       [self tabLoadComplete:newTab withSuccess:newTab.loadFinished];
-
       return;
     }
   }
@@ -4666,15 +4675,20 @@
   // transitioning panel and remove it.
   void (^completion)(BOOL) = ^(BOOL finished) {
     _contextualSearchMask.alpha = 0;
-    Tab* newTab = [tabProvider releaseTab];
-    DCHECK(newTab);
-    DCHECK([newTab navigationManager]);
-    // Add the new tab to the tab model.
-    [newTab setParentTabModel:_model];
-    // Insert the new tab one after the current tab.
-    Tab* currentTab = [_model currentTab];
-    NSUInteger index = [_model indexOfTab:currentTab];
-    [_model insertTab:newTab atIndex:index + 1];
+    std::unique_ptr<web::WebState> webState = [tabProvider releaseWebState];
+    DCHECK(webState);
+    DCHECK(webState->GetNavigationManager());
+
+    Tab* newTab = LegacyTabHelper::GetTabForWebState(webState.get());
+    WebStateList* webStateList = [_model webStateList];
+
+    // Insert the new tab after the current tab.
+    DCHECK_NE(webStateList->active_index(), WebStateList::kInvalidIndex);
+    DCHECK_NE(webStateList->active_index(), INT_MAX);
+    int insertion_index = webStateList->active_index() + 1;
+    webStateList->InsertWebState(insertion_index, std::move(webState));
+    webStateList->SetOpenerOfWebStateAt(insertion_index,
+                                        [tabProvider webStateOpener]);
 
     // Set isPrerenderTab to NO after inserting the tab. This will allow the
     // BrowserViewController to detect that a pre-rendered tab is switched in,
@@ -4682,6 +4696,7 @@
     // tab is made the current tab.
     // This also enables contextual search (if otherwise applicable) on
     // |newTab|.
+
     newTab.isPrerenderTab = NO;
     [_model setCurrentTab:newTab];