Decouple NavigationControllerImpl and WebContentsImpl.

This CL is the first step in breaking dependencies between WebContents and navigation logic. It creates a NavigationControllerDelegate interface, which contains all the methods NavController needs to call on WebContentsImpl.
More details and roadmap of the changes to come are in https://docs.google.com/a/chromium.org/document/d/127ODQnXaoMtHdu2WXTR6iHg411bXa_8zRTb3kXlwArA/edit.

BUG=304341

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@230480 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/browser/ssl/ssl_manager.cc b/content/browser/ssl/ssl_manager.cc
index 6a6572a..9c96b9b2 100644
--- a/content/browser/ssl/ssl_manager.cc
+++ b/content/browser/ssl/ssl_manager.cc
@@ -207,10 +207,12 @@
 
   SSLStatus original_ssl_status = entry->GetSSL();  // Copy!
 
-  policy()->UpdateEntry(entry, controller_->web_contents());
+  WebContentsImpl* contents =
+      static_cast<WebContentsImpl*>(controller_->delegate()->GetWebContents());
+  policy()->UpdateEntry(entry, contents);
 
   if (!entry->GetSSL().Equals(original_ssl_status))
-    controller_->web_contents()->DidChangeVisibleSSLState();
+    contents->DidChangeVisibleSSLState();
 }
 
 }  // namespace content
