Add Navigator and NavigatorDelegate objects.

BUG=304341

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@234067 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/browser/frame_host/frame_tree.cc b/content/browser/frame_host/frame_tree.cc
index 440b095..34d117b7 100644
--- a/content/browser/frame_host/frame_tree.cc
+++ b/content/browser/frame_host/frame_tree.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/navigator.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 
 namespace content {
@@ -41,9 +42,9 @@
 
 }  // namespace
 
-FrameTree::FrameTree()
+FrameTree::FrameTree(Navigator* navigator)
     : root_(new FrameTreeNode(FrameTreeNode::kInvalidFrameId, std::string(),
-                              scoped_ptr<RenderFrameHostImpl>())) {
+                              navigator, scoped_ptr<RenderFrameHostImpl>())) {
 }
 
 FrameTree::~FrameTree() {
@@ -90,6 +91,7 @@
     return;
 
   parent->AddChild(CreateNode(frame_id, frame_name, render_frame_host_id,
+                              parent->navigator(),
                               parent->render_frame_host()->GetProcess()));
 }
 
@@ -150,13 +152,14 @@
     int64 frame_id,
     const std::string& frame_name,
     int render_frame_host_id,
+    Navigator* navigator,
     RenderProcessHost* render_process_host) {
   scoped_ptr<RenderFrameHostImpl> render_frame_host(
       new RenderFrameHostImpl(root_->render_frame_host()->render_view_host(),
                               this, render_frame_host_id, false));
 
-  return make_scoped_ptr(new FrameTreeNode(frame_id, frame_name,
-                                           render_frame_host.Pass()));
+  return make_scoped_ptr(new FrameTreeNode(
+      frame_id, frame_name, navigator, render_frame_host.Pass()));
 }
 
 }  // namespace content
