Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / renderer / visual_state_browsertest.cc
blob26d9a6ddd26cb6ae254ec6db14fc406ed8db4fdc
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"
19 namespace content {
21 class CommitObserver : public RenderViewObserver {
22 public:
23 CommitObserver(RenderView* render_view)
24 : RenderViewObserver(render_view), quit_closures_(), commit_count_(0) {}
26 void DidCommitCompositorFrame() override {
27 commit_count_++;
28 for (base::Closure* closure : quit_closures_) {
29 closure->Run();
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);
45 runner->Run();
46 quit_closures_.erase(&quit_closure);
50 int GetCommitCount() { return commit_count_; }
52 private:
53 std::set<base::Closure*> quit_closures_;
54 int commit_count_;
57 class VisualStateTest : public ContentBrowserTest {
58 public:
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());
70 void AssertIsIdle() {
71 ASSERT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
74 void InvokeVisualStateCallback(bool result) {
75 EXPECT_TRUE(result);
76 callback_count_++;
79 int GetCallbackCount() { return callback_count_; }
81 private:
82 int 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
95 // the callback.
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