diff --git a/content/browser/web_contents/navigation_controller_delegate.h b/content/browser/web_contents/navigation_controller_delegate.h
new file mode 100644
index 0000000..b5880558
--- /dev/null
+++ b/content/browser/web_contents/navigation_controller_delegate.h
@@ -0,0 +1,64 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEB_CONTENTS_NAVIGATION_CONTROLLER_DELEGATE_H_
+#define CONTENT_BROWSER_WEB_CONTENTS_NAVIGATION_CONTROLLER_DELEGATE_H_
+
+#include <string>
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_details.h"
+
+namespace content {
+
+struct LoadCommittedDetails;
+class InterstitialPage;
+class RenderViewHost;
+class SiteInstance;
+class WebContents;
+class WebContentsDelegate;
+
+// Interface for objects embedding a NavigationController to provide the
+// functionality NavigationController needs.
+// TODO(nasko): This interface should exist for short amount of time, while
+// we transition navigation code from WebContents to Navigator.
+class NavigationControllerDelegate {
+ public:
+  virtual ~NavigationControllerDelegate() {}
+
+  // Duplicates of WebContents methods.
+  virtual RenderViewHost* GetRenderViewHost() const = 0;
+  virtual InterstitialPage* GetInterstitialPage() const = 0;
+  virtual const std::string& GetContentsMimeType() const = 0;
+  virtual void NotifyNavigationStateChanged(unsigned changed_flags) = 0;
+  virtual void Stop() = 0;
+  virtual SiteInstance* GetSiteInstance() const = 0;
+  virtual SiteInstance* GetPendingSiteInstance() const = 0;
+  virtual int32 GetMaxPageID() = 0;
+  virtual int32 GetMaxPageIDForSiteInstance(SiteInstance* site_instance) = 0;
+
+  // Methods from WebContentsImpl that NavigationControllerImpl needs to
+  // call.
+  virtual void NotifyBeforeFormRepostWarningShow() = 0;
+  virtual void NotifyNavigationEntryCommitted(
+      const LoadCommittedDetails& load_details) = 0;
+  virtual bool NavigateToPendingEntry(
+      NavigationController::ReloadType reload_type) = 0;
+  virtual void SetHistoryLengthAndPrune(
+      const SiteInstance* site_instance,
+      int merge_history_length,
+      int32 minimum_page_id) = 0;
+  virtual void CopyMaxPageIDsFrom(WebContents* web_contents) = 0;
+  virtual void UpdateMaxPageID(int32 page_id) = 0;
+  virtual void UpdateMaxPageIDForSiteInstance(SiteInstance* site_instance,
+                                              int32 page_id) = 0;
+  virtual void ActivateAndShowRepostFormWarningDialog() = 0;
+
+  // This method is needed, since we are no longer guaranteed that the
+  // embedder for NavigationController will be a WebContents object.
+  virtual WebContents* GetWebContents() = 0;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_WEB_CONTENTS_NAVIGATION_CONTROLLER_DELEGATE_H_
diff --git a/content/browser/web_contents/navigation_controller_impl.cc b/content/browser/web_contents/navigation_controller_impl.cc
index ebbd866..75cfee7 100644
--- a/content/browser/web_contents/navigation_controller_impl.cc
+++ b/content/browser/web_contents/navigation_controller_impl.cc
@@ -19,7 +19,6 @@
 #include "content/browser/web_contents/debug_urls.h"
 #include "content/browser/web_contents/interstitial_page_impl.h"
 #include "content/browser/web_contents/navigation_entry_impl.h"
-#include "content/browser/web_contents/web_contents_impl.h"
 #include "content/browser/web_contents/web_contents_screenshot_manager.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/browser_context.h"
@@ -197,14 +196,14 @@
 }
 
 NavigationControllerImpl::NavigationControllerImpl(
-    WebContentsImpl* web_contents,
+    NavigationControllerDelegate* delegate,
     BrowserContext* browser_context)
     : browser_context_(browser_context),
       pending_entry_(NULL),
       last_committed_entry_index_(-1),
       pending_entry_index_(-1),
       transient_entry_index_(-1),
-      web_contents_(web_contents),
+      delegate_(delegate),
       max_restored_page_id_(-1),
       ssl_manager_(this),
       needs_reload_(false),
@@ -220,7 +219,7 @@
 }
 
 WebContents* NavigationControllerImpl::GetWebContents() const {
-  return web_contents_;
+  return delegate_->GetWebContents();
 }
 
 BrowserContext* NavigationControllerImpl::GetBrowserContext() const {
@@ -317,11 +316,10 @@
     // The user is asking to reload a page with POST data. Prompt to make sure
     // they really want to do this. If they do, the dialog will call us back
     // with check_for_repost = false.
-    web_contents_->NotifyBeforeFormRepostWarningShow();
+    delegate_->NotifyBeforeFormRepostWarningShow();
 
     pending_reload_ = reload_type;
-    web_contents_->Activate();
-    web_contents_->GetDelegate()->ShowRepostFormWarningDialog(web_contents_);
+    delegate_->ActivateAndShowRepostFormWarningDialog();
   } else {
     if (!IsInitialNavigation())
       DiscardNonCommittedEntriesInternal();
@@ -427,7 +425,7 @@
   // the new tab.  If another page modifies this blank page, a URL spoof is
   // possible, so we must stop showing the pending entry.
   RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
-      web_contents_->GetRenderViewHost());
+      delegate_->GetRenderViewHost());
   bool safe_to_show_pending =
       pending_entry_ &&
       // Require a new navigation.
@@ -468,12 +466,12 @@
 }
 
 bool NavigationControllerImpl::CanViewSource() const {
-  const std::string& mime_type = web_contents_->GetContentsMimeType();
+  const std::string& mime_type = delegate_->GetContentsMimeType();
   bool is_viewable_mime_type = net::IsSupportedNonImageMimeType(mime_type) &&
       !net::IsSupportedMediaMimeType(mime_type);
   NavigationEntry* visible_entry = GetVisibleEntry();
   return visible_entry && !visible_entry->IsViewSourceMode() &&
-      is_viewable_mime_type && !web_contents_->GetInterstitialPage();
+      is_viewable_mime_type && !delegate_->GetInterstitialPage();
 }
 
 int NavigationControllerImpl::GetLastCommittedEntryIndex() const {
@@ -780,7 +778,7 @@
       // the caller that nothing has happened.
       if (pending_entry_) {
         DiscardNonCommittedEntries();
-        web_contents_->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
+        delegate_->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
       }
       return false;
     default:
@@ -821,12 +819,12 @@
   active_entry->set_should_clear_history_list(false);
 
   // The active entry's SiteInstance should match our SiteInstance.
-  CHECK(active_entry->site_instance() == web_contents_->GetSiteInstance());
+  CHECK(active_entry->site_instance() == delegate_->GetSiteInstance());
 
   // Remember the bindings the renderer process has at this point, so that
   // we do not grant this entry additional bindings if we come back to it.
   active_entry->SetBindings(
-      web_contents_->GetRenderViewHost()->GetEnabledBindings());
+      delegate_->GetRenderViewHost()->GetEnabledBindings());
 
   // Now prep the rest of the details for the notification and broadcast.
   details->entry = active_entry;
