Make USB permissions work in the new permission message system
[chromium-blink-merge.git] / content / browser / web_contents / web_contents_impl_browsertest.cc
blobaa00317d4d4973eb3836480a1ff3d18ebefc563b
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/common/url_constants.h"
22 #include "content/public/test/browser_test_utils.h"
23 #include "content/public/test/content_browser_test.h"
24 #include "content/public/test/content_browser_test_utils.h"
25 #include "content/public/test/test_navigation_observer.h"
26 #include "content/public/test/test_utils.h"
27 #include "content/shell/browser/shell.h"
28 #include "net/dns/mock_host_resolver.h"
29 #include "net/test/embedded_test_server/embedded_test_server.h"
31 namespace content {
33 void ResizeWebContentsView(Shell* shell, const gfx::Size& size,
34 bool set_start_page) {
35 // Shell::SizeTo is not implemented on Aura; WebContentsView::SizeContents
36 // works on Win and ChromeOS but not Linux - we need to resize the shell
37 // window on Linux because if we don't, the next layout of the unchanged shell
38 // window will resize WebContentsView back to the previous size.
39 // SizeContents is a hack and should not be relied on.
40 #if defined(OS_MACOSX)
41 shell->SizeTo(size);
42 // If |set_start_page| is true, start with blank page to make sure resize
43 // takes effect.
44 if (set_start_page)
45 NavigateToURL(shell, GURL("about://blank"));
46 #else
47 static_cast<WebContentsImpl*>(shell->web_contents())->GetView()->
48 SizeContents(size);
49 #endif // defined(OS_MACOSX)
52 class WebContentsImplBrowserTest : public ContentBrowserTest {
53 public:
54 WebContentsImplBrowserTest() {}
55 void SetUp() override {
56 RenderWidgetHostImpl::DisableResizeAckCheckForTesting();
57 ContentBrowserTest::SetUp();
60 private:
61 DISALLOW_COPY_AND_ASSIGN(WebContentsImplBrowserTest);
64 // Keeps track of data from LoadNotificationDetails so we can later verify that
65 // they are correct, after the LoadNotificationDetails object is deleted.
66 class LoadStopNotificationObserver : public WindowedNotificationObserver {
67 public:
68 LoadStopNotificationObserver(NavigationController* controller)
69 : WindowedNotificationObserver(NOTIFICATION_LOAD_STOP,
70 Source<NavigationController>(controller)),
71 session_index_(-1),
72 controller_(NULL) {
74 void Observe(int type,
75 const NotificationSource& source,
76 const NotificationDetails& details) override {
77 if (type == NOTIFICATION_LOAD_STOP) {
78 const Details<LoadNotificationDetails> load_details(details);
79 url_ = load_details->url;
80 session_index_ = load_details->session_index;
81 controller_ = load_details->controller;
83 WindowedNotificationObserver::Observe(type, source, details);
86 GURL url_;
87 int session_index_;
88 NavigationController* controller_;
91 // Starts a new navigation as soon as the current one commits, but does not
92 // wait for it to complete. This allows us to observe DidStopLoading while
93 // a pending entry is present.
94 class NavigateOnCommitObserver : public WebContentsObserver {
95 public:
96 NavigateOnCommitObserver(Shell* shell, GURL url)
97 : WebContentsObserver(shell->web_contents()),
98 shell_(shell),
99 url_(url),
100 done_(false) {
103 // WebContentsObserver:
104 void NavigationEntryCommitted(
105 const LoadCommittedDetails& load_details) override {
106 if (!done_) {
107 done_ = true;
108 shell_->Stop();
109 shell_->LoadURL(url_);
113 Shell* shell_;
114 GURL url_;
115 bool done_;
118 class RenderViewSizeDelegate : public WebContentsDelegate {
119 public:
120 void set_size_insets(const gfx::Size& size_insets) {
121 size_insets_ = size_insets;
124 // WebContentsDelegate:
125 gfx::Size GetSizeForNewRenderView(WebContents* web_contents) const override {
126 gfx::Size size(web_contents->GetContainerBounds().size());
127 size.Enlarge(size_insets_.width(), size_insets_.height());
128 return size;
131 private:
132 gfx::Size size_insets_;
135 class RenderViewSizeObserver : public WebContentsObserver {
136 public:
137 RenderViewSizeObserver(Shell* shell, const gfx::Size& wcv_new_size)
138 : WebContentsObserver(shell->web_contents()),
139 shell_(shell),
140 wcv_new_size_(wcv_new_size) {
143 // WebContentsObserver:
144 void RenderViewCreated(RenderViewHost* rvh) override {
145 rwhv_create_size_ = rvh->GetView()->GetViewBounds().size();
148 void DidStartProvisionalLoadForFrame(
149 RenderFrameHost* render_frame_host,
150 const GURL& url,
151 bool is_error_page,
152 bool is_iframe_srcdoc) override {
153 ResizeWebContentsView(shell_, wcv_new_size_, false);
156 gfx::Size rwhv_create_size() const { return rwhv_create_size_; }
158 private:
159 Shell* shell_; // Weak ptr.
160 gfx::Size wcv_new_size_;
161 gfx::Size rwhv_create_size_;
164 class LoadingStateChangedDelegate : public WebContentsDelegate {
165 public:
166 LoadingStateChangedDelegate()
167 : loadingStateChangedCount_(0)
168 , loadingStateToDifferentDocumentCount_(0) {
171 // WebContentsDelegate:
172 void LoadingStateChanged(WebContents* contents,
173 bool to_different_document) override {
174 loadingStateChangedCount_++;
175 if (to_different_document)
176 loadingStateToDifferentDocumentCount_++;
179 int loadingStateChangedCount() const { return loadingStateChangedCount_; }
180 int loadingStateToDifferentDocumentCount() const {
181 return loadingStateToDifferentDocumentCount_;
184 private:
185 int loadingStateChangedCount_;
186 int loadingStateToDifferentDocumentCount_;
189 // See: http://crbug.com/298193
190 #if defined(OS_WIN) || defined(OS_LINUX)
191 #define MAYBE_DidStopLoadingDetails DISABLED_DidStopLoadingDetails
192 #else
193 #define MAYBE_DidStopLoadingDetails DidStopLoadingDetails
194 #endif
196 // Test that DidStopLoading includes the correct URL in the details.
197 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
198 MAYBE_DidStopLoadingDetails) {
199 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
201 LoadStopNotificationObserver load_observer(
202 &shell()->web_contents()->GetController());
203 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
204 load_observer.Wait();
206 EXPECT_EQ("/title1.html", load_observer.url_.path());
207 EXPECT_EQ(0, load_observer.session_index_);
208 EXPECT_EQ(&shell()->web_contents()->GetController(),
209 load_observer.controller_);
212 // See: http://crbug.com/298193
213 #if defined(OS_WIN) || defined(OS_LINUX)
214 #define MAYBE_DidStopLoadingDetailsWithPending \
215 DISABLED_DidStopLoadingDetailsWithPending
216 #else
217 #define MAYBE_DidStopLoadingDetailsWithPending DidStopLoadingDetailsWithPending
218 #endif
220 // Test that DidStopLoading includes the correct URL in the details when a
221 // pending entry is present.
222 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
223 MAYBE_DidStopLoadingDetailsWithPending) {
224 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
225 GURL url("data:text/html,<div>test</div>");
227 // Listen for the first load to stop.
228 LoadStopNotificationObserver load_observer(
229 &shell()->web_contents()->GetController());
230 // Start a new pending navigation as soon as the first load commits.
231 // We will hear a DidStopLoading from the first load as the new load
232 // is started.
233 NavigateOnCommitObserver commit_observer(
234 shell(), embedded_test_server()->GetURL("/title2.html"));
235 NavigateToURL(shell(), url);
236 load_observer.Wait();
238 EXPECT_EQ(url, load_observer.url_);
239 EXPECT_EQ(0, load_observer.session_index_);
240 EXPECT_EQ(&shell()->web_contents()->GetController(),
241 load_observer.controller_);
243 // Test that a renderer-initiated navigation to an invalid URL does not leave
244 // around a pending entry that could be used in a URL spoof. We test this in
245 // a browser test because our unit test framework incorrectly calls
246 // DidStartProvisionalLoadForFrame for in-page navigations.
247 // See http://crbug.com/280512.
248 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
249 ClearNonVisiblePendingOnFail) {
250 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
252 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
254 // Navigate to an invalid URL and make sure it doesn't leave a pending entry.
255 LoadStopNotificationObserver load_observer1(
256 &shell()->web_contents()->GetController());
257 ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
258 "window.location.href=\"nonexistent:12121\";"));
259 load_observer1.Wait();
260 EXPECT_FALSE(shell()->web_contents()->GetController().GetPendingEntry());
262 LoadStopNotificationObserver load_observer2(
263 &shell()->web_contents()->GetController());
264 ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
265 "window.location.href=\"#foo\";"));
266 load_observer2.Wait();
267 EXPECT_EQ(embedded_test_server()->GetURL("/title1.html#foo"),
268 shell()->web_contents()->GetVisibleURL());
271 // Crashes under ThreadSanitizer, http://crbug.com/356758.
272 #if defined(OS_WIN) || defined(OS_ANDROID) \
273 || defined(THREAD_SANITIZER)
274 #define MAYBE_GetSizeForNewRenderView DISABLED_GetSizeForNewRenderView
275 #else
276 #define MAYBE_GetSizeForNewRenderView GetSizeForNewRenderView
277 #endif
278 // Test that RenderViewHost is created and updated at the size specified by
279 // WebContentsDelegate::GetSizeForNewRenderView().
280 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
281 MAYBE_GetSizeForNewRenderView) {
282 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
283 // Create a new server with a different site.
284 net::SpawnedTestServer https_server(
285 net::SpawnedTestServer::TYPE_HTTPS,
286 net::SpawnedTestServer::kLocalhost,
287 base::FilePath(FILE_PATH_LITERAL("content/test/data")));
288 ASSERT_TRUE(https_server.Start());
290 scoped_ptr<RenderViewSizeDelegate> delegate(new RenderViewSizeDelegate());
291 shell()->web_contents()->SetDelegate(delegate.get());
292 ASSERT_TRUE(shell()->web_contents()->GetDelegate() == delegate.get());
294 // When no size is set, RenderWidgetHostView adopts the size of
295 // WebContentsView.
296 NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html"));
297 EXPECT_EQ(shell()->web_contents()->GetContainerBounds().size(),
298 shell()->web_contents()->GetRenderWidgetHostView()->GetViewBounds().
299 size());
301 // When a size is set, RenderWidgetHostView and WebContentsView honor this
302 // size.
303 gfx::Size size(300, 300);
304 gfx::Size size_insets(10, 15);
305 ResizeWebContentsView(shell(), size, true);
306 delegate->set_size_insets(size_insets);
307 NavigateToURL(shell(), https_server.GetURL("/"));
308 size.Enlarge(size_insets.width(), size_insets.height());
309 EXPECT_EQ(size,
310 shell()->web_contents()->GetRenderWidgetHostView()->GetViewBounds().
311 size());
312 // The web_contents size is set by the embedder, and should not depend on the
313 // rwhv size. The behavior is correct on OSX, but incorrect on other
314 // platforms.
315 gfx::Size exp_wcv_size(300, 300);
316 #if !defined(OS_MACOSX)
317 exp_wcv_size.Enlarge(size_insets.width(), size_insets.height());
318 #endif
320 EXPECT_EQ(exp_wcv_size,
321 shell()->web_contents()->GetContainerBounds().size());
323 // If WebContentsView is resized after RenderWidgetHostView is created but
324 // before pending navigation entry is committed, both RenderWidgetHostView and
325 // WebContentsView use the new size of WebContentsView.
326 gfx::Size init_size(200, 200);
327 gfx::Size new_size(100, 100);
328 size_insets = gfx::Size(20, 30);
329 ResizeWebContentsView(shell(), init_size, true);
330 delegate->set_size_insets(size_insets);
331 RenderViewSizeObserver observer(shell(), new_size);
332 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
333 // RenderWidgetHostView is created at specified size.
334 init_size.Enlarge(size_insets.width(), size_insets.height());
335 EXPECT_EQ(init_size, observer.rwhv_create_size());
337 // Once again, the behavior is correct on OSX. The embedder explicitly sets
338 // the size to (100,100) during navigation. Both the wcv and the rwhv should
339 // take on that size.
340 #if !defined(OS_MACOSX)
341 new_size.Enlarge(size_insets.width(), size_insets.height());
342 #endif
343 gfx::Size actual_size = shell()->web_contents()->GetRenderWidgetHostView()->
344 GetViewBounds().size();
346 EXPECT_EQ(new_size, actual_size);
347 EXPECT_EQ(new_size, shell()->web_contents()->GetContainerBounds().size());
350 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, SetTitleOnUnload) {
351 GURL url(
352 "data:text/html,"
353 "<title>A</title>"
354 "<body onunload=\"document.title = 'B'\"></body>");
355 NavigateToURL(shell(), url);
356 ASSERT_EQ(1, shell()->web_contents()->GetController().GetEntryCount());
357 NavigationEntryImpl* entry1 = NavigationEntryImpl::FromNavigationEntry(
358 shell()->web_contents()->GetController().GetLastCommittedEntry());
359 SiteInstance* site_instance1 = entry1->site_instance();
360 EXPECT_EQ(base::ASCIIToUTF16("A"), entry1->GetTitle());
362 // Force a process switch by going to a privileged page.
363 GURL web_ui_page(std::string(kChromeUIScheme) + "://" +
364 std::string(kChromeUIGpuHost));
365 NavigateToURL(shell(), web_ui_page);
366 NavigationEntryImpl* entry2 = NavigationEntryImpl::FromNavigationEntry(
367 shell()->web_contents()->GetController().GetLastCommittedEntry());
368 SiteInstance* site_instance2 = entry2->site_instance();
369 EXPECT_NE(site_instance1, site_instance2);
371 EXPECT_EQ(2, shell()->web_contents()->GetController().GetEntryCount());
372 EXPECT_EQ(base::ASCIIToUTF16("B"), entry1->GetTitle());
375 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, OpenURLSubframe) {
376 // Navigate to a page with frames and grab a subframe's FrameTreeNode ID.
377 ASSERT_TRUE(test_server()->Start());
378 NavigateToURL(shell(),
379 test_server()->GetURL("files/frame_tree/top.html"));
380 WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
381 FrameTreeNode* root = wc->GetFrameTree()->root();
382 ASSERT_EQ(3UL, root->child_count());
383 int frame_tree_node_id = root->child_at(0)->frame_tree_node_id();
384 EXPECT_NE(-1, frame_tree_node_id);
386 // Navigate with the subframe's FrameTreeNode ID.
387 const GURL url(test_server()->GetURL("files/title1.html"));
388 OpenURLParams params(url, Referrer(), frame_tree_node_id, CURRENT_TAB,
389 ui::PAGE_TRANSITION_LINK, true);
390 shell()->web_contents()->OpenURL(params);
392 // Make sure the NavigationEntry ends up with the FrameTreeNode ID.
393 NavigationController* controller = &shell()->web_contents()->GetController();
394 EXPECT_TRUE(controller->GetPendingEntry());
395 EXPECT_EQ(frame_tree_node_id,
396 NavigationEntryImpl::FromNavigationEntry(
397 controller->GetPendingEntry())->frame_tree_node_id());
400 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
401 AppendingFrameInWebUIDoesNotCrash) {
402 const GURL kWebUIUrl("chrome://tracing");
403 const char kJSCodeForAppendingFrame[] =
404 "document.body.appendChild(document.createElement('iframe'));";
406 NavigateToURL(shell(), kWebUIUrl);
408 bool js_executed = content::ExecuteScript(shell()->web_contents(),
409 kJSCodeForAppendingFrame);
410 EXPECT_TRUE(js_executed);
413 // Observer class to track the creation of RenderFrameHost objects. It is used
414 // in subsequent tests.
415 class RenderFrameCreatedObserver : public WebContentsObserver {
416 public:
417 RenderFrameCreatedObserver(Shell* shell)
418 : WebContentsObserver(shell->web_contents()),
419 last_rfh_(NULL) {
422 void RenderFrameCreated(RenderFrameHost* render_frame_host) override {
423 last_rfh_ = render_frame_host;
426 RenderFrameHost* last_rfh() const { return last_rfh_; }
428 private:
429 RenderFrameHost* last_rfh_;
431 DISALLOW_COPY_AND_ASSIGN(RenderFrameCreatedObserver);
434 // Test that creation of new RenderFrameHost objects sends the correct object
435 // to the WebContentObservers. See http://crbug.com/347339.
436 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
437 RenderFrameCreatedCorrectProcessForObservers) {
438 static const char kFooCom[] = "foo.com";
439 GURL::Replacements replace_host;
440 net::HostPortPair foo_host_port;
441 GURL cross_site_url;
443 // Setup the server to allow serving separate sites, so we can perform
444 // cross-process navigation.
445 host_resolver()->AddRule("*", "127.0.0.1");
446 ASSERT_TRUE(test_server()->Start());
448 foo_host_port = test_server()->host_port_pair();
449 foo_host_port.set_host(kFooCom);
451 GURL initial_url(test_server()->GetURL("/title1.html"));
453 cross_site_url = test_server()->GetURL("/title2.html");
454 replace_host.SetHostStr(kFooCom);
455 cross_site_url = cross_site_url.ReplaceComponents(replace_host);
457 // Navigate to the initial URL and capture the RenderFrameHost for later
458 // comparison.
459 NavigateToURL(shell(), initial_url);
460 RenderFrameHost* orig_rfh = shell()->web_contents()->GetMainFrame();
462 // Install the observer and navigate cross-site.
463 RenderFrameCreatedObserver observer(shell());
464 NavigateToURL(shell(), cross_site_url);
466 // The observer should've seen a RenderFrameCreated call for the new frame
467 // and not the old one.
468 EXPECT_NE(observer.last_rfh(), orig_rfh);
469 EXPECT_EQ(observer.last_rfh(), shell()->web_contents()->GetMainFrame());
472 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
473 LoadingStateChangedForSameDocumentNavigation) {
474 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
475 scoped_ptr<LoadingStateChangedDelegate> delegate(
476 new LoadingStateChangedDelegate());
477 shell()->web_contents()->SetDelegate(delegate.get());
479 LoadStopNotificationObserver load_observer(
480 &shell()->web_contents()->GetController());
481 TitleWatcher title_watcher(shell()->web_contents(),
482 base::ASCIIToUTF16("pushState"));
483 NavigateToURL(shell(), embedded_test_server()->GetURL("/push_state.html"));
484 load_observer.Wait();
485 base::string16 title = title_watcher.WaitAndGetTitle();
486 ASSERT_EQ(title, base::ASCIIToUTF16("pushState"));
488 // LoadingStateChanged should be called 4 times: start and stop for the
489 // initial load of push_state.html, and start and stop for the "navigation"
490 // triggered by history.pushState(). However, the start notification for the
491 // history.pushState() navigation should set to_different_document to false.
492 EXPECT_EQ("pushState", shell()->web_contents()->GetLastCommittedURL().ref());
493 EXPECT_EQ(4, delegate->loadingStateChangedCount());
494 EXPECT_EQ(3, delegate->loadingStateToDifferentDocumentCount());
497 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
498 RenderViewCreatedForChildWindow) {
499 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
501 NavigateToURL(shell(),
502 embedded_test_server()->GetURL("/title1.html"));
504 WebContentsAddedObserver new_web_contents_observer;
505 ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
506 "var a = document.createElement('a');"
507 "a.href='./title2.html';"
508 "a.target = '_blank';"
509 "document.body.appendChild(a);"
510 "a.click();"));
511 WebContents* new_web_contents = new_web_contents_observer.GetWebContents();
512 WaitForLoadStop(new_web_contents);
513 EXPECT_TRUE(new_web_contents_observer.RenderViewCreatedCalled());
516 struct LoadProgressDelegateAndObserver : public WebContentsDelegate,
517 public WebContentsObserver {
518 LoadProgressDelegateAndObserver(Shell* shell)
519 : WebContentsObserver(shell->web_contents()),
520 did_start_loading(false),
521 did_stop_loading(false) {
522 web_contents()->SetDelegate(this);
525 // WebContentsDelegate:
526 void LoadProgressChanged(WebContents* source, double progress) override {
527 EXPECT_TRUE(did_start_loading);
528 EXPECT_FALSE(did_stop_loading);
529 progresses.push_back(progress);
532 // WebContentsObserver:
533 void DidStartLoading() override {
534 EXPECT_FALSE(did_start_loading);
535 EXPECT_EQ(0U, progresses.size());
536 EXPECT_FALSE(did_stop_loading);
537 did_start_loading = true;
540 void DidStopLoading() override {
541 EXPECT_TRUE(did_start_loading);
542 EXPECT_GE(progresses.size(), 1U);
543 EXPECT_FALSE(did_stop_loading);
544 did_stop_loading = true;
547 bool did_start_loading;
548 std::vector<double> progresses;
549 bool did_stop_loading;
552 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, LoadProgress) {
553 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
554 scoped_ptr<LoadProgressDelegateAndObserver> delegate(
555 new LoadProgressDelegateAndObserver(shell()));
557 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
559 const std::vector<double>& progresses = delegate->progresses;
560 // All updates should be in order ...
561 if (std::adjacent_find(progresses.begin(),
562 progresses.end(),
563 std::greater<double>()) != progresses.end()) {
564 ADD_FAILURE() << "Progress values should be in order: "
565 << ::testing::PrintToString(progresses);
568 // ... and the last one should be 1.0, meaning complete.
569 ASSERT_GE(progresses.size(), 1U)
570 << "There should be at least one progress update";
571 EXPECT_EQ(1.0, *progresses.rbegin());
574 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, LoadProgressWithFrames) {
575 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
576 scoped_ptr<LoadProgressDelegateAndObserver> delegate(
577 new LoadProgressDelegateAndObserver(shell()));
579 NavigateToURL(shell(),
580 embedded_test_server()->GetURL("/frame_tree/top.html"));
582 const std::vector<double>& progresses = delegate->progresses;
583 // All updates should be in order ...
584 if (std::adjacent_find(progresses.begin(),
585 progresses.end(),
586 std::greater<double>()) != progresses.end()) {
587 ADD_FAILURE() << "Progress values should be in order: "
588 << ::testing::PrintToString(progresses);
591 // ... and the last one should be 1.0, meaning complete.
592 ASSERT_GE(progresses.size(), 1U)
593 << "There should be at least one progress update";
594 EXPECT_EQ(1.0, *progresses.rbegin());
597 // Ensure that a new navigation that interrupts a pending one will still fire
598 // a DidStopLoading. See http://crbug.com/429399.
599 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
600 LoadProgressAfterInterruptedNav) {
601 host_resolver()->AddRule("*", "127.0.0.1");
602 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
604 // Start at a real page.
605 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
607 // Simulate a navigation that has not completed.
608 scoped_ptr<LoadProgressDelegateAndObserver> delegate(
609 new LoadProgressDelegateAndObserver(shell()));
610 RenderFrameHost* main_frame = shell()->web_contents()->GetMainFrame();
611 FrameHostMsg_DidStartLoading start_msg(main_frame->GetRoutingID(), true);
612 static_cast<RenderFrameHostImpl*>(main_frame)->OnMessageReceived(start_msg);
613 EXPECT_TRUE(delegate->did_start_loading);
614 EXPECT_FALSE(delegate->did_stop_loading);
616 // Also simulate a DidChangeLoadProgress, but not a DidStopLoading.
617 FrameHostMsg_DidChangeLoadProgress progress_msg(main_frame->GetRoutingID(),
618 1.0);
619 static_cast<RenderFrameHostImpl*>(main_frame)->OnMessageReceived(
620 progress_msg);
621 EXPECT_TRUE(delegate->did_start_loading);
622 EXPECT_FALSE(delegate->did_stop_loading);
624 // Now interrupt with a new cross-process navigation.
625 TestNavigationObserver tab_observer(shell()->web_contents(), 1);
626 GURL url(embedded_test_server()->GetURL("foo.com", "/title2.html"));
627 shell()->LoadURL(url);
628 tab_observer.Wait();
629 EXPECT_EQ(url, shell()->web_contents()->GetLastCommittedURL());
631 // We should have gotten to DidStopLoading.
632 EXPECT_TRUE(delegate->did_stop_loading);
635 struct FirstVisuallyNonEmptyPaintObserver : public WebContentsObserver {
636 FirstVisuallyNonEmptyPaintObserver(Shell* shell)
637 : WebContentsObserver(shell->web_contents()),
638 did_fist_visually_non_empty_paint_(false) {}
640 void DidFirstVisuallyNonEmptyPaint() override {
641 did_fist_visually_non_empty_paint_ = true;
642 on_did_first_visually_non_empty_paint_.Run();
645 void WaitForDidFirstVisuallyNonEmptyPaint() {
646 if (did_fist_visually_non_empty_paint_)
647 return;
648 base::RunLoop run_loop;
649 on_did_first_visually_non_empty_paint_ = run_loop.QuitClosure();
650 run_loop.Run();
653 base::Closure on_did_first_visually_non_empty_paint_;
654 bool did_fist_visually_non_empty_paint_;
657 // See: http://crbug.com/395664
658 #if defined(OS_ANDROID)
659 #define MAYBE_FirstVisuallyNonEmptyPaint DISABLED_FirstVisuallyNonEmptyPaint
660 #else
661 // http://crbug.com/398471
662 #define MAYBE_FirstVisuallyNonEmptyPaint DISABLED_FirstVisuallyNonEmptyPaint
663 #endif
664 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
665 MAYBE_FirstVisuallyNonEmptyPaint) {
666 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
667 scoped_ptr<FirstVisuallyNonEmptyPaintObserver> observer(
668 new FirstVisuallyNonEmptyPaintObserver(shell()));
670 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
672 observer->WaitForDidFirstVisuallyNonEmptyPaint();
673 ASSERT_TRUE(observer->did_fist_visually_non_empty_paint_);
676 namespace {
678 class WebDisplayModeDelegate : public WebContentsDelegate {
679 public:
680 explicit WebDisplayModeDelegate(blink::WebDisplayMode mode) : mode_(mode) { }
681 ~WebDisplayModeDelegate() override { }
683 blink::WebDisplayMode GetDisplayMode(
684 const WebContents* source) const override { return mode_; }
685 void set_mode(blink::WebDisplayMode mode) { mode_ = mode; }
686 private:
687 blink::WebDisplayMode mode_;
689 DISALLOW_COPY_AND_ASSIGN(WebDisplayModeDelegate);
694 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ChangeDisplayMode) {
695 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
696 WebDisplayModeDelegate delegate(blink::WebDisplayModeMinimalUi);
697 shell()->web_contents()->SetDelegate(&delegate);
699 NavigateToURL(shell(), GURL("about://blank"));
701 ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
702 "document.title = "
703 " window.matchMedia('(display-mode:"
704 " minimal-ui)').matches"));
705 EXPECT_EQ(base::ASCIIToUTF16("true"), shell()->web_contents()->GetTitle());
707 delegate.set_mode(blink::WebDisplayModeFullscreen);
708 // Simulate widget is entering fullscreen (changing size is enough).
709 shell()->web_contents()->GetRenderViewHost()->WasResized();
711 ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
712 "document.title = "
713 " window.matchMedia('(display-mode:"
714 " fullscreen)').matches"));
715 EXPECT_EQ(base::ASCIIToUTF16("true"), shell()->web_contents()->GetTitle());
718 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NewNamedWindow) {
719 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
721 GURL url = embedded_test_server()->GetURL("/click-noreferrer-links.html");
722 EXPECT_TRUE(NavigateToURL(shell(), url));
725 ShellAddedObserver new_shell_observer;
727 // Open a new, named window.
728 EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
729 "window.open('about:blank','new_window');"));
731 Shell* new_shell = new_shell_observer.GetShell();
732 WaitForLoadStop(new_shell->web_contents());
734 EXPECT_EQ("new_window",
735 static_cast<WebContentsImpl*>(new_shell->web_contents())
736 ->GetFrameTree()->root()->frame_name());
738 bool success = false;
739 EXPECT_TRUE(ExecuteScriptAndExtractBool(
740 new_shell->web_contents(),
741 "window.domAutomationController.send(window.name == 'new_window');",
742 &success));
743 EXPECT_TRUE(success);
747 ShellAddedObserver new_shell_observer;
749 // Test clicking a target=foo link.
750 bool success = false;
751 EXPECT_TRUE(ExecuteScriptAndExtractBool(
752 shell()->web_contents(),
753 "window.domAutomationController.send(clickSameSiteTargetedLink());",
754 &success));
755 EXPECT_TRUE(success);
757 Shell* new_shell = new_shell_observer.GetShell();
758 WaitForLoadStop(new_shell->web_contents());
760 EXPECT_EQ("foo",
761 static_cast<WebContentsImpl*>(new_shell->web_contents())
762 ->GetFrameTree()->root()->frame_name());
766 } // namespace content