- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / web_contents / web_contents_impl_browsertest.cc
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/web_contents/web_contents_impl.h"
7 #include "content/public/browser/load_notification_details.h"
8 #include "content/public/browser/navigation_controller.h"
9 #include "content/public/browser/notification_details.h"
10 #include "content/public/browser/notification_observer.h"
11 #include "content/public/browser/notification_types.h"
12 #include "content/public/browser/render_view_host.h"
13 #include "content/public/browser/render_widget_host_view.h"
14 #include "content/public/browser/web_contents_observer.h"
15 #include "content/public/browser/web_contents_view.h"
16 #include "content/public/common/content_paths.h"
17 #include "content/public/test/browser_test_utils.h"
18 #include "content/public/test/test_utils.h"
19 #include "content/shell/browser/shell.h"
20 #include "content/test/content_browser_test.h"
21 #include "content/test/content_browser_test_utils.h"
22 #include "net/test/embedded_test_server/embedded_test_server.h"
23
24 namespace content {
25
26 void ResizeWebContentsView(Shell* shell, const gfx::Size& size,
27                            bool set_start_page) {
28   // Shell::SizeTo is not implemented on Aura; WebContentsView::SizeContents
29   // works on Win and ChromeOS but not Linux - we need to resize the shell
30   // window on Linux because if we don't, the next layout of the unchanged shell
31   // window will resize WebContentsView back to the previous size.
32   // The cleaner and shorter SizeContents is preferred as more platforms convert
33   // to Aura.
34 #if defined(TOOLKIT_GTK) || defined(OS_MACOSX)
35   shell->SizeTo(size.width(), size.height());
36   // If |set_start_page| is true, start with blank page to make sure resize
37   // takes effect.
38   if (set_start_page)
39     NavigateToURL(shell, GURL("about://blank"));
40 #else
41   shell->web_contents()->GetView()->SizeContents(size);
42 #endif  // defined(TOOLKIT_GTK) || defined(OS_MACOSX)
43 }
44
45 class WebContentsImplBrowserTest : public ContentBrowserTest {
46  public:
47   WebContentsImplBrowserTest() {}
48
49  private:
50   DISALLOW_COPY_AND_ASSIGN(WebContentsImplBrowserTest);
51 };
52
53 // Keeps track of data from LoadNotificationDetails so we can later verify that
54 // they are correct, after the LoadNotificationDetails object is deleted.
55 class LoadStopNotificationObserver : public WindowedNotificationObserver {
56  public:
57   LoadStopNotificationObserver(NavigationController* controller)
58       : WindowedNotificationObserver(NOTIFICATION_LOAD_STOP,
59                                      Source<NavigationController>(controller)),
60         session_index_(-1),
61         controller_(NULL) {
62   }
63   virtual void Observe(int type,
64                        const NotificationSource& source,
65                        const NotificationDetails& details) OVERRIDE {
66     if (type == NOTIFICATION_LOAD_STOP) {
67       const Details<LoadNotificationDetails> load_details(details);
68       url_ = load_details->url;
69       session_index_ = load_details->session_index;
70       controller_ = load_details->controller;
71     }
72     WindowedNotificationObserver::Observe(type, source, details);
73   }
74
75   GURL url_;
76   int session_index_;
77   NavigationController* controller_;
78 };
79
80 // Starts a new navigation as soon as the current one commits, but does not
81 // wait for it to complete.  This allows us to observe DidStopLoading while
82 // a pending entry is present.
83 class NavigateOnCommitObserver : public WebContentsObserver {
84  public:
85   NavigateOnCommitObserver(Shell* shell, GURL url)
86       : WebContentsObserver(shell->web_contents()),
87         shell_(shell),
88         url_(url),
89         done_(false) {
90   }
91
92   // WebContentsObserver:
93   virtual void NavigationEntryCommitted(
94       const LoadCommittedDetails& load_details) OVERRIDE {
95     if (!done_) {
96       done_ = true;
97       shell_->LoadURL(url_);
98     }
99   }
100
101   Shell* shell_;
102   GURL url_;
103   bool done_;
104 };
105
106 class RenderViewSizeDelegate : public WebContentsDelegate {
107  public:
108   void set_size_insets(const gfx::Size& size_insets) {
109     size_insets_ = size_insets;
110   }
111
112   // WebContentsDelegate:
113   virtual gfx::Size GetSizeForNewRenderView(
114       const WebContents* web_contents) const OVERRIDE {
115     gfx::Size size(web_contents->GetView()->GetContainerSize());
116     size.Enlarge(size_insets_.width(), size_insets_.height());
117     return size;
118   }
119
120  private:
121   gfx::Size size_insets_;
122 };
123
124 class RenderViewSizeObserver : public WebContentsObserver {
125  public:
126   RenderViewSizeObserver(Shell* shell, const gfx::Size& wcv_new_size)
127       : WebContentsObserver(shell->web_contents()),
128         shell_(shell),
129         wcv_new_size_(wcv_new_size) {
130   }
131
132   // WebContentsObserver:
133   virtual void RenderViewCreated(RenderViewHost* rvh) OVERRIDE {
134     rwhv_create_size_ = rvh->GetView()->GetViewBounds().size();
135   }
136
137   virtual void NavigateToPendingEntry(
138       const GURL& url,
139       NavigationController::ReloadType reload_type) OVERRIDE {
140     ResizeWebContentsView(shell_, wcv_new_size_, false);
141   }
142
143   gfx::Size rwhv_create_size() const { return rwhv_create_size_; }
144
145  private:
146   Shell* shell_;  // Weak ptr.
147   gfx::Size wcv_new_size_;
148   gfx::Size rwhv_create_size_;
149 };
150
151 // See: http://crbug.com/298193
152 #if defined(OS_WIN)
153 #define MAYBE_DidStopLoadingDetails DISABLED_DidStopLoadingDetails
154 #else
155 #define MAYBE_DidStopLoadingDetails DidStopLoadingDetails
156 #endif
157
158 // Test that DidStopLoading includes the correct URL in the details.
159 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
160                        MAYBE_DidStopLoadingDetails) {
161   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
162
163   LoadStopNotificationObserver load_observer(
164       &shell()->web_contents()->GetController());
165   NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
166   load_observer.Wait();
167
168   EXPECT_EQ("/title1.html", load_observer.url_.path());
169   EXPECT_EQ(0, load_observer.session_index_);
170   EXPECT_EQ(&shell()->web_contents()->GetController(),
171             load_observer.controller_);
172 }
173
174 // See: http://crbug.com/298193
175 #if defined(OS_WIN)
176 #define MAYBE_DidStopLoadingDetailsWithPending \
177   DISABLED_DidStopLoadingDetailsWithPending
178 #else
179 #define MAYBE_DidStopLoadingDetailsWithPending DidStopLoadingDetailsWithPending
180 #endif
181
182 // Test that DidStopLoading includes the correct URL in the details when a
183 // pending entry is present.
184 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
185                        MAYBE_DidStopLoadingDetailsWithPending) {
186   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
187
188   // Listen for the first load to stop.
189   LoadStopNotificationObserver load_observer(
190       &shell()->web_contents()->GetController());
191   // Start a new pending navigation as soon as the first load commits.
192   // We will hear a DidStopLoading from the first load as the new load
193   // is started.
194   NavigateOnCommitObserver commit_observer(
195       shell(), embedded_test_server()->GetURL("/title2.html"));
196   NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
197   load_observer.Wait();
198
199   EXPECT_EQ("/title1.html", load_observer.url_.path());
200   EXPECT_EQ(0, load_observer.session_index_);
201   EXPECT_EQ(&shell()->web_contents()->GetController(),
202             load_observer.controller_);
203 }
204 // Test that a renderer-initiated navigation to an invalid URL does not leave
205 // around a pending entry that could be used in a URL spoof.  We test this in
206 // a browser test because our unit test framework incorrectly calls
207 // DidStartProvisionalLoadForFrame for in-page navigations.
208 // See http://crbug.com/280512.
209 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
210                        ClearNonVisiblePendingOnFail) {
211   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
212
213   NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
214
215   // Navigate to an invalid URL and make sure it doesn't leave a pending entry.
216   LoadStopNotificationObserver load_observer1(
217       &shell()->web_contents()->GetController());
218   ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
219                             "window.location.href=\"nonexistent:12121\";"));
220   load_observer1.Wait();
221   EXPECT_FALSE(shell()->web_contents()->GetController().GetPendingEntry());
222
223   LoadStopNotificationObserver load_observer2(
224       &shell()->web_contents()->GetController());
225   ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
226                             "window.location.href=\"#foo\";"));
227   load_observer2.Wait();
228   EXPECT_EQ(embedded_test_server()->GetURL("/title1.html#foo"),
229             shell()->web_contents()->GetVisibleURL());
230 }
231
232 // TODO(sail): enable this for MAC when auto resizing of WebContentsViewCocoa is
233 // fixed.
234 // TODO(shrikant): enable this for Windows when issue with
235 // force-compositing-mode is resolved (http://crbug.com/281726).
236 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID)
237 #define MAYBE_GetSizeForNewRenderView DISABLED_GetSizeForNewRenderView
238 #else
239 #define MAYBE_GetSizeForNewRenderView GetSizeForNewRenderView
240 #endif
241 // Test that RenderViewHost is created and updated at the size specified by
242 // WebContentsDelegate::GetSizeForNewRenderView().
243 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
244                        MAYBE_GetSizeForNewRenderView) {
245   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
246   // Create a new server with a different site.
247   net::SpawnedTestServer https_server(
248       net::SpawnedTestServer::TYPE_HTTPS,
249       net::SpawnedTestServer::kLocalhost,
250       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
251   ASSERT_TRUE(https_server.Start());
252
253   scoped_ptr<RenderViewSizeDelegate> delegate(new RenderViewSizeDelegate());
254   shell()->web_contents()->SetDelegate(delegate.get());
255   ASSERT_TRUE(shell()->web_contents()->GetDelegate() == delegate.get());
256
257   // When no size is set, RenderWidgetHostView adopts the size of
258   // WebContenntsView.
259   NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html"));
260   EXPECT_EQ(shell()->web_contents()->GetView()->GetContainerSize(),
261             shell()->web_contents()->GetRenderWidgetHostView()->GetViewBounds().
262                 size());
263
264   // When a size is set, RenderWidgetHostView and WebContentsView honor this
265   // size.
266   gfx::Size size(300, 300);
267   gfx::Size size_insets(-10, -15);
268   ResizeWebContentsView(shell(), size, true);
269   delegate->set_size_insets(size_insets);
270   NavigateToURL(shell(), https_server.GetURL("/"));
271   size.Enlarge(size_insets.width(), size_insets.height());
272   EXPECT_EQ(size,
273             shell()->web_contents()->GetRenderWidgetHostView()->GetViewBounds().
274                 size());
275   EXPECT_EQ(size, shell()->web_contents()->GetView()->GetContainerSize());
276
277   // If WebContentsView is resized after RenderWidgetHostView is created but
278   // before pending navigation entry is committed, both RenderWidgetHostView and
279   // WebContentsView use the new size of WebContentsView.
280   gfx::Size init_size(200, 200);
281   gfx::Size new_size(100, 100);
282   size_insets = gfx::Size(-20, -30);
283   ResizeWebContentsView(shell(), init_size, true);
284   delegate->set_size_insets(size_insets);
285   RenderViewSizeObserver observer(shell(), new_size);
286   NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
287   // RenderWidgetHostView is created at specified size.
288   init_size.Enlarge(size_insets.width(), size_insets.height());
289   EXPECT_EQ(init_size, observer.rwhv_create_size());
290   // RenderViewSizeObserver resizes WebContentsView in NavigateToPendingEntry,
291   // so both WebContentsView and RenderWidgetHostView adopt this new size.
292   new_size.Enlarge(size_insets.width(), size_insets.height());
293   EXPECT_EQ(new_size,
294             shell()->web_contents()->GetRenderWidgetHostView()->GetViewBounds().
295                 size());
296   EXPECT_EQ(new_size, shell()->web_contents()->GetView()->GetContainerSize());
297 }
298
299 }  // namespace content