@@ -863,7 +861,7 @@
     return NAVIGATION_TYPE_NAV_IGNORE;
   }
 
-  if (params.page_id > web_contents_->GetMaxPageID()) {
+  if (params.page_id > delegate_->GetMaxPageID()) {
     // Greater page IDs than we've ever seen before are new pages. We may or may
     // not have a pending entry for the page, and this may or may not be the
     // main frame.
@@ -887,7 +885,7 @@
 
   // Now we know that the notification is for an existing page. Find that entry.
   int existing_entry_index = GetEntryIndexWithPageID(
-      web_contents_->GetSiteInstance(),
+      delegate_->GetSiteInstance(),
       params.page_id);
   if (existing_entry_index == -1) {
     // The page was not found. It could have been pruned because of the limit on
@@ -906,7 +904,7 @@
     temp.append("#page");
     temp.append(base::IntToString(params.page_id));
     temp.append("#max");
-    temp.append(base::IntToString(web_contents_->GetMaxPageID()));
+    temp.append(base::IntToString(delegate_->GetMaxPageID()));
     temp.append("#frame");
     temp.append(base::IntToString(params.frame_id));
     temp.append("#ids");
@@ -921,13 +919,13 @@
         temp.append(base::IntToString(entries_[i]->site_instance()->GetId()));
       else
         temp.append("N");
-      if (entries_[i]->site_instance() != web_contents_->GetSiteInstance())
+      if (entries_[i]->site_instance() != delegate_->GetSiteInstance())
         temp.append("x");
       temp.append(",");
     }
     GURL url(temp);
     static_cast<RenderViewHostImpl*>(
-        web_contents_->GetRenderViewHost())->Send(
+        delegate_->GetRenderViewHost())->Send(
             new ViewMsg_TempCrashWithData(url));
     return NAVIGATION_TYPE_NAV_IGNORE;
   }
@@ -992,7 +990,7 @@
   // the SiteInstance hasn't been assigned to something else.
   if (pending_entry_ &&
       (!pending_entry_->site_instance() ||
-       pending_entry_->site_instance() == web_contents_->GetSiteInstance())) {
+       pending_entry_->site_instance() == delegate_->GetSiteInstance())) {
     new_entry = new NavigationEntryImpl(*pending_entry_);
 
     // Don't use the page type from the pending entry. Some interstitial page
@@ -1026,7 +1024,7 @@
   new_entry->SetPageID(params.page_id);
   new_entry->SetTransitionType(params.transition);
   new_entry->set_site_instance(
-      static_cast<SiteInstanceImpl*>(web_contents_->GetSiteInstance()));
+      static_cast<SiteInstanceImpl*>(delegate_->GetSiteInstance()));
   new_entry->SetHasPostData(params.is_post);
   new_entry->SetPostID(params.post_id);
   new_entry->SetOriginalRequestURL(params.original_request_url);
@@ -1053,7 +1051,7 @@
   // This is a back/forward navigation. The existing page for the ID is
   // guaranteed to exist by ClassifyNavigation, and we just need to update it
   // with new information from the renderer.
-  int entry_index = GetEntryIndexWithPageID(web_contents_->GetSiteInstance(),
+  int entry_index = GetEntryIndexWithPageID(delegate_->GetSiteInstance(),
                                             params.page_id);
   DCHECK(entry_index >= 0 &&
          entry_index < static_cast<int>(entries_.size()));
@@ -1072,9 +1070,9 @@
   // The site instance will normally be the same except during session restore,
   // when no site instance will be assigned.
   DCHECK(entry->site_instance() == NULL ||
-         entry->site_instance() == web_contents_->GetSiteInstance());
+         entry->site_instance() == delegate_->GetSiteInstance());
   entry->set_site_instance(
-      static_cast<SiteInstanceImpl*>(web_contents_->GetSiteInstance()));
+      static_cast<SiteInstanceImpl*>(delegate_->GetSiteInstance()));
 
   entry->SetHasPostData(params.is_post);
   entry->SetPostID(params.post_id);
