web_contents_impl_browsertest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/values.h"
6#include "content/browser/renderer_host/render_view_host_impl.h"
7#include "content/browser/web_contents/web_contents_impl.h"
8#include "content/public/browser/load_notification_details.h"
9#include "content/public/browser/navigation_controller.h"
10#include "content/public/browser/notification_details.h"
11#include "content/public/browser/notification_observer.h"
12#include "content/public/browser/notification_types.h"
13#include "content/public/common/content_paths.h"
14#include "content/public/test/browser_test_utils.h"
15#include "content/public/test/test_utils.h"
16#include "content/shell/shell.h"
17#include "content/test/content_browser_test.h"
18#include "content/test/content_browser_test_utils.h"
19#include "net/test/embedded_test_server/embedded_test_server.h"
20
21namespace content {
22
23class WebContentsImplBrowserTest : public ContentBrowserTest {
24 public:
25  WebContentsImplBrowserTest() {}
26
27 private:
28  DISALLOW_COPY_AND_ASSIGN(WebContentsImplBrowserTest);
29};
30
31// Keeps track of data from LoadNotificationDetails so we can later verify that
32// they are correct, after the LoadNotificationDetails object is deleted.
33class LoadStopNotificationObserver : public WindowedNotificationObserver {
34 public:
35  LoadStopNotificationObserver(NavigationController* controller)
36      : WindowedNotificationObserver(NOTIFICATION_LOAD_STOP,
37                                     Source<NavigationController>(controller)),
38        session_index_(-1),
39        controller_(NULL) {
40  }
41  virtual void Observe(int type,
42                       const NotificationSource& source,
43                       const NotificationDetails& details) OVERRIDE {
44    if (type == NOTIFICATION_LOAD_STOP) {
45      const Details<LoadNotificationDetails> load_details(details);
46      url_ = load_details->url;
47      session_index_ = load_details->session_index;
48      controller_ = load_details->controller;
49    }
50    WindowedNotificationObserver::Observe(type, source, details);
51  }
52
53  GURL url_;
54  int session_index_;
55  NavigationController* controller_;
56};
57
58// Starts a new navigation as soon as the current one commits, but does not
59// wait for it to complete.  This allows us to observe DidStopLoading while
60// a pending entry is present.
61class NavigateOnCommitObserver : public WindowedNotificationObserver {
62 public:
63  NavigateOnCommitObserver(Shell* shell, GURL url)
64      : WindowedNotificationObserver(
65            NOTIFICATION_NAV_ENTRY_COMMITTED,
66            Source<NavigationController>(
67                &shell->web_contents()->GetController())),
68        shell_(shell),
69        url_(url),
70        done_(false) {
71  }
72  virtual void Observe(int type,
73                       const NotificationSource& source,
74                       const NotificationDetails& details) OVERRIDE {
75    if (type == NOTIFICATION_NAV_ENTRY_COMMITTED && !done_) {
76      done_ = true;
77      shell_->LoadURL(url_);
78    }
79    WindowedNotificationObserver::Observe(type, source, details);
80  }
81
82  Shell* shell_;
83  GURL url_;
84  bool done_;
85};
86
87// Test that DidStopLoading includes the correct URL in the details.
88IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DidStopLoadingDetails) {
89  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
90
91  LoadStopNotificationObserver load_observer(
92      &shell()->web_contents()->GetController());
93  NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
94  load_observer.Wait();
95
96  EXPECT_EQ("/title1.html", load_observer.url_.path());
97  EXPECT_EQ(0, load_observer.session_index_);
98  EXPECT_EQ(&shell()->web_contents()->GetController(),
99            load_observer.controller_);
100}
101
102// Test that DidStopLoading includes the correct URL in the details when a
103// pending entry is present.
104IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
105                       DidStopLoadingDetailsWithPending) {
106  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
107
108  // Listen for the first load to stop.
109  LoadStopNotificationObserver load_observer(
110      &shell()->web_contents()->GetController());
111  // Start a new pending navigation as soon as the first load commits.
112  // We will hear a DidStopLoading from the first load as the new load
113  // is started.
114  NavigateOnCommitObserver commit_observer(
115      shell(), embedded_test_server()->GetURL("/title2.html"));
116  NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
117  commit_observer.Wait();
118  load_observer.Wait();
119
120  EXPECT_EQ("/title1.html", load_observer.url_.path());
121  EXPECT_EQ(0, load_observer.session_index_);
122  EXPECT_EQ(&shell()->web_contents()->GetController(),
123            load_observer.controller_);
124}
125
126// Test that the browser receives the proper frame attach/detach messages from
127// the renderer and builds proper frame tree.
128IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, FrameTree) {
129  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
130
131  NavigateToURL(shell(),
132                embedded_test_server()->GetURL("/frame_tree/top.html"));
133
134  WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
135  RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
136      wc->GetRenderViewHost());
137  FrameTreeNode* root = wc->GetFrameTreeRootForTesting();
138
139  // Check that the root node is properly created with the frame id of the
140  // initial navigation.
141  EXPECT_EQ(3UL, root->child_count());
142  EXPECT_EQ(std::string(), root->frame_name());
143  EXPECT_EQ(rvh->main_frame_id(), root->frame_id());
144
145  EXPECT_EQ(2UL, root->child_at(0)->child_count());
146  EXPECT_STREQ("1-1-name", root->child_at(0)->frame_name().c_str());
147
148  // Verify the deepest node exists and has the right name.
149  EXPECT_EQ(2UL, root->child_at(2)->child_count());
150  EXPECT_EQ(1UL, root->child_at(2)->child_at(1)->child_count());
151  EXPECT_EQ(0UL, root->child_at(2)->child_at(1)->child_at(0)->child_count());
152  EXPECT_STREQ("3-1-id",
153      root->child_at(2)->child_at(1)->child_at(0)->frame_name().c_str());
154
155  // Navigate to about:blank, which should leave only the root node of the frame
156  // tree in the browser process.
157  NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
158
159  root = wc->GetFrameTreeRootForTesting();
160  EXPECT_EQ(0UL, root->child_count());
161  EXPECT_EQ(std::string(), root->frame_name());
162  EXPECT_EQ(rvh->main_frame_id(), root->frame_id());
163}
164
165}  // namespace content
166