diff --git a/content/browser/frame_host/frame_tree.h b/content/browser/frame_host/frame_tree.h
index 6824e7e..91a0c29f 100644
--- a/content/browser/frame_host/frame_tree.h
+++ b/content/browser/frame_host/frame_tree.h
@@ -15,6 +15,7 @@
 namespace content {
 
 class FrameTreeNode;
+class Navigator;
 class RenderProcessHost;
 class RenderViewHostImpl;
 
@@ -35,7 +36,9 @@
 // This object is only used on the UI thread.
 class CONTENT_EXPORT FrameTree {
  public:
-  FrameTree();
+  // Each FrameTreeNode will default to using the given |navigator| for
+  // navigation tasks in the frame.
+  FrameTree(Navigator* navigator);
   ~FrameTree();
 
   // Returns the FrameTreeNode with the given |frame_tree_node_id|.
@@ -100,6 +103,7 @@
   scoped_ptr<FrameTreeNode> CreateNode(int64 frame_id,
                                        const std::string& frame_name,
                                        int render_frame_host_id,
+                                       Navigator* navigator,
                                        RenderProcessHost* render_process_host);
 
   scoped_ptr<FrameTreeNode> root_;
diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc
index fc45dc1f..fd9a3bf 100644
--- a/content/browser/frame_host/frame_tree_node.cc
+++ b/content/browser/frame_host/frame_tree_node.cc
@@ -7,6 +7,7 @@
 #include <queue>
 
 #include "base/stl_util.h"
+#include "content/browser/frame_host/navigator.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 
 namespace content {
@@ -14,12 +15,15 @@
 const int64 FrameTreeNode::kInvalidFrameId = -1;
 int64 FrameTreeNode::next_frame_tree_node_id_ = 1;
 
-FrameTreeNode::FrameTreeNode(int64 frame_id,
-                             const std::string& name,
-                             scoped_ptr<RenderFrameHostImpl> render_frame_host)
+FrameTreeNode::FrameTreeNode(
+  int64 frame_id,
+  const std::string& name,
+  Navigator* navigator,
+  scoped_ptr<RenderFrameHostImpl> render_frame_host)
   : frame_tree_node_id_(next_frame_tree_node_id_++),
     frame_id_(frame_id),
     frame_name_(name),
+    navigator_(navigator),
     owns_render_frame_host_(true),
     render_frame_host_(render_frame_host.release()) {
 }
diff --git a/content/browser/frame_host/frame_tree_node.h b/content/browser/frame_host/frame_tree_node.h
index 36faa1a..8bacc776 100644
--- a/content/browser/frame_host/frame_tree_node.h
+++ b/content/browser/frame_host/frame_tree_node.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "content/common/content_export.h"
@@ -15,6 +16,7 @@
 
 namespace content {
 
+class Navigator;
 class RenderFrameHostImpl;
 
 // When a page contains iframes, its renderer process maintains a tree structure
@@ -25,9 +27,12 @@
  public:
   static const int64 kInvalidFrameId;
 
-  FrameTreeNode(int64 frame_id,
-                const std::string& name,
-                scoped_ptr<RenderFrameHostImpl> render_frame_host);
+  FrameTreeNode(
+    int64 frame_id,
+    const std::string& name,
+    Navigator* navigator,
+    scoped_ptr<RenderFrameHostImpl> render_frame_host);
+
   ~FrameTreeNode();
 
   void AddChild(scoped_ptr<FrameTreeNode> child);
@@ -81,6 +86,10 @@
     return render_frame_host_;
   }
 
+  Navigator* navigator() {
+    return navigator_.get();
+  }
+
  private:
   // The next available browser-global FrameTreeNode ID.
   static int64 next_frame_tree_node_id_;
@@ -102,6 +111,10 @@
   // The immediate children of this specific frame.
   ScopedVector<FrameTreeNode> children_;
 
+  // The Navigator object responsible for managing navigations at this node
+  // of the frame tree.
+  scoped_refptr<Navigator> navigator_;
+
   // When ResetForMainFrame() is called, this is set to false and the
   // |render_frame_host_| below is not deleted on destruction.
   //
diff --git a/content/browser/frame_host/frame_tree_unittest.cc b/content/browser/frame_host/frame_tree_unittest.cc
index 20295dc..28f1b88 100644
--- a/content/browser/frame_host/frame_tree_unittest.cc
+++ b/content/browser/frame_host/frame_tree_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
+#include "content/browser/frame_host/navigator.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/public/test/mock_render_process_host.h"
@@ -51,7 +52,7 @@
 //  - Swapping back to NULL doesn't crash (easier tear-down for interstitials).
 //  - Main frame does not own RenderFrameHost.
 TEST_F(FrameTreeTest, RootNode) {
-  FrameTree frame_tree;
+  FrameTree frame_tree(new Navigator(NULL, NULL));
 
   // Initial state has empty node.
   FrameTreeNode* root = frame_tree.GetRootForTesting();
@@ -78,7 +79,7 @@
 //  - On creation, frame id is unassigned.
 //  - After a swap, frame id is unassigned.
 TEST_F(FrameTreeTest, FirstNavigationAfterSwap) {
-  FrameTree frame_tree;
+  FrameTree frame_tree(new Navigator(NULL, NULL));
 
   EXPECT_TRUE(frame_tree.IsFirstNavigationAfterSwap());
   EXPECT_EQ(FrameTreeNode::kInvalidFrameId,
@@ -97,7 +98,8 @@
 //  - Add a series of nodes and verify tree structure.
 //  - Remove a series of nodes and verify tree structure.
 TEST_F(FrameTreeTest, Shape) {
-  FrameTree frame_tree;
+  FrameTree frame_tree(new Navigator(NULL, NULL));
+
   std::string no_children_node("no children node");
   std::string deep_subtree("node with deep subtree");
 
diff --git a/content/browser/frame_host/interstitial_page_impl.cc b/content/browser/frame_host/interstitial_page_impl.cc
index 2516621..68991492 100644
--- a/content/browser/frame_host/interstitial_page_impl.cc
+++ b/content/browser/frame_host/interstitial_page_impl.cc
@@ -16,6 +16,7 @@
 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
 #include "content/browser/frame_host/navigation_controller_impl.h"
 #include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/frame_host/navigator.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_factory.h"
@@ -154,6 +155,11 @@
       enabled_(true),
       action_taken_(NO_ACTION),
       render_view_host_(NULL),
+      // TODO(nasko): The InterstitialPageImpl will need to provide its own
+      // NavigationControllerImpl to the Navigator, which is separate from
+      // the WebContents one, so we can enforce no navigation policy here.
+      // While we get the code to a point to do this, pass NULL for it.
+      frame_tree_(new Navigator(NULL, this)),
       original_child_id_(web_contents->GetRenderProcessHost()->GetID()),
       original_rvh_id_(web_contents->GetRenderViewHost()->GetRoutingID()),
       should_revert_web_contents_title_(false),
diff --git a/content/browser/frame_host/interstitial_page_impl.h b/content/browser/frame_host/interstitial_page_impl.h
index 347a014..47a127e 100644
--- a/content/browser/frame_host/interstitial_page_impl.h
+++ b/content/browser/frame_host/interstitial_page_impl.h
@@ -9,6 +9,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/frame_host/navigator_delegate.h"
 #include "content/browser/renderer_host/render_view_host_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/public/browser/interstitial_page.h"
@@ -21,6 +22,7 @@
 namespace content {
 class NavigationEntry;
 class NavigationControllerImpl;
+class Navigator;
 class RenderViewHostImpl;
 class RenderWidgetHostView;
 class WebContentsView;
@@ -37,7 +39,8 @@
       public NotificationObserver,
       public WebContentsObserver,
       public RenderViewHostDelegate,
-      public RenderWidgetHostDelegate {
+      public RenderWidgetHostDelegate,
+      public NON_EXPORTED_BASE(NavigatorDelegate) {
  public:
   // The different state of actions the user can take in an interstitial.
   enum ActionState {
diff --git a/content/browser/frame_host/navigator.cc b/content/browser/frame_host/navigator.cc
new file mode 100644
index 0000000..4ca26b68
--- /dev/null
+++ b/content/browser/frame_host/navigator.cc
@@ -0,0 +1,18 @@
+// 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.
+
+#include "content/browser/frame_host/navigator.h"
+
+#include "content/browser/frame_host/navigator_delegate.h"
+
+namespace content {
+
+Navigator::Navigator(
+    NavigationControllerImpl* nav_controller,
+    NavigatorDelegate* delegate)
+    : controller_(nav_controller),
+      delegate_(delegate) {
+}
+
+}  // namespace content
diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h
new file mode 100644
index 0000000..c20c9dd
--- /dev/null
+++ b/content/browser/frame_host/navigator.h
@@ -0,0 +1,53 @@
+// 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_FRAME_HOST_NAVIGATOR_H_
+#define CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_H_
+
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class NavigationControllerImpl;
+class NavigatorDelegate;
+
+// This class is responsible for performing navigations in a node of the
+// FrameTree. Its lifetime is bound to all FrameTreeNode objects that are
+// using it and will be released once all nodes that use it are freed.
+// The Navigator is bound to a single frame tree and cannot be used by multiple
+// instances of FrameTree.
+// TODO(nasko): Move all navigation methods, such as didStartProvisionalLoad
+// from WebContentsImpl to this class.
+class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
+ public:
+  Navigator(NavigationControllerImpl* nav_controller,
+            NavigatorDelegate* delegate);
+
+  NavigationControllerImpl* controller() {
+    return controller_;
+  }
+
+  NavigatorDelegate* delegate() {
+    return delegate_;
+  }
+
+ private:
+  friend class base::RefCounted<Navigator>;
+  virtual ~Navigator() {}
+
+  // The NavigationController that will keep track of session history for all
+  // RenderFrameHost objects using this Navigator.
+  // TODO(nasko): Move ownership of the NavigationController from
+  // WebContentsImpl to this class.
+  NavigationControllerImpl* controller_;
+
+  // Used to notify the object embedding this Navigator about navigation
+  // events. Can be NULL in tests.
+  NavigatorDelegate* delegate_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_H_
diff --git a/content/browser/frame_host/navigator_delegate.h b/content/browser/frame_host/navigator_delegate.h
new file mode 100644
index 0000000..c906b6b
--- /dev/null
+++ b/content/browser/frame_host/navigator_delegate.h
@@ -0,0 +1,23 @@
+// 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_FRAME_HOST_NAVIGATOR_DELEGATE_H_
+#define CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_DELEGATE_H_
+
+namespace content {
+
+class RenderFrameHost;
+
+// A delegate API used by Navigator to notify its embedder of navigation
+// related events.
+class NavigatorDelegate {
+  // TODO(nasko): This class will be used to dispatch notifications to
+  // WebContentsImpl, such as DidStartProvisionalLoad and
+  // NotifyNavigationStateChanged. Longer term, most of the
+  // NavigationControllerDelegate methods will likely move here.
+};
+
+}  // namspace content
+
+#endif  // CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_DELEGATE_H_
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 3ca6c66..99d7e60 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -29,6 +29,7 @@
 #include "content/browser/download/save_package.h"
 #include "content/browser/frame_host/interstitial_page_impl.h"
 #include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/frame_host/navigator.h"
 #include "content/browser/host_zoom_map_impl.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/message_port_message_filter.h"
@@ -342,6 +343,7 @@
       accessible_parent_(NULL),
 #endif
       render_manager_(this, this, this),
+      frame_tree_(new Navigator(&controller_, this)),
       is_loading_(false),
       crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
       crashed_error_code_(0),
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index d0ac6b3..a4530af2 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/frame_host/frame_tree.h"
 #include "content/browser/frame_host/navigation_controller_delegate.h"
 #include "content/browser/frame_host/navigation_controller_impl.h"
+#include "content/browser/frame_host/navigator_delegate.h"
 #include "content/browser/frame_host/render_view_host_manager.h"
 #include "content/browser/renderer_host/render_view_host_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
@@ -48,6 +49,7 @@
 class InterstitialPageImpl;
 class JavaBridgeDispatcherHostManager;
 class JavaScriptDialogManager;
+class Navigator;
 class PowerSaveBlocker;
 class RenderViewHost;
 class RenderViewHostDelegateView;
@@ -79,7 +81,8 @@
       public RenderWidgetHostDelegate,
       public RenderViewHostManager::Delegate,
       public NotificationObserver,
-      public NON_EXPORTED_BASE(NavigationControllerDelegate) {
+      public NON_EXPORTED_BASE(NavigationControllerDelegate),
+      public NON_EXPORTED_BASE(NavigatorDelegate) {
  public:
   virtual ~WebContentsImpl();