@@ -1093,7 +1091,7 @@
   // If a transient entry was removed, the indices might have changed, so we
   // have to query the entry index again.
   last_committed_entry_index_ =
-      GetEntryIndexWithPageID(web_contents_->GetSiteInstance(), params.page_id);
+      GetEntryIndexWithPageID(delegate_->GetSiteInstance(), params.page_id);
 }
 
 void NavigationControllerImpl::RendererDidNavigateToSamePage(
@@ -1102,7 +1100,7 @@
   // entry for this page ID. This entry is guaranteed to exist by
   // ClassifyNavigation. All we need to do is update the existing entry.
   NavigationEntryImpl* existing_entry = GetEntryWithPageID(
-      web_contents_->GetSiteInstance(), params.page_id);
+      delegate_->GetSiteInstance(), params.page_id);
 
   // We assign the entry's unique ID to be that of the new one. Since this is
   // always the result of a user action, we want to dismiss infobars, etc. like
@@ -1123,7 +1121,7 @@
       "WebKit should only tell us about in-page navs for the main frame.";
   // We're guaranteed to have an entry for this one.
   NavigationEntryImpl* existing_entry = GetEntryWithPageID(
-      web_contents_->GetSiteInstance(), params.page_id);
+      delegate_->GetSiteInstance(), params.page_id);
 
   // Reference fragment navigation. We're guaranteed to have the last_committed
   // entry and it will be the same page as the new navigation (minus the
@@ -1141,7 +1139,7 @@
   // If a transient entry was removed, the indices might have changed, so we
   // have to query the entry index again.
   last_committed_entry_index_ =
-      GetEntryIndexWithPageID(web_contents_->GetSiteInstance(), params.page_id);
+      GetEntryIndexWithPageID(delegate_->GetSiteInstance(), params.page_id);
 }
 
 void NavigationControllerImpl::RendererDidNavigateNewSubframe(
@@ -1175,7 +1173,7 @@
   // navigation entry. This is case "2." in NAV_AUTO_SUBFRAME comment in the
   // header file. In case "1." this will be a NOP.
   int entry_index = GetEntryIndexWithPageID(
-      web_contents_->GetSiteInstance(),
+      delegate_->GetSiteInstance(),
       params.page_id);
   if (entry_index < 0 ||
       entry_index >= static_cast<int>(entries_.size())) {
@@ -1240,7 +1238,7 @@
   // Copy the max page id map from the old tab to the new tab.  This ensures
   // that new and existing navigations in the tab's current SiteInstances
   // are identified properly.
-  web_contents_->CopyMaxPageIDsFrom(source.web_contents());
+  delegate_->CopyMaxPageIDsFrom(source.delegate()->GetWebContents());
 }
 
 void NavigationControllerImpl::CopyStateFromAndPrune(
@@ -1260,7 +1258,7 @@
       last_committed->site_instance());
   int32 minimum_page_id = last_committed->GetPageID();
   int32 max_page_id =
-      web_contents_->GetMaxPageIDForSiteInstance(site_instance.get());
+      delegate_->GetMaxPageIDForSiteInstance(site_instance.get());
 
   // Remove all the entries leaving the active entry.
   PruneAllButVisibleInternal();
@@ -1283,20 +1281,20 @@
   // Adjust indices such that the last entry and pending are at the end now.
   last_committed_entry_index_ = GetEntryCount() - 1;
 
-  web_contents_->SetHistoryLengthAndPrune(site_instance.get(),
-                                          max_source_index,
-                                          minimum_page_id);
+  delegate_->SetHistoryLengthAndPrune(site_instance.get(),
+                                      max_source_index,
+                                      minimum_page_id);
 
   // Copy the max page id map from the old tab to the new tab.  This ensures
   // that new and existing navigations in the tab's current SiteInstances
   // are identified properly.
-  web_contents_->CopyMaxPageIDsFrom(source->web_contents());
+  delegate_->CopyMaxPageIDsFrom(source->delegate()->GetWebContents());
 
   // If there is a last committed entry, be sure to include it in the new
   // max page ID map.
   if (max_page_id > -1) {
-    web_contents_->UpdateMaxPageIDForSiteInstance(site_instance.get(),
-                                                  max_page_id);
+    delegate_->UpdateMaxPageIDForSiteInstance(site_instance.get(),
+                                              max_page_id);
   }
 }
 
