Android: Store language .pak files in res/raw rather than assets
[chromium-blink-merge.git] / content / browser / web_contents / web_contents_impl_browsertest.cc
blobd52f967eebdf935607e3c480e2db601179322cd1
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.
5 #include "base/strings/utf_string_conversions.h"
6 #include "base/values.h"
7 #include "content/browser/frame_host/navigation_entry_impl.h"
8 #include "content/browser/renderer_host/render_widget_host_impl.h"
9 #include "content/browser/web_contents/web_contents_impl.h"
10 #include "content/browser/web_contents/web_contents_view.h"
11 #include "content/common/frame_messages.h"
12 #include "content/public/browser/load_notification_details.h"
13 #include "content/public/browser/navigation_controller.h"
14 #include "content/public/browser/notification_details.h"
15 #include "content/public/browser/notification_observer.h"
16 #include "content/public/browser/notification_types.h"
17 #include "content/public/browser/render_view_host.h"
18 #include "content/public/browser/render_widget_host_view.h"
19 #include "content/public/browser/web_contents_observer.h"
20 #include "content/public/common/content_paths.h"
21 #include "content/public/test/browser_test_utils.h"
22 #include "content/public/test/content_browser_test.h"
23 #include "content/public/test/content_browser_test_utils.h"
24 #include "content/public/test/test_navigation_observer.h"
25 #include "content/public/test/test_utils.h"
26 #include "content/shell/browser/shell.h"
27 #include "net/dns/mock_host_resolver.h"
28 #include "net/test/embedded_test_server/embedded_test_server.h"
30 namespace content {
32 void ResizeWebContentsView(Shell* shell, const gfx::Size& size,
33 bool set_start_page) {
34 // Shell::SizeTo is not implemented on Aura; WebContentsView::SizeContents
35 // works on Win and ChromeOS but not Linux - we need to resize the shell
36 // window on Linux because if we don't, the next layout of the unchanged shell
37 // window will resize WebContentsView back to the previous size.
38 // SizeContents is a hack and should not be relied on.
39 #if defined(OS_MACOSX)
40 shell->SizeTo(size);
41 // If |set_start_page| is true, start with blank page to make sure resize
42 // takes effect.
43 if (set_start_page)
44 NavigateToURL(shell, GURL("about://blank"));
45 #else
46 static_cast<WebContentsImpl*>(shell->web_contents())->GetView()->
47 SizeContents(size);
48 #endif // defined(OS_MACOSX)
51 class WebContentsImplBrowserTest : public ContentBrowserTest {
52 public:
53 WebContentsImplBrowserTest() {}
54 void SetUp() override {
55 RenderWidgetHostImpl::DisableResizeAckCheckForTesting();
56 ContentBrowserTest::SetUp();
59 private:
60 DISALLOW_COPY_AND_ASSIGN(WebContentsImplBrowserTest);
63 // Keeps track of data from LoadNotificationDetails so we can later verify that
64 // they are correct, after the LoadNotificationDetails object is deleted.
65 class LoadStopNotificationObserver : public WindowedNotificationObserver {
66 public:
67 LoadStopNotificationObserver(NavigationController* controller)
68 : WindowedNotificationObserver(NOTIFICATION_LOAD_STOP,
69 Source<NavigationController>(controller)),
70 session_index_(-1),
71 controller_(NULL) {
73 void Observe(int type,
74 const NotificationSource& source,
75 const NotificationDetails& details) override {
76 if (type == NOTIFICATION_LOAD_STOP) {
77 const Details<LoadNotificationDetails> load_details(details);
78 url_ = load_details->url;
79 session_index_ = load_details->session_index;
80 controller_ = load_details->controller;
82 WindowedNotificationObserver::Observe(type, source, details);
85 GURL url_;
86 int session_index_;
87 NavigationController* controller_;
90 // Starts a new navigation as soon as the current one commits, but does not
91 // wait for it to complete. This allows us to observe DidStopLoading while
92 // a pending entry is present.
93 class NavigateOnCommitObserver : public WebContentsObserver {
94 public:
95 NavigateOnCommitObserver(Shell* shell, GURL url)
96 : WebContentsObserver(shell->web_contents()),
97 shell_(shell),
98 url_(url),
99 done_(false) {
102 // WebContentsObserver:
103 void NavigationEntryCommitted(
104 const LoadCommittedDetails& load_details) override {
105 if (!done_) {
106 done_ = true;
107 shell_->Stop();
108 shell_->LoadURL(url_);
112 Shell* shell_;
113 GURL url_;
114 bool done_;
117 class RenderViewSizeDelegate : public WebContentsDelegate {
118 public:
119 void set_size_insets(const gfx::Size& size_insets) {
120 size_insets_ = size_insets;
123 // WebContentsDelegate:
124 gfx::Size GetSizeForNewRenderView(WebContents* web_contents) const override {
125 gfx::Size size(web_contents->GetContainerBounds().size());
126 size.Enlarge(size_insets_.width(), size_insets_.height());
127 return size;
130 private:
131 gfx::Size size_insets_;
134 class RenderViewSizeObserver : public WebContentsObserver {
135 public:
136 RenderViewSizeObserver(Shell* shell, const gfx::Size& wcv_new_size)
137 : WebContentsObserver(shell->web_contents()),
138 shell_(shell),
139 wcv_new_size_(wcv_new_size) {
142 // WebContentsObserver:
143 void RenderViewCreated(RenderViewHost* rvh) override {
144 rwhv_create_size_ = rvh->GetView()->GetViewBounds().size();
147 void DidStartProvisionalLoadForFrame(
148 RenderFrameHost* render_frame_host,
149 const GURL& url,
150 bool is_error_page,
151 bool is_iframe_srcdoc) override {
152 ResizeWebContentsView(shell_, wcv_new_size_, false);
155 gfx::Size rwhv_create_size() const { return rwhv_create_size_; }
157 private:
158 Shell* shell_; // Weak ptr.
159 gfx::Size wcv_new_size_;
160 gfx::Size rwhv_create_size_;
163 class LoadingStateChangedDelegate : public WebContentsDelegate {
164 public:
165 LoadingStateChangedDelegate()
166 : loadingStateChangedCount_(0)
167 , loadingStateToDifferentDocumentCount_(0) {
170 // WebContentsDelegate:
171 void LoadingStateChanged(WebContents* contents,
172 bool to_different_document) override {
173 loadingStateChangedCount_++;
174 if (to_different_document)
175 loadingStateToDifferentDocumentCount_++;
178 int loadingStateChangedCount() const { return loadingStateChangedCount_; }
179 int loadingStateToDifferentDocumentCount() const {
180 return loadingStateToDifferentDocumentCount_;
183 private:
184 int loadingStateChangedCount_;
185 int loadingStateToDifferentDocumentCount_;
188 // See: http://crbug.com/298193
189 #if defined(OS_WIN) || defined(OS_LINUX)
190 #define MAYBE_DidStopLoadingDetails DISABLED_DidStopLoadingDetails
191 #else
192 #define MAYBE_DidStopLoadingDetails DidStopLoadingDetails
193 #endif
195 // Test that DidStopLoading includes the correct URL in the details.
196 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
197 MAYBE_DidStopLoadingDetails) {
198 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
200 LoadStopNotificationObserver load_observer(
201 &shell()->web_contents()->GetController());
202 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
203 load_observer.Wait();
205 EXPECT_EQ("/title1.html", load_observer.url_.path());
206 EXPECT_EQ(0, load_observer.session_index_);
207 EXPECT_EQ(&shell()->web_contents()->GetController(),
208 load_observer.controller_);
211 // See: http://crbug.com/298193
212 #if defined(OS_WIN) || defined(OS_LINUX)
213 #define MAYBE_DidStopLoadingDetailsWithPending \
214 DISABLED_DidStopLoadingDetailsWithPending
215 #else
216 #define MAYBE_DidStopLoadingDetailsWithPending DidStopLoadingDetailsWithPending
217 #endif
219 // Test that DidStopLoading includes the correct URL in the details when a
220 // pending entry is present.
221 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
222 MAYBE_DidStopLoadingDetailsWithPending) {
223 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
224 GURL url("data:text/html,<div>test</div>");
226 // Listen for the first load to stop.
227 LoadStopNotificationObserver load_observer(
228 &shell()->web_contents()->GetController());
229 // Start a new pending navigation as soon as the first load commits.
230 // We will hear a DidStopLoading from the first load as the new load
231 // is started.
232 NavigateOnCommitObserver commit_observer(
233 shell(), embedded_test_server()->GetURL("/title2.html"));
234 NavigateToURL(shell(), url);
235 load_observer.Wait();
237 EXPECT_EQ(url, load_observer.url_);
238 EXPECT_EQ(0, load_observer.session_index_);
239 EXPECT_EQ(&shell()->web_contents()->GetController(),
240 load_observer.controller_);
242 // Test that a renderer-initiated navigation to an invalid URL does not leave
243 // around a pending entry that could be used in a URL spoof. We test this in
244 // a browser test because our unit test framework incorrectly calls
245 // DidStartProvisionalLoadForFrame for in-page navigations.
246 // See http://crbug.com/280512.
247 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
248 ClearNonVisiblePendingOnFail) {
249 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
251 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
253 // Navigate to an invalid URL and make sure it doesn't leave a pending entry.
254 LoadStopNotificationObserver load_observer1(
255 &shell()->web_contents()->GetController());
256 ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
257 "window.location.href=\"nonexistent:12121\";"));
258 load_observer1.Wait();
259 EXPECT_FALSE(shell()->web_contents()->GetController().GetPendingEntry());
261 LoadStopNotificationObserver load_observer2(
262 &shell()->web_contents()->GetController());
263 ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
264 "window.location.href=\"#foo\";"));
265 load_observer2.Wait();
266 EXPECT_EQ(embedded_test_server()->GetURL("/title1.html#foo"),
267 shell()->web_contents()->GetVisibleURL());
270 // Crashes under ThreadSanitizer, http://crbug.com/356758.
271 #if defined(OS_WIN) || defined(OS_ANDROID) \
272 || defined(THREAD_SANITIZER)
273 #define MAYBE_GetSizeForNewRenderView DISABLED_GetSizeForNewRenderView
274 #else
275 #define MAYBE_GetSizeForNewRenderView GetSizeForNewRenderView
276 #endif
277 // Test that RenderViewHost is created and updated at the size specified by
278 // WebContentsDelegate::GetSizeForNewRenderView().
279 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
280 MAYBE_GetSizeForNewRenderView) {
281 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
282 // Create a new server with a different site.
283 net::SpawnedTestServer https_server(
284 net::SpawnedTestServer::TYPE_HTTPS,
285 net::SpawnedTestServer::kLocalhost,
286 base::FilePath(FILE_PATH_LITERAL("content/test/data")));
287 ASSERT_TRUE(https_server.Start());
289 scoped_ptr<RenderViewSizeDelegate> delegate(new RenderViewSizeDelegate());
290 shell()->web_contents()->SetDelegate(delegate.get());
291 ASSERT_TRUE(shell()->web_contents()->GetDelegate() == delegate.get());
293 // When no size is set, RenderWidgetHostView adopts the size of
294 // WebContentsView.
295 NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html"));
296 EXPECT_EQ(shell()->web_contents()->GetContainerBounds().size(),
297 shell()->web_contents()->GetRenderWidgetHostView()->GetViewBounds().
298 size());
300 // When a size is set, RenderWidgetHostView and WebContentsView honor this
301 // size.
302 gfx::Size size(300, 300);
303 gfx::Size size_insets(10, 15);
304 ResizeWebContentsView(shell(), size, true);
305 delegate->set_size_insets(size_insets);
306 NavigateToURL(shell(), https_server.GetURL("/"));
307 size.Enlarge(size_insets.width(), size_insets.height());
308 EXPECT_EQ(size,
309 shell()->web_contents()->GetRenderWidgetHostView()->GetViewBounds().
310 size());
311 // The web_contents size is set by the embedder, and should not depend on the
312 // rwhv size. The behavior is correct on OSX, but incorrect on other
313 // platforms.
314 gfx::Size exp_wcv_size(300, 300);
315 #if !defined(OS_MACOSX)
316 exp_wcv_size.Enlarge(size_insets.width(), size_insets.height());
317 #endif
319 EXPECT_EQ(exp_wcv_size,
320 shell()->web_contents()->GetContainerBounds().size());
322 // If WebContentsView is resized after RenderWidgetHostView is created but
323 // before pending navigation entry is committed, both RenderWidgetHostView and
324 // WebContentsView use the new size of WebContentsView.
325 gfx::Size init_size(200, 200);
326 gfx::Size new_size(100, 100);
327 size_insets = gfx::Size(20, 30);
328 ResizeWebContentsView(shell(), init_size, true);
329 delegate->set_size_insets(size_insets);
330 RenderViewSizeObserver observer(shell(), new_size);
331 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
332 // RenderWidgetHostView is created at specified size.
333 init_size.Enlarge(size_insets.width(), size_insets.height());
334 EXPECT_EQ(init_size, observer.rwhv_create_size());
336 // Once again, the behavior is correct on OSX. The embedder explicitly sets
337 // the size to (100,100) during navigation. Both the wcv and the rwhv should
338 // take on that size.
339 #if !defined(OS_MACOSX)
340 new_size.Enlarge(size_insets.width(), size_insets.height());
341 #endif
342 gfx::Size actual_size = shell()->web_contents()->GetRenderWidgetHostView()->
343 GetViewBounds().size();
345 EXPECT_EQ(new_size, actual_size);
346 EXPECT_EQ(new_size, shell()->web_contents()->GetContainerBounds().size());
349 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, OpenURLSubframe) {
350 // Navigate to a page with frames and grab a subframe's FrameTreeNode ID.
351 ASSERT_TRUE(test_server()->Start());
352 NavigateToURL(shell(),
353 test_server()->GetURL("files/frame_tree/top.html"));
354 WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
355 FrameTreeNode* root = wc->GetFrameTree()->root();
356 ASSERT_EQ(3UL, root->child_count());
357 int frame_tree_node_id = root->child_at(0)->frame_tree_node_id();
358 EXPECT_NE(-1, frame_tree_node_id);
360 // Navigate with the subframe's FrameTreeNode ID.
361 const GURL url(test_server()->GetURL("files/title1.html"));
362 OpenURLParams params(url, Referrer(), frame_tree_node_id, CURRENT_TAB,
363 ui::PAGE_TRANSITION_LINK, true);
364 shell()->web_contents()->OpenURL(params);
366 // Make sure the NavigationEntry ends up with the FrameTreeNode ID.
367 NavigationController* controller = &shell()->web_contents()->GetController();
368 EXPECT_TRUE(controller->GetPendingEntry());
369 EXPECT_EQ(frame_tree_node_id,
370 NavigationEntryImpl::FromNavigationEntry(
371 controller->GetPendingEntry())->frame_tree_node_id());
374 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
375 AppendingFrameInWebUIDoesNotCrash) {
376 const GURL kWebUIUrl("chrome://tracing");
377 const char kJSCodeForAppendingFrame[] =
378 "document.body.appendChild(document.createElement('iframe'));";
380 NavigateToURL(shell(), kWebUIUrl);
382 bool js_executed = content::ExecuteScript(shell()->web_contents(),
383 kJSCodeForAppendingFrame);
384 EXPECT_TRUE(js_executed);
387 // Observer class to track the creation of RenderFrameHost objects. It is used
388 // in subsequent tests.
389 class RenderFrameCreatedObserver : public WebContentsObserver {
390 public:
391 RenderFrameCreatedObserver(Shell* shell)
392 : WebContentsObserver(shell->web_contents()),
393 last_rfh_(NULL) {
396 void RenderFrameCreated(RenderFrameHost* render_frame_host) override {
397 last_rfh_ = render_frame_host;
400 RenderFrameHost* last_rfh() const { return last_rfh_; }
402 private:
403 RenderFrameHost* last_rfh_;
405 DISALLOW_COPY_AND_ASSIGN(RenderFrameCreatedObserver);
408 // Test that creation of new RenderFrameHost objects sends the correct object
409 // to the WebContentObservers. See http://crbug.com/347339.
410 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
411 RenderFrameCreatedCorrectProcessForObservers) {
412 static const char kFooCom[] = "foo.com";
413 GURL::Replacements replace_host;
414 net::HostPortPair foo_host_port;
415 GURL cross_site_url;
417 // Setup the server to allow serving separate sites, so we can perform
418 // cross-process navigation.
419 host_resolver()->AddRule("*", "127.0.0.1");
420 ASSERT_TRUE(test_server()->Start());
422 foo_host_port = test_server()->host_port_pair();
423 foo_host_port.set_host(kFooCom);
425 GURL initial_url(test_server()->GetURL("/title1.html"));
427 cross_site_url = test_server()->GetURL("/title2.html");
428 replace_host.SetHostStr(kFooCom);
429 cross_site_url = cross_site_url.ReplaceComponents(replace_host);
431 // Navigate to the initial URL and capture the RenderFrameHost for later
432 // comparison.
433 NavigateToURL(shell(), initial_url);
434 RenderFrameHost* orig_rfh = shell()->web_contents()->GetMainFrame();
436 // Install the observer and navigate cross-site.
437 RenderFrameCreatedObserver observer(shell());
438 NavigateToURL(shell(), cross_site_url);
440 // The observer should've seen a RenderFrameCreated call for the new frame
441 // and not the old one.
442 EXPECT_NE(observer.last_rfh(), orig_rfh);
443 EXPECT_EQ(observer.last_rfh(), shell()->web_contents()->GetMainFrame());
446 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
447 LoadingStateChangedForSameDocumentNavigation) {
448 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
449 scoped_ptr<LoadingStateChangedDelegate> delegate(
450 new LoadingStateChangedDelegate());
451 shell()->web_contents()->SetDelegate(delegate.get());
453 LoadStopNotificationObserver load_observer(
454 &shell()->web_contents()->GetController());
455 TitleWatcher title_watcher(shell()->web_contents(),
456 base::ASCIIToUTF16("pushState"));
457 NavigateToURL(shell(), embedded_test_server()->GetURL("/push_state.html"));
458 load_observer.Wait();
459 base::string16 title = title_watcher.WaitAndGetTitle();
460 ASSERT_EQ(title, base::ASCIIToUTF16("pushState"));
462 // LoadingStateChanged should be called 4 times: start and stop for the
463 // initial load of push_state.html, and start and stop for the "navigation"
464 // triggered by history.pushState(). However, the start notification for the
465 // history.pushState() navigation should set to_different_document to false.
466 EXPECT_EQ("pushState", shell()->web_contents()->GetLastCommittedURL().ref());
467 EXPECT_EQ(4, delegate->loadingStateChangedCount());
468 EXPECT_EQ(3, delegate->loadingStateToDifferentDocumentCount());
471 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
472 RenderViewCreatedForChildWindow) {
473 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
475 NavigateToURL(shell(),
476 embedded_test_server()->GetURL("/title1.html"));
478 WebContentsAddedObserver new_web_contents_observer;
479 ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
480 "var a = document.createElement('a');"
481 "a.href='./title2.html';"
482 "a.target = '_blank';"
483 "document.body.appendChild(a);"
484 "a.click();"));
485 WebContents* new_web_contents = new_web_contents_observer.GetWebContents();
486 WaitForLoadStop(new_web_contents);
487 EXPECT_TRUE(new_web_contents_observer.RenderViewCreatedCalled());
490 struct LoadProgressDelegateAndObserver : public WebContentsDelegate,
491 public WebContentsObserver {
492 LoadProgressDelegateAndObserver(Shell* shell)
493 : WebContentsObserver(shell->web_contents()),
494 did_start_loading(false),
495 did_stop_loading(false) {
496 web_contents()->SetDelegate(this);
499 // WebContentsDelegate:
500 void LoadProgressChanged(WebContents* source, double progress) override {
501 EXPECT_TRUE(did_start_loading);
502 EXPECT_FALSE(did_stop_loading);
503 progresses.push_back(progress);
506 // WebContentsObserver:
507 void DidStartLoading() override {
508 EXPECT_FALSE(did_start_loading);
509 EXPECT_EQ(0U, progresses.size());
510 EXPECT_FALSE(did_stop_loading);
511 did_start_loading = true;
514 void DidStopLoading() override {
515 EXPECT_TRUE(did_start_loading);
516 EXPECT_GE(progresses.size(), 1U);
517 EXPECT_FALSE(did_stop_loading);
518 did_stop_loading = true;
521 bool did_start_loading;
522 std::vector<double> progresses;
523 bool did_stop_loading;
526 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, LoadProgress) {
527 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
528 scoped_ptr<LoadProgressDelegateAndObserver> delegate(
529 new LoadProgressDelegateAndObserver(shell()));
531 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
533 const std::vector<double>& progresses = delegate->progresses;
534 // All updates should be in order ...
535 if (std::adjacent_find(progresses.begin(),
536 progresses.end(),
537 std::greater<double>()) != progresses.end()) {
538 ADD_FAILURE() << "Progress values should be in order: "
539 << ::testing::PrintToString(progresses);
542 // ... and the last one should be 1.0, meaning complete.
543 ASSERT_GE(progresses.size(), 1U)
544 << "There should be at least one progress update";
545 EXPECT_EQ(1.0, *progresses.rbegin());
548 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, LoadProgressWithFrames) {
549 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
550 scoped_ptr<LoadProgressDelegateAndObserver> delegate(
551 new LoadProgressDelegateAndObserver(shell()));
553 NavigateToURL(shell(),
554 embedded_test_server()->GetURL("/frame_tree/top.html"));
556 const std::vector<double>& progresses = delegate->progresses;
557 // All updates should be in order ...
558 if (std::adjacent_find(progresses.begin(),
559 progresses.end(),
560 std::greater<double>()) != progresses.end()) {
561 ADD_FAILURE() << "Progress values should be in order: "
562 << ::testing::PrintToString(progresses);
565 // ... and the last one should be 1.0, meaning complete.
566 ASSERT_GE(progresses.size(), 1U)
567 << "There should be at least one progress update";
568 EXPECT_EQ(1.0, *progresses.rbegin());
571 // Ensure that a new navigation that interrupts a pending one will still fire
572 // a DidStopLoading. See http://crbug.com/429399.
573 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
574 LoadProgressAfterInterruptedNav) {
575 host_resolver()->AddRule("*", "127.0.0.1");
576 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
578 // Start at a real page.
579 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
581 // Simulate a navigation that has not completed.
582 scoped_ptr<LoadProgressDelegateAndObserver> delegate(
583 new LoadProgressDelegateAndObserver(shell()));
584 RenderFrameHost* main_frame = shell()->web_contents()->GetMainFrame();
585 FrameHostMsg_DidStartLoading start_msg(main_frame->GetRoutingID(), true);
586 static_cast<RenderFrameHostImpl*>(main_frame)->OnMessageReceived(start_msg);
587 EXPECT_TRUE(delegate->did_start_loading);
588 EXPECT_FALSE(delegate->did_stop_loading);
590 // Also simulate a DidChangeLoadProgress, but not a DidStopLoading.
591 FrameHostMsg_DidChangeLoadProgress progress_msg(main_frame->GetRoutingID(),
592 1.0);
593 static_cast<RenderFrameHostImpl*>(main_frame)->OnMessageReceived(
594 progress_msg);
595 EXPECT_TRUE(delegate->did_start_loading);
596 EXPECT_FALSE(delegate->did_stop_loading);
598 // Now interrupt with a new cross-process navigation.
599 TestNavigationObserver tab_observer(shell()->web_contents(), 1);
600 GURL url(embedded_test_server()->GetURL("foo.com", "/title2.html"));
601 shell()->LoadURL(url);
602 tab_observer.Wait();
603 EXPECT_EQ(url, shell()->web_contents()->GetLastCommittedURL());
605 // We should have gotten to DidStopLoading.
606 EXPECT_TRUE(delegate->did_stop_loading);
609 struct FirstVisuallyNonEmptyPaintObserver : public WebContentsObserver {
610 FirstVisuallyNonEmptyPaintObserver(Shell* shell)
611 : WebContentsObserver(shell->web_contents()),
612 did_fist_visually_non_empty_paint_(false) {}
614 void DidFirstVisuallyNonEmptyPaint() override {
615 did_fist_visually_non_empty_paint_ = true;
616 on_did_first_visually_non_empty_paint_.Run();
619 void WaitForDidFirstVisuallyNonEmptyPaint() {
620 if (did_fist_visually_non_empty_paint_)
621 return;
622 base::RunLoop run_loop;
623 on_did_first_visually_non_empty_paint_ = run_loop.QuitClosure();
624 run_loop.Run();
627 base::Closure on_did_first_visually_non_empty_paint_;
628 bool did_fist_visually_non_empty_paint_;
631 // See: http://crbug.com/395664
632 #if defined(OS_ANDROID)
633 #define MAYBE_FirstVisuallyNonEmptyPaint DISABLED_FirstVisuallyNonEmptyPaint
634 #else
635 // http://crbug.com/398471
636 #define MAYBE_FirstVisuallyNonEmptyPaint DISABLED_FirstVisuallyNonEmptyPaint
637 #endif
638 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
639 MAYBE_FirstVisuallyNonEmptyPaint) {
640 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
641 scoped_ptr<FirstVisuallyNonEmptyPaintObserver> observer(
642 new FirstVisuallyNonEmptyPaintObserver(shell()));
644 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
646 observer->WaitForDidFirstVisuallyNonEmptyPaint();
647 ASSERT_TRUE(observer->did_fist_visually_non_empty_paint_);
650 namespace {
652 class WebDisplayModeDelegate : public WebContentsDelegate {
653 public:
654 explicit WebDisplayModeDelegate(blink::WebDisplayMode mode) : mode_(mode) { }
655 ~WebDisplayModeDelegate() override { }
657 blink::WebDisplayMode GetDisplayMode(
658 const WebContents* source) const override { return mode_; }
659 void set_mode(blink::WebDisplayMode mode) { mode_ = mode; }
660 private:
661 blink::WebDisplayMode mode_;
663 DISALLOW_COPY_AND_ASSIGN(WebDisplayModeDelegate);
668 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ChangeDisplayMode) {
669 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
670 WebDisplayModeDelegate delegate(blink::WebDisplayModeMinimalUi);
671 shell()->web_contents()->SetDelegate(&delegate);
673 NavigateToURL(shell(), GURL("about://blank"));
675 ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
676 "document.title = "
677 " window.matchMedia('(display-mode:"
678 " minimal-ui)').matches"));
679 EXPECT_EQ(base::ASCIIToUTF16("true"), shell()->web_contents()->GetTitle());
681 delegate.set_mode(blink::WebDisplayModeFullscreen);
682 // Simulate widget is entering fullscreen (changing size is enough).
683 shell()->web_contents()->GetRenderViewHost()->WasResized();
685 ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
686 "document.title = "
687 " window.matchMedia('(display-mode:"
688 " fullscreen)').matches"));
689 EXPECT_EQ(base::ASCIIToUTF16("true"), shell()->web_contents()->GetTitle());
692 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NewNamedWindow) {
693 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
695 GURL url = embedded_test_server()->GetURL("/click-noreferrer-links.html");
696 EXPECT_TRUE(NavigateToURL(shell(), url));
699 ShellAddedObserver new_shell_observer;
701 // Open a new, named window.
702 EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
703 "window.open('about:blank','new_window');"));
705 Shell* new_shell = new_shell_observer.GetShell();
706 WaitForLoadStop(new_shell->web_contents());
708 EXPECT_EQ("new_window",
709 static_cast<WebContentsImpl*>(new_shell->web_contents())
710 ->GetFrameTree()->root()->frame_name());
712 bool success = false;
713 EXPECT_TRUE(ExecuteScriptAndExtractBool(
714 new_shell->web_contents(),
715 "window.domAutomationController.send(window.name == 'new_window');",
716 &success));
717 EXPECT_TRUE(success);
721 ShellAddedObserver new_shell_observer;
723 // Test clicking a target=foo link.
724 bool success = false;
725 EXPECT_TRUE(ExecuteScriptAndExtractBool(
726 shell()->web_contents(),
727 "window.domAutomationController.send(clickSameSiteTargetedLink());",
728 &success));
729 EXPECT_TRUE(success);
731 Shell* new_shell = new_shell_observer.GetShell();
732 WaitForLoadStop(new_shell->web_contents());
734 EXPECT_EQ("foo",
735 static_cast<WebContentsImpl*>(new_shell->web_contents())
736 ->GetFrameTree()->root()->frame_name());
740 } // namespace content