1 // Copyright 2015 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/command_line.h"
6 #include "base/run_loop.h"
7 #include "content/public/browser/render_frame_host.h"
8 #include "content/public/browser/web_contents.h"
9 #include "content/public/common/content_switches.h"
10 #include "content/public/renderer/render_view.h"
11 #include "content/public/renderer/render_view_observer.h"
12 #include "content/public/test/browser_test_utils.h"
13 #include "content/public/test/content_browser_test.h"
14 #include "content/public/test/content_browser_test_utils.h"
15 #include "content/public/test/test_utils.h"
16 #include "content/renderer/render_frame_impl.h"
17 #include "content/shell/browser/shell.h"
21 class CommitObserver
: public RenderViewObserver
{
23 CommitObserver(RenderView
* render_view
)
24 : RenderViewObserver(render_view
), quit_closures_(), commit_count_(0) {}
26 void DidCommitCompositorFrame() override
{
28 for (base::Closure
* closure
: quit_closures_
) {
33 void QuitAfterCommit(int commit_number
,
34 scoped_refptr
<MessageLoopRunner
> runner
) {
35 if (commit_number
>= commit_count_
) runner
->Quit();
38 void WaitForCommitNumber(int commit_number
) {
39 if (commit_number
> commit_count_
) {
40 scoped_refptr
<MessageLoopRunner
> runner
= new MessageLoopRunner
;
41 base::Closure quit_closure
=
42 base::Bind(&CommitObserver::QuitAfterCommit
, base::Unretained(this),
43 commit_number
, runner
);
44 quit_closures_
.insert(&quit_closure
);
46 quit_closures_
.erase(&quit_closure
);
50 int GetCommitCount() { return commit_count_
; }
53 std::set
<base::Closure
*> quit_closures_
;
57 class VisualStateTest
: public ContentBrowserTest
{
59 VisualStateTest() : callback_count_(0) {}
61 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
62 command_line
->AppendSwitch(switches::kSingleProcess
);
65 void WaitForCommit(CommitObserver
*observer
, int commit_number
) {
66 observer
->WaitForCommitNumber(commit_number
);
67 EXPECT_EQ(commit_number
, observer
->GetCommitCount());
71 ASSERT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
74 void InvokeVisualStateCallback(bool result
) {
79 int GetCallbackCount() { return callback_count_
; }
85 // This test verifies that visual state callbacks do not deadlock. In other
86 // words, the visual state callback should be received even if there are no
87 // pending updates or commits.
88 // Disabled due to cross-platform flakes; http://crbug.com/462580.
89 IN_PROC_BROWSER_TEST_F(VisualStateTest
, DISABLED_CallbackDoesNotDeadlock
) {
90 // This test relies on the fact that loading "about:blank" only requires a
91 // single commit. We first load "about:blank" and wait for this single
92 // commit. At that point we know that the page has stabilized and no
93 // further commits are expected. We then insert a visual state callback
94 // and verify that this causes an additional commit in order to deliver
96 // Unfortunately, if loading "about:blank" changes and starts requiring
97 // two commits then this test will prove nothing. We could detect this
98 // with a high level of confidence if we used a timeout, but that's
99 // discouraged (see https://codereview.chromium.org/939673002).
100 NavigateToURL(shell(), GURL("about:blank"));
101 CommitObserver
observer(
102 RenderView::FromRoutingID(shell()->web_contents()->GetRoutingID()));
104 // Wait for the commit corresponding to the load.
106 PostTaskToInProcessRendererAndWait(base::Bind(
107 &VisualStateTest::WaitForCommit
, base::Unretained(this), &observer
, 1));
109 // Try our best to check that there are no pending updates or commits.
110 PostTaskToInProcessRendererAndWait(
111 base::Bind(&VisualStateTest::AssertIsIdle
, base::Unretained(this)));
113 // Insert a visual state callback.
114 shell()->web_contents()->GetMainFrame()->InsertVisualStateCallback(base::Bind(
115 &VisualStateTest::InvokeVisualStateCallback
, base::Unretained(this)));
117 // Verify that the callback is invoked and a new commit completed.
118 PostTaskToInProcessRendererAndWait(base::Bind(
119 &VisualStateTest::WaitForCommit
, base::Unretained(this), &observer
, 2));
120 EXPECT_EQ(1, GetCallbackCount());
123 } // namespace content