@@ -1334,7 +1332,7 @@
   // http://crbug.com/178491
   NavigationEntryImpl* entry =
       NavigationEntryImpl::FromNavigationEntry(GetVisibleEntry());
-  web_contents_->SetHistoryLengthAndPrune(
+  delegate_->SetHistoryLengthAndPrune(
       entry->site_instance(), 0, entry->GetPageID());
 }
 
@@ -1447,7 +1445,7 @@
   // If there was a transient entry, invalidate everything so the new active
   // entry state is shown.
   if (transient) {
-    web_contents_->NotifyNavigationStateChanged(kInvalidateAll);
+    delegate_->NotifyNavigationStateChanged(kInvalidateAll);
   }
 }
 
@@ -1500,7 +1498,7 @@
   last_committed_entry_index_ = static_cast<int>(entries_.size()) - 1;
 
   // This is a new page ID, so we need everybody to know about it.
-  web_contents_->UpdateMaxPageID(entry->GetPageID());
+  delegate_->UpdateMaxPageID(entry->GetPageID());
 }
 
 void NavigationControllerImpl::PruneOldestEntryIfFull() {
@@ -1527,12 +1525,12 @@
           NavigationEntryImpl::RESTORE_NONE) &&
       (entries_[pending_entry_index_]->GetTransitionType() &
           PAGE_TRANSITION_FORWARD_BACK)) {
-    web_contents_->Stop();
+    delegate_->Stop();
 
     // If an interstitial page is showing, we want to close it to get back
     // to what was showing before.
-    if (web_contents_->GetInterstitialPage())
-      web_contents_->GetInterstitialPage()->DontProceed();
+    if (delegate_->GetInterstitialPage())
+      delegate_->GetInterstitialPage()->DontProceed();
 
     DiscardNonCommittedEntries();
     return;
@@ -1542,8 +1540,8 @@
   // cannot make new requests.  Unblock (and disable) it to allow this
   // navigation to succeed.  The interstitial will stay visible until the
   // resulting DidNavigate.
-  if (web_contents_->GetInterstitialPage()) {
-    static_cast<InterstitialPageImpl*>(web_contents_->GetInterstitialPage())->
+  if (delegate_->GetInterstitialPage()) {
+    static_cast<InterstitialPageImpl*>(delegate_->GetInterstitialPage())->
         CancelForNavigation();
   }
 
@@ -1553,7 +1551,7 @@
     pending_entry_ = entries_[pending_entry_index_].get();
   }
 
-  if (!web_contents_->NavigateToPendingEntry(reload_type))
+  if (!delegate_->NavigateToPendingEntry(reload_type))
     DiscardNonCommittedEntries();
 
   // If the entry is being restored and doesn't have a SiteInstance yet, fill
@@ -1563,7 +1561,7 @@
   if (pending_entry_ && !pending_entry_->site_instance() &&
       pending_entry_->restore_type() != NavigationEntryImpl::RESTORE_NONE) {
     pending_entry_->set_site_instance(static_cast<SiteInstanceImpl*>(
-        web_contents_->GetPendingSiteInstance()));
+        delegate_->GetPendingSiteInstance()));
     pending_entry_->set_restore_type(NavigationEntryImpl::RESTORE_NONE);
   }
 }
@@ -1577,8 +1575,8 @@
   // when it wants to draw.  See http://crbug.com/11157
   ssl_manager_.DidCommitProvisionalLoad(*details);
 
