Update To 11.40.268.0
[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/strings/utf_string_conversions.h"
6 #include "base/values.h"
7 #include "content/browser/frame_host/navigation_entry_impl.h"
8 #include "content/browser/web_contents/web_contents_impl.h"
9 #include "content/browser/web_contents/web_contents_view.h"
10 #include "content/public/browser/load_notification_details.h"
11 #include "content/public/browser/navigation_controller.h"
12 #include "content/public/browser/notification_details.h"
13 #include "content/public/browser/notification_observer.h"
14 #include "content/public/browser/notification_types.h"
15 #include "content/public/browser/render_view_host.h"
16 #include "content/public/browser/render_widget_host_view.h"
17 #include "content/public/browser/web_contents_observer.h"
18 #include "content/public/common/content_paths.h"
19 #include "content/public/test/browser_test_utils.h"
20 #include "content/public/test/content_browser_test.h"
21 #include "content/public/test/content_browser_test_utils.h"
22 #include "content/public/test/test_utils.h"
23 #include "content/shell/browser/shell.h"
24 #include "net/dns/mock_host_resolver.h"
25 #include "net/test/embedded_test_server/embedded_test_server.h"
26
27 namespace content {
28
29 void ResizeWebContentsView(Shell* shell, const gfx::Size& size,
30                            bool set_start_page) {
31   // Shell::SizeTo is not implemented on Aura; WebContentsView::SizeContents
32   // works on Win and ChromeOS but not Linux - we need to resize the shell
33   // window on Linux because if we don't, the next layout of the unchanged shell
34   // window will resize WebContentsView back to the previous size.
35   // SizeContents is a hack and should not be relied on.
36 #if defined(OS_MACOSX)
37   shell->SizeTo(size);
38   // If |set_start_page| is true, start with blank page to make sure resize
39   // takes effect.
40   if (set_start_page)
41     NavigateToURL(shell, GURL("about://blank"));
42 #else
43   static_cast<WebContentsImpl*>(shell->web_contents())->GetView()->
44       SizeContents(size);
45 #endif  // defined(OS_MACOSX)
46 }
47
48 class WebContentsImplBrowserTest : public ContentBrowserTest {
49  public:
50   WebContentsImplBrowserTest() {}
51
52  private:
53   DISALLOW_COPY_AND_ASSIGN(WebContentsImplBrowserTest);
54 };
55
56 // Keeps track of data from LoadNotificationDetails so we can later verify that
57 // they are correct, after the LoadNotificationDetails object is deleted.
58 class LoadStopNotificationObserver : public WindowedNotificationObserver {
59  public:
60   LoadStopNotificationObserver(NavigationController* controller)
61       : WindowedNotificationObserver(NOTIFICATION_LOAD_STOP,
62                                      Source<NavigationController>(controller)),
63         session_index_(-1),
64         controller_(NULL) {
65   }
66   void Observe(int type,
67                const NotificationSource& source,
68                const NotificationDetails& details) override {
69     if (type == NOTIFICATION_LOAD_STOP) {
70       const Details<LoadNotificationDetails> load_details(details);
71       url_ = load_details->url;
72       session_index_ = load_details->session_index;
73       controller_ = load_details->controller;
74     }
75     WindowedNotificationObserver::Observe(type, source, details);
76   }
77
78   GURL url_;
79   int session_index_;
80   NavigationController* controller_;
81 };
82
83 // Starts a new navigation as soon as the current one commits, but does not
84 // wait for it to complete.  This allows us to observe DidStopLoading while
85 // a pending entry is present.
86 class NavigateOnCommitObserver : public WebContentsObserver {
87  public:
88   NavigateOnCommitObserver(Shell* shell, GURL url)
89       : WebContentsObserver(shell->web_contents()),
90         shell_(shell),
91         url_(url),
92         done_(false) {
93   }
94
95   // WebContentsObserver:
96   void NavigationEntryCommitted(
97       const LoadCommittedDetails& load_details) override {
98     if (!done_) {
99       done_ = true;
100       shell_->Stop();
101       shell_->LoadURL(url_);
102     }
103   }
104
105   Shell* shell_;
106   GURL url_;
107   bool done_;
108 };
109
110 class RenderViewSizeDelegate : public WebContentsDelegate {
111  public:
112   void set_size_insets(const gfx::Size& size_insets) {
113     size_insets_ = size_insets;
114   }
115
116   // WebContentsDelegate:
117   gfx::Size GetSizeForNewRenderView(WebContents* web_contents) const override {
118     gfx::Size size(web_contents->GetContainerBounds().size());
119     size.Enlarge(size_insets_.width(), size_insets_.height());
120     return size;
121   }
122
123  private:
124   gfx::Size size_insets_;
125 };
126
127 class RenderViewSizeObserver : public WebContentsObserver {
128  public:
129   RenderViewSizeObserver(Shell* shell, const gfx::Size& wcv_new_size)
130       : WebContentsObserver(shell->web_contents()),
131         shell_(shell),
132         wcv_new_size_(wcv_new_size) {
133   }
134
135   // WebContentsObserver:
136   void RenderViewCreated(RenderViewHost* rvh) override {
137     rwhv_create_size_ = rvh->GetView()->GetViewBounds().size();
138   }
139
140   void DidStartNavigationToPendingEntry(
141       const GURL& url,
142       NavigationController::ReloadType reload_type) override {
143     ResizeWebContentsView(shell_, wcv_new_size_, false);
144   }
145
146   gfx::Size rwhv_create_size() const { return rwhv_create_size_; }
147
148  private:
149   Shell* shell_;  // Weak ptr.
150   gfx::Size wcv_new_size_;
151   gfx::Size rwhv_create_size_;
152 };
153
154 class LoadingStateChangedDelegate : public WebContentsDelegate {
155  public:
156   LoadingStateChangedDelegate()
157       : loadingStateChangedCount_(0)
158       , loadingStateToDifferentDocumentCount_(0) {
159   }
160
161   // WebContentsDelegate:
162   void LoadingStateChanged(WebContents* contents,
163                            bool to_different_document) override {
164       loadingStateChangedCount_++;
165       if (to_different_document)
166         loadingStateToDifferentDocumentCount_++;
167   }
168
169   int loadingStateChangedCount() const { return loadingStateChangedCount_; }
170   int loadingStateToDifferentDocumentCount() const {
171     return loadingStateToDifferentDocumentCount_;
172   }
173
174  private:
175   int loadingStateChangedCount_;
176   int loadingStateToDifferentDocumentCount_;
177 };
178
179 // See: http://crbug.com/298193
180 #if defined(OS_WIN)
181 #define MAYBE_DidStopLoadingDetails DISABLED_DidStopLoadingDetails
182 #else
183 #define MAYBE_DidStopLoadingDetails DidStopLoadingDetails
184 #endif
185
186 // Test that DidStopLoading includes the correct URL in the details.
187 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
188                        MAYBE_DidStopLoadingDetails) {
189   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
190
191   LoadStopNotificationObserver load_observer(
192       &shell()->web_contents()->GetController());
193   NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
194   load_observer.Wait();
195
196   EXPECT_EQ("/title1.html", load_observer.url_.path());
197   EXPECT_EQ(0, load_observer.session_index_);
198   EXPECT_EQ(&shell()->web_contents()->GetController(),
199             load_observer.controller_);
200 }
201
202 // See: http://crbug.com/298193
203 #if defined(OS_WIN)
204 #define MAYBE_DidStopLoadingDetailsWithPending \
205   DISABLED_DidStopLoadingDetailsWithPending
206 #else
207 #define MAYBE_DidStopLoadingDetailsWithPending DidStopLoadingDetailsWithPending
208 #endif
209
210 // Test that DidStopLoading includes the correct URL in the details when a
211 // pending entry is present.
212 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
213                        MAYBE_DidStopLoadingDetailsWithPending) {
214   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
215   GURL url("data:text/html,<div>test</div>");
216
217   // Listen for the first load to stop.
218   LoadStopNotificationObserver load_observer(
219       &shell()->web_contents()->GetController());
220   // Start a new pending navigation as soon as the first load commits.
221   // We will hear a DidStopLoading from the first load as the new load
222   // is started.
223   NavigateOnCommitObserver commit_observer(
224       shell(), embedded_test_server()->GetURL("/title2.html"));
225   NavigateToURL(shell(), url);
226   load_observer.Wait();
227
228   EXPECT_EQ(url, load_observer.url_);
229   EXPECT_EQ(0, load_observer.session_index_);
230   EXPECT_EQ(&shell()->web_contents()->GetController(),
231             load_observer.controller_);
232 }
233 // Test that a renderer-initiated navigation to an invalid URL does not leave
234 // around a pending entry that could be used in a URL spoof.  We test this in
235 // a browser test because our unit test framework incorrectly calls
236 // DidStartProvisionalLoadForFrame for in-page navigations.
237 // See http://crbug.com/280512.
238 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
239                        ClearNonVisiblePendingOnFail) {
240   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
241
242   NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
243
244   // Navigate to an invalid URL and make sure it doesn't leave a pending entry.
245   LoadStopNotificationObserver load_observer1(
246       &shell()->web_contents()->GetController());
247   ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
248                             "window.location.href=\"nonexistent:12121\";"));
249   load_observer1.Wait();
250   EXPECT_FALSE(shell()->web_contents()->GetController().GetPendingEntry());
251
252   LoadStopNotificationObserver load_observer2(
253       &shell()->web_contents()->GetController());
254   ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
255                             "window.location.href=\"#foo\";"));
256   load_observer2.Wait();
257   EXPECT_EQ(embedded_test_server()->GetURL("/title1.html#foo"),
258             shell()->web_contents()->GetVisibleURL());
259 }
260
261 // Crashes under ThreadSanitizer, http://crbug.com/356758.
262 #if defined(OS_WIN) || defined(OS_ANDROID) \
263     || defined(THREAD_SANITIZER)
264 #define MAYBE_GetSizeForNewRenderView DISABLED_GetSizeForNewRenderView
265 #else
266 #define MAYBE_GetSizeForNewRenderView GetSizeForNewRenderView
267 #endif
268 // Test that RenderViewHost is created and updated at the size specified by
269 // WebContentsDelegate::GetSizeForNewRenderView().
270 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
271                        MAYBE_GetSizeForNewRenderView) {
272   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
273   // Create a new server with a different site.
274   net::SpawnedTestServer https_server(
275       net::SpawnedTestServer::TYPE_HTTPS,
276       net::SpawnedTestServer::kLocalhost,
277       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
278   ASSERT_TRUE(https_server.Start());
279
280   scoped_ptr<RenderViewSizeDelegate> delegate(new RenderViewSizeDelegate());
281   shell()->web_contents()->SetDelegate(delegate.get());
282   ASSERT_TRUE(shell()->web_contents()->GetDelegate() == delegate.get());
283
284   // When no size is set, RenderWidgetHostView adopts the size of
285   // WebContentsView.
286   NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html"));
287   EXPECT_EQ(shell()->web_contents()->GetContainerBounds().size(),
288             shell()->web_contents()->GetRenderWidgetHostView()->GetViewBounds().
289                 size());
290
291   // When a size is set, RenderWidgetHostView and WebContentsView honor this
292   // size.
293   gfx::Size size(300, 300);
294   gfx::Size size_insets(10, 15);
295   ResizeWebContentsView(shell(), size, true);
296   delegate->set_size_insets(size_insets);
297   NavigateToURL(shell(), https_server.GetURL("/"));
298   size.Enlarge(size_insets.width(), size_insets.height());
299   EXPECT_EQ(size,
300             shell()->web_contents()->GetRenderWidgetHostView()->GetViewBounds().
301                 size());
302   // The web_contents size is set by the embedder, and should not depend on the
303   // rwhv size. The behavior is correct on OSX, but incorrect on other
304   // platforms.
305   gfx::Size exp_wcv_size(300, 300);
306 #if !defined(OS_MACOSX)
307   exp_wcv_size.Enlarge(size_insets.width(), size_insets.height());
308 #endif
309
310   EXPECT_EQ(exp_wcv_size,
311             shell()->web_contents()->GetContainerBounds().size());
312
313   // If WebContentsView is resized after RenderWidgetHostView is created but
314   // before pending navigation entry is committed, both RenderWidgetHostView and
315   // WebContentsView use the new size of WebContentsView.
316   gfx::Size init_size(200, 200);
317   gfx::Size new_size(100, 100);
318   size_insets = gfx::Size(20, 30);
319   ResizeWebContentsView(shell(), init_size, true);
320   delegate->set_size_insets(size_insets);
321   RenderViewSizeObserver observer(shell(), new_size);
322   NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
323   // RenderWidgetHostView is created at specified size.
324   init_size.Enlarge(size_insets.width(), size_insets.height());
325   EXPECT_EQ(init_size, observer.rwhv_create_size());
326
327 // Once again, the behavior is correct on OSX. The embedder explicitly sets
328 // the size to (100,100) during navigation. Both the wcv and the rwhv should
329 // take on that size.
330 #if !defined(OS_MACOSX)
331   new_size.Enlarge(size_insets.width(), size_insets.height());
332 #endif
333   gfx::Size actual_size = shell()->web_contents()->GetRenderWidgetHostView()->
334       GetViewBounds().size();
335
336   EXPECT_EQ(new_size, actual_size);
337   EXPECT_EQ(new_size, shell()->web_contents()->GetContainerBounds().size());
338 }
339
340 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, OpenURLSubframe) {
341   // Navigate to a page with frames and grab a subframe's FrameTreeNode ID.
342   ASSERT_TRUE(test_server()->Start());
343   NavigateToURL(shell(),
344                 test_server()->GetURL("files/frame_tree/top.html"));
345   WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
346   FrameTreeNode* root = wc->GetFrameTree()->root();
347   ASSERT_EQ(3UL, root->child_count());
348   int64 frame_tree_node_id = root->child_at(0)->frame_tree_node_id();
349   EXPECT_NE(-1, frame_tree_node_id);
350
351   // Navigate with the subframe's FrameTreeNode ID.
352   const GURL url(test_server()->GetURL("files/title1.html"));
353   OpenURLParams params(url, Referrer(), frame_tree_node_id, CURRENT_TAB,
354                        ui::PAGE_TRANSITION_LINK, true);
355   shell()->web_contents()->OpenURL(params);
356
357   // Make sure the NavigationEntry ends up with the FrameTreeNode ID.
358   NavigationController* controller = &shell()->web_contents()->GetController();
359   EXPECT_TRUE(controller->GetPendingEntry());
360   EXPECT_EQ(frame_tree_node_id,
361             NavigationEntryImpl::FromNavigationEntry(
362                 controller->GetPendingEntry())->frame_tree_node_id());
363 }
364
365 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
366                        AppendingFrameInWebUIDoesNotCrash) {
367   const GURL kWebUIUrl("chrome://tracing");
368   const char kJSCodeForAppendingFrame[] =
369       "document.body.appendChild(document.createElement('iframe'));";
370
371   NavigateToURL(shell(), kWebUIUrl);
372
373   bool js_executed = content::ExecuteScript(shell()->web_contents(),
374                                             kJSCodeForAppendingFrame);
375   EXPECT_TRUE(js_executed);
376 }
377
378 // Observer class to track the creation of RenderFrameHost objects. It is used
379 // in subsequent tests.
380 class RenderFrameCreatedObserver : public WebContentsObserver {
381  public:
382   RenderFrameCreatedObserver(Shell* shell)
383       : WebContentsObserver(shell->web_contents()),
384         last_rfh_(NULL) {
385   }
386
387   void RenderFrameCreated(RenderFrameHost* render_frame_host) override {
388     last_rfh_ = render_frame_host;
389   }
390
391   RenderFrameHost* last_rfh() const { return last_rfh_; }
392
393  private:
394   RenderFrameHost* last_rfh_;
395
396   DISALLOW_COPY_AND_ASSIGN(RenderFrameCreatedObserver);
397 };
398
399 // Test that creation of new RenderFrameHost objects sends the correct object
400 // to the WebContentObservers. See http://crbug.com/347339.
401 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
402                        RenderFrameCreatedCorrectProcessForObservers) {
403   std::string foo_com("foo.com");
404   GURL::Replacements replace_host;
405   net::HostPortPair foo_host_port;
406   GURL cross_site_url;
407
408   // Setup the server to allow serving separate sites, so we can perform
409   // cross-process navigation.
410   host_resolver()->AddRule("*", "127.0.0.1");
411   ASSERT_TRUE(test_server()->Start());
412
413   foo_host_port = test_server()->host_port_pair();
414   foo_host_port.set_host(foo_com);
415
416   GURL initial_url(test_server()->GetURL("/title1.html"));
417
418   cross_site_url = test_server()->GetURL("/title2.html");
419   replace_host.SetHostStr(foo_com);
420   cross_site_url = cross_site_url.ReplaceComponents(replace_host);
421
422   // Navigate to the initial URL and capture the RenderFrameHost for later
423   // comparison.
424   NavigateToURL(shell(), initial_url);
425   RenderFrameHost* orig_rfh = shell()->web_contents()->GetMainFrame();
426
427   // Install the observer and navigate cross-site.
428   RenderFrameCreatedObserver observer(shell());
429   NavigateToURL(shell(), cross_site_url);
430
431   // The observer should've seen a RenderFrameCreated call for the new frame
432   // and not the old one.
433   EXPECT_NE(observer.last_rfh(), orig_rfh);
434   EXPECT_EQ(observer.last_rfh(), shell()->web_contents()->GetMainFrame());
435 }
436
437 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
438                        LoadingStateChangedForSameDocumentNavigation) {
439   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
440   scoped_ptr<LoadingStateChangedDelegate> delegate(
441       new LoadingStateChangedDelegate());
442   shell()->web_contents()->SetDelegate(delegate.get());
443
444   LoadStopNotificationObserver load_observer(
445       &shell()->web_contents()->GetController());
446   TitleWatcher title_watcher(shell()->web_contents(),
447                              base::ASCIIToUTF16("pushState"));
448   NavigateToURL(shell(), embedded_test_server()->GetURL("/push_state.html"));
449   load_observer.Wait();
450   base::string16 title = title_watcher.WaitAndGetTitle();
451   ASSERT_EQ(title, base::ASCIIToUTF16("pushState"));
452
453   // LoadingStateChanged should be called 4 times: start and stop for the
454   // initial load of push_state.html, and start and stop for the "navigation"
455   // triggered by history.pushState(). However, the start notification for the
456   // history.pushState() navigation should set to_different_document to false.
457   EXPECT_EQ("pushState", shell()->web_contents()->GetURL().ref());
458   EXPECT_EQ(4, delegate->loadingStateChangedCount());
459   EXPECT_EQ(3, delegate->loadingStateToDifferentDocumentCount());
460 }
461
462 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
463                        RenderViewCreatedForChildWindow) {
464   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
465
466   NavigateToURL(shell(),
467                 embedded_test_server()->GetURL("/title1.html"));
468
469   WebContentsAddedObserver new_web_contents_observer;
470   ASSERT_TRUE(ExecuteScript(shell()->web_contents(),
471                             "var a = document.createElement('a');"
472                             "a.href='./title2.html';"
473                             "a.target = '_blank';"
474                             "document.body.appendChild(a);"
475                             "a.click();"));
476   WebContents* new_web_contents = new_web_contents_observer.GetWebContents();
477   WaitForLoadStop(new_web_contents);
478   EXPECT_TRUE(new_web_contents_observer.RenderViewCreatedCalled());
479 }
480
481 struct LoadProgressDelegateAndObserver : public WebContentsDelegate,
482                                          public WebContentsObserver {
483   LoadProgressDelegateAndObserver(Shell* shell)
484       : WebContentsObserver(shell->web_contents()),
485         did_start_loading(false),
486         did_stop_loading(false) {
487     web_contents()->SetDelegate(this);
488   }
489
490   // WebContentsDelegate:
491   void LoadProgressChanged(WebContents* source, double progress) override {
492     EXPECT_TRUE(did_start_loading);
493     EXPECT_FALSE(did_stop_loading);
494     progresses.push_back(progress);
495   }
496
497   // WebContentsObserver:
498   void DidStartLoading(RenderViewHost* render_view_host) override {
499     EXPECT_FALSE(did_start_loading);
500     EXPECT_EQ(0U, progresses.size());
501     EXPECT_FALSE(did_stop_loading);
502     did_start_loading = true;
503   }
504
505   void DidStopLoading(RenderViewHost* render_view_host) override {
506     EXPECT_TRUE(did_start_loading);
507     EXPECT_GE(progresses.size(), 1U);
508     EXPECT_FALSE(did_stop_loading);
509     did_stop_loading = true;
510   }
511
512   bool did_start_loading;
513   std::vector<double> progresses;
514   bool did_stop_loading;
515 };
516
517 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, LoadProgress) {
518   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
519   scoped_ptr<LoadProgressDelegateAndObserver> delegate(
520       new LoadProgressDelegateAndObserver(shell()));
521
522   NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
523
524   const std::vector<double>& progresses = delegate->progresses;
525   // All updates should be in order ...
526   if (std::adjacent_find(progresses.begin(),
527                          progresses.end(),
528                          std::greater<double>()) != progresses.end()) {
529     ADD_FAILURE() << "Progress values should be in order: "
530                   << ::testing::PrintToString(progresses);
531   }
532
533   // ... and the last one should be 1.0, meaning complete.
534   ASSERT_GE(progresses.size(), 1U)
535       << "There should be at least one progress update";
536   EXPECT_EQ(1.0, *progresses.rbegin());
537 }
538
539 struct FirstVisuallyNonEmptyPaintObserver : public WebContentsObserver {
540   FirstVisuallyNonEmptyPaintObserver(Shell* shell)
541       : WebContentsObserver(shell->web_contents()),
542         did_fist_visually_non_empty_paint_(false) {}
543
544   void DidFirstVisuallyNonEmptyPaint() override {
545     did_fist_visually_non_empty_paint_ = true;
546     on_did_first_visually_non_empty_paint_.Run();
547   }
548
549   void WaitForDidFirstVisuallyNonEmptyPaint() {
550     if (did_fist_visually_non_empty_paint_)
551       return;
552     base::RunLoop run_loop;
553     on_did_first_visually_non_empty_paint_ = run_loop.QuitClosure();
554     run_loop.Run();
555   }
556
557   base::Closure on_did_first_visually_non_empty_paint_;
558   bool did_fist_visually_non_empty_paint_;
559 };
560
561 // See: http://crbug.com/395664
562 #if defined(OS_ANDROID)
563 #define MAYBE_FirstVisuallyNonEmptyPaint DISABLED_FirstVisuallyNonEmptyPaint
564 #else
565 // http://crbug.com/398471
566 #define MAYBE_FirstVisuallyNonEmptyPaint DISABLED_FirstVisuallyNonEmptyPaint
567 #endif
568 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
569                        MAYBE_FirstVisuallyNonEmptyPaint) {
570   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
571   scoped_ptr<FirstVisuallyNonEmptyPaintObserver> observer(
572       new FirstVisuallyNonEmptyPaintObserver(shell()));
573
574   NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
575
576   observer->WaitForDidFirstVisuallyNonEmptyPaint();
577   ASSERT_TRUE(observer->did_fist_visually_non_empty_paint_);
578 }
579
580 }  // namespace content
581