blob: 3ad17d1b81e32e6b72c69a9b386d515f834fcd4a [file] [log] [blame]
tobiasjs609b99f82015-02-27 10:45:521// 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.
4
Sebastien Marchandf8cbfab2019-01-25 16:02:305#include "base/bind.h"
tobiasjs609b99f82015-02-27 10:45:526#include "base/command_line.h"
Gabriel Charettea6b93642018-04-24 22:01:347#include "base/message_loop/message_loop_current.h"
tobiasjs609b99f82015-02-27 10:45:528#include "base/run_loop.h"
9#include "content/public/browser/render_frame_host.h"
davidsac996be112016-11-30 08:56:3810#include "content/public/browser/render_view_host.h"
tobiasjs609b99f82015-02-27 10:45:5211#include "content/public/browser/web_contents.h"
12#include "content/public/common/content_switches.h"
13#include "content/public/renderer/render_view.h"
14#include "content/public/renderer/render_view_observer.h"
15#include "content/public/test/browser_test_utils.h"
16#include "content/public/test/content_browser_test.h"
17#include "content/public/test/content_browser_test_utils.h"
18#include "content/public/test/test_utils.h"
19#include "content/renderer/render_frame_impl.h"
20#include "content/shell/browser/shell.h"
21
22namespace content {
23
24class CommitObserver : public RenderViewObserver {
25 public:
26 CommitObserver(RenderView* render_view)
27 : RenderViewObserver(render_view), quit_closures_(), commit_count_(0) {}
28
29 void DidCommitCompositorFrame() override {
30 commit_count_++;
31 for (base::Closure* closure : quit_closures_) {
32 closure->Run();
33 }
34 }
35
36 void QuitAfterCommit(int commit_number,
37 scoped_refptr<MessageLoopRunner> runner) {
38 if (commit_number >= commit_count_) runner->Quit();
39 }
40
41 void WaitForCommitNumber(int commit_number) {
42 if (commit_number > commit_count_) {
43 scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
44 base::Closure quit_closure =
45 base::Bind(&CommitObserver::QuitAfterCommit, base::Unretained(this),
46 commit_number, runner);
47 quit_closures_.insert(&quit_closure);
48 runner->Run();
49 quit_closures_.erase(&quit_closure);
50 }
51 }
52
53 int GetCommitCount() { return commit_count_; }
54
55 private:
xjz694b50a92016-06-07 21:49:3756 // RenderViewObserver implementation.
57 void OnDestruct() override { delete this; }
58
tobiasjs609b99f82015-02-27 10:45:5259 std::set<base::Closure*> quit_closures_;
60 int commit_count_;
61};
62
63class VisualStateTest : public ContentBrowserTest {
64 public:
65 VisualStateTest() : callback_count_(0) {}
66
67 void SetUpCommandLine(base::CommandLine* command_line) override {
68 command_line->AppendSwitch(switches::kSingleProcess);
69 }
70
71 void WaitForCommit(CommitObserver *observer, int commit_number) {
72 observer->WaitForCommitNumber(commit_number);
73 EXPECT_EQ(commit_number, observer->GetCommitCount());
74 }
75
76 void AssertIsIdle() {
Gabriel Charettea6b93642018-04-24 22:01:3477 ASSERT_TRUE(base::MessageLoopCurrent::Get()->IsIdleForTesting());
tobiasjs609b99f82015-02-27 10:45:5278 }
79
80 void InvokeVisualStateCallback(bool result) {
81 EXPECT_TRUE(result);
82 callback_count_++;
83 }
84
85 int GetCallbackCount() { return callback_count_; }
86
87 private:
88 int callback_count_;
89};
90
91// This test verifies that visual state callbacks do not deadlock. In other
92// words, the visual state callback should be received even if there are no
93// pending updates or commits.
grt9e383ca2015-02-27 15:36:0694// Disabled due to cross-platform flakes; http://crbug.com/462580.
95IN_PROC_BROWSER_TEST_F(VisualStateTest, DISABLED_CallbackDoesNotDeadlock) {
tobiasjs609b99f82015-02-27 10:45:5296 // This test relies on the fact that loading "about:blank" only requires a
97 // single commit. We first load "about:blank" and wait for this single
98 // commit. At that point we know that the page has stabilized and no
99 // further commits are expected. We then insert a visual state callback
100 // and verify that this causes an additional commit in order to deliver
101 // the callback.
102 // Unfortunately, if loading "about:blank" changes and starts requiring
103 // two commits then this test will prove nothing. We could detect this
104 // with a high level of confidence if we used a timeout, but that's
105 // discouraged (see https://codereview.chromium.org/939673002).
106 NavigateToURL(shell(), GURL("about:blank"));
davidsac996be112016-11-30 08:56:38107 CommitObserver observer(RenderView::FromRoutingID(
108 shell()->web_contents()->GetRenderViewHost()->GetRoutingID()));
tobiasjs609b99f82015-02-27 10:45:52109
110 // Wait for the commit corresponding to the load.
111
112 PostTaskToInProcessRendererAndWait(base::Bind(
113 &VisualStateTest::WaitForCommit, base::Unretained(this), &observer, 1));
114
115 // Try our best to check that there are no pending updates or commits.
116 PostTaskToInProcessRendererAndWait(
117 base::Bind(&VisualStateTest::AssertIsIdle, base::Unretained(this)));
118
119 // Insert a visual state callback.
tzik2ce14ce2018-07-26 05:17:18120 shell()->web_contents()->GetMainFrame()->InsertVisualStateCallback(
121 base::BindOnce(&VisualStateTest::InvokeVisualStateCallback,
122 base::Unretained(this)));
tobiasjs609b99f82015-02-27 10:45:52123
124 // Verify that the callback is invoked and a new commit completed.
125 PostTaskToInProcessRendererAndWait(base::Bind(
126 &VisualStateTest::WaitForCommit, base::Unretained(this), &observer, 2));
127 EXPECT_EQ(1, GetCallbackCount());
128}
129
130} // namespace content