-  web_contents_->NotifyNavigationStateChanged(kInvalidateAll);
-  web_contents_->NotifyNavigationEntryCommitted(*details);
+  delegate_->NotifyNavigationStateChanged(kInvalidateAll);
+  delegate_->NotifyNavigationEntryCommitted(*details);
 
   // TODO(avi): Remove. http://crbug.com/170921
   NotificationDetails notification_details =
@@ -1680,7 +1678,7 @@
       entries_.begin() + index, linked_ptr<NavigationEntryImpl>(
           NavigationEntryImpl::FromNavigationEntry(entry)));
   transient_entry_index_ = index;
-  web_contents_->NotifyNavigationStateChanged(kInvalidateAll);
+  delegate_->NotifyNavigationStateChanged(kInvalidateAll);
 }
 
 void NavigationControllerImpl::InsertEntriesFrom(
diff --git a/content/browser/web_contents/navigation_controller_impl.h b/content/browser/web_contents/navigation_controller_impl.h
index 6e6f333..1aad311 100644
--- a/content/browser/web_contents/navigation_controller_impl.h
+++ b/content/browser/web_contents/navigation_controller_impl.h
@@ -12,6 +12,7 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "content/browser/ssl/ssl_manager.h"
+#include "content/browser/web_contents/navigation_controller_delegate.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_type.h"
 
@@ -20,7 +21,6 @@
 namespace content {
 class NavigationEntryImpl;
 class RenderViewHost;
-class WebContentsImpl;
 class WebContentsScreenshotManager;
 class SiteInstance;
 struct LoadCommittedDetails;
@@ -29,7 +29,7 @@
     : public NON_EXPORTED_BASE(NavigationController) {
  public:
   NavigationControllerImpl(
-      WebContentsImpl* web_contents,
+      NavigationControllerDelegate* delegate,
       BrowserContext* browser_context);
   virtual ~NavigationControllerImpl();
 
@@ -114,10 +114,8 @@
       SiteInstance* instance,
       int32 page_id) const;
 
-  // WebContentsImpl -----------------------------------------------------------
-
-  WebContentsImpl* web_contents() const {
-    return web_contents_;
+  NavigationControllerDelegate* delegate() const {
+    return delegate_;
   }
 
   // For use by WebContentsImpl ------------------------------------------------
@@ -204,9 +202,11 @@
   // that.
   void SetScreenshotManager(WebContentsScreenshotManager* manager);
 
+  // Discards only the pending entry.
+  void DiscardPendingEntry();
+
  private:
   friend class RestoreHelper;
-  friend class WebContentsImpl;  // For invoking OnReservedPageIDRange.
 
   FRIEND_TEST_ALL_PREFIXES(NavigationControllerTest,
                            PurgeScreenshot);
@@ -293,9 +293,6 @@
   // Discards both the pending and transient entries.
   void DiscardNonCommittedEntriesInternal();
 
-  // Discards only the pending entry.
-  void DiscardPendingEntry();
-
   // Discards only the transient entry.
   void DiscardTransientEntry();
 
@@ -358,9 +355,9 @@
   // after the transient entry will become invalid if you navigate forward.
   int transient_entry_index_;
 
-  // The WebContents associated with the controller. Possibly NULL during
+  // The delegate associated with the controller. Possibly NULL during
   // setup.
-  WebContentsImpl* web_contents_;
+  NavigationControllerDelegate* delegate_;
 
   // The max restored page ID in this controller, if it was restored.  We must
   // store this so that WebContentsImpl can tell any renderer in charge of one
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index d5bf114..44dd284 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1010,8 +1010,9 @@
     max_page_ids_[site_instance->GetId()] = page_id;
 }
 
-void WebContentsImpl::CopyMaxPageIDsFrom(WebContentsImpl* web_contents) {
-  max_page_ids_ = web_contents->max_page_ids_;
+void WebContentsImpl::CopyMaxPageIDsFrom(WebContents* web_contents) {
+  WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents);
+  max_page_ids_ = contents->max_page_ids_;
 }
 
 SiteInstance* WebContentsImpl::GetSiteInstance() const {
@@ -1218,6 +1219,10 @@
   }
 }
 
+WebContents* WebContentsImpl::GetWebContents() {
+  return this;
+}
+
 void WebContentsImpl::Init(const WebContents::CreateParams& params) {
   // This is set before initializing the render_manager_ since render_manager_
   // init calls back into us via its delegate to ask if it should be hidden.
@@ -2682,6 +2687,13 @@
                     BeforeFormRepostWarningShow());
 }
 
+
+void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() {
+  Activate();
+  if (delegate_)
+    delegate_->ShowRepostFormWarningDialog(this);
+}
+
 // Notifies the RenderWidgetHost instance about the fact that the page is
 // loading, or done loading.
 void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host,
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index fb81399..0ab09cc 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -18,6 +18,7 @@
 #include "content/browser/renderer_host/frame_tree.h"
 #include "content/browser/renderer_host/render_view_host_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
+#include "content/browser/web_contents/navigation_controller_delegate.h"
 #include "content/browser/web_contents/navigation_controller_impl.h"
 #include "content/browser/web_contents/render_view_host_manager.h"
 #include "content/common/content_export.h"
@@ -76,7 +77,8 @@
       public RenderViewHostDelegate,
       public RenderWidgetHostDelegate,
       public RenderViewHostManager::Delegate,
-      public NotificationObserver {
+      public NotificationObserver,
+      public NON_EXPORTED_BASE(NavigationControllerDelegate) {
  public:
   virtual ~WebContentsImpl();
 
@@ -112,32 +114,6 @@
   // Returns the SavePackage which manages the page saving job. May be NULL.
   SavePackage* save_package() const { return save_package_.get(); }
 
-  // Updates the max page ID for the current SiteInstance in this
-  // WebContentsImpl to be at least |page_id|.
-  void UpdateMaxPageID(int32 page_id);
-
-  // Updates the max page ID for the given SiteInstance in this WebContentsImpl
-  // to be at least |page_id|.
-  void UpdateMaxPageIDForSiteInstance(SiteInstance* site_instance,
-                                      int32 page_id);
-
-  // Copy the current map of SiteInstance ID to max page ID from another tab.
-  // This is necessary when this tab adopts the NavigationEntries from
-  // |web_contents|.
-  void CopyMaxPageIDsFrom(WebContentsImpl* web_contents);
-
-  // Called by the NavigationController to cause the WebContentsImpl to navigate
-  // to the current pending entry. The NavigationController should be called
-  // back with RendererDidNavigate on success or DiscardPendingEntry on failure.
-  // The callbacks can be inside of this function, or at some future time.
-  //
-  // The entry has a PageID of -1 if newly created (corresponding to navigation
-  // to a new URL).
-  //
-  // If this method returns false, then the navigation is discarded (equivalent
-  // to calling DiscardPendingEntry on the NavigationController).
-  bool NavigateToPendingEntry(NavigationController::ReloadType reload_type);
-
   // Called by InterstitialPageImpl when it creates a RenderViewHost.
   void RenderViewForInterstitialPageCreated(RenderViewHost* render_view_host);
 
@@ -188,10 +164,6 @@
   // Invoked when visible SSL state (as defined by SSLStatus) changes.
   void DidChangeVisibleSSLState();
 
-  // Invoked before a form repost warning is shown.
-  void NotifyBeforeFormRepostWarningShow();
-
-
   // Informs the render view host and the BrowserPluginEmbedder, if present, of
   // a Drag Source End.
   void DragSourceEndedAt(int client_x, int client_y, int screen_x,
@@ -510,6 +482,53 @@
                        const NotificationSource& source,
                        const NotificationDetails& details) OVERRIDE;
 
+  // NavigationControllerDelegate ----------------------------------------------
+
+  virtual WebContents* GetWebContents() OVERRIDE;
+  virtual void NotifyNavigationEntryCommitted(
+      const LoadCommittedDetails& load_details) OVERRIDE;
+
+  // Invoked before a form repost warning is shown.
+  virtual void NotifyBeforeFormRepostWarningShow() OVERRIDE;
+
+  // Activate this WebContents and show a form repost warning.
+  virtual void ActivateAndShowRepostFormWarningDialog() OVERRIDE;
+
+  // Updates the max page ID for the current SiteInstance in this
+  // WebContentsImpl to be at least |page_id|.
+  virtual void UpdateMaxPageID(int32 page_id) OVERRIDE;
+
+  // Updates the max page ID for the given SiteInstance in this WebContentsImpl
+  // to be at least |page_id|.
+  virtual void UpdateMaxPageIDForSiteInstance(SiteInstance* site_instance,
+                                              int32 page_id) OVERRIDE;
+
+  // Copy the current map of SiteInstance ID to max page ID from another tab.
+  // This is necessary when this tab adopts the NavigationEntries from
+  // |web_contents|.
+  virtual void CopyMaxPageIDsFrom(WebContents* web_contents) OVERRIDE;
+
+  // Called by the NavigationController to cause the WebContentsImpl to navigate
+  // to the current pending entry. The NavigationController should be called
+  // back with RendererDidNavigate on success or DiscardPendingEntry on failure.
+  // The callbacks can be inside of this function, or at some future time.
+  //
+  // The entry has a PageID of -1 if newly created (corresponding to navigation
+  // to a new URL).
+  //
+  // If this method returns false, then the navigation is discarded (equivalent
+  // to calling DiscardPendingEntry on the NavigationController).
+  virtual bool NavigateToPendingEntry(
+      NavigationController::ReloadType reload_type) OVERRIDE;
+
+  // Sets the history for this WebContentsImpl to |history_length| entries, and
+  // moves the current page_id to the last entry in the list if it's valid.
+  // This is mainly used when a prerendered page is swapped into the current
+  // tab. The method is virtual for testing.
+  virtual void SetHistoryLengthAndPrune(
+      const SiteInstance* site_instance,
+      int merge_history_length,
+      int32 minimum_page_id) OVERRIDE;
 
  private:
   friend class NavigationControllerImpl;
@@ -693,15 +712,6 @@
   bool NavigateToEntry(const NavigationEntryImpl& entry,
                        NavigationController::ReloadType reload_type);
 
-  // Sets the history for this WebContentsImpl to |history_length| entries, and
-  // moves the current page_id to the last entry in the list if it's valid.
-  // This is mainly used when a prerendered page is swapped into the current
-  // tab. The method is virtual for testing.
-  virtual void SetHistoryLengthAndPrune(
-      const SiteInstance* site_instance,
-      int merge_history_length,
-      int32 minimum_page_id);
-
   // Recursively creates swapped out RenderViews for this tab's opener chain
   // (including this tab) in the given SiteInstance, allowing other tabs to send
   // cross-process JavaScript calls to their opener(s).  Returns the route ID of
@@ -739,7 +749,6 @@
   // Helper functions for sending notifications.
   void NotifySwapped(RenderViewHost* old_host, RenderViewHost* new_host);
   void NotifyDisconnected();
-  void NotifyNavigationEntryCommitted(const LoadCommittedDetails& load_details);
 
   void SetEncoding(const std::string& encoding);
 
diff --git a/content/browser/web_contents/web_contents_screenshot_manager.cc b/content/browser/web_contents/web_contents_screenshot_manager.cc
index 811e4ea..d7becb5 100644
--- a/content/browser/web_contents/web_contents_screenshot_manager.cc
+++ b/content/browser/web_contents/web_contents_screenshot_manager.cc
@@ -81,7 +81,7 @@
     return;
 
   RenderViewHost* render_view_host =
-      owner_->web_contents()->GetRenderViewHost();
+      owner_->delegate()->GetRenderViewHost();
   if (!static_cast<RenderViewHostImpl*>
       (render_view_host)->overscroll_controller()) {
     return;
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 3bd337e..a1bf021 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -1135,6 +1135,7 @@
     'browser/web_contents/drag_utils_gtk.h',
     'browser/web_contents/interstitial_page_impl.cc',
     'browser/web_contents/interstitial_page_impl.h',
+    'browser/web_contents/navigation_controller_delegate.h',
     'browser/web_contents/navigation_controller_impl.cc',
     'browser/web_contents/navigation_controller_impl.h',
     'browser/web_contents/navigation_entry_impl.cc',