OLD | NEW |
| (Empty) |
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. | |
4 | |
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" | |
18 | |
19 namespace content { | |
20 | |
21 class CommitObserver : public RenderViewObserver { | |
22 public: | |
23 CommitObserver(RenderView* render_view, const base::Closure& quit_closure) | |
24 : RenderViewObserver(render_view), | |
25 quit_closure_(quit_closure), | |
26 commit_count_(0) {} | |
27 | |
28 void DidCommitCompositorFrame() override { | |
29 commit_count_++; | |
30 quit_closure_.Run(); | |
31 } | |
32 | |
33 int GetCommitCount() { return commit_count_; } | |
34 | |
35 private: | |
36 base::Closure quit_closure_; | |
37 int commit_count_; | |
38 }; | |
39 | |
40 class VisualStateTest : public ContentBrowserTest { | |
41 public: | |
42 VisualStateTest() : callback_count_(0) {} | |
43 | |
44 void SetUpCommandLine(base::CommandLine* command_line) override { | |
45 command_line->AppendSwitch(switches::kSingleProcess); | |
46 } | |
47 | |
48 void WaitForCommit(int routing_id) { | |
49 scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner; | |
50 CommitObserver observer(GetRenderView(routing_id), runner->QuitClosure()); | |
51 runner->Run(); | |
52 EXPECT_EQ(1, observer.GetCommitCount()); | |
53 } | |
54 | |
55 void AssertIsIdle() { | |
56 ASSERT_TRUE(base::MessageLoop::current()->IsIdleForTesting()); | |
57 } | |
58 | |
59 void InvokeVisualStateCallback(bool result) { | |
60 EXPECT_TRUE(result); | |
61 callback_count_++; | |
62 } | |
63 | |
64 int GetCallbackCount() { return callback_count_; } | |
65 | |
66 private: | |
67 RenderView* GetRenderView(int routing_id) { | |
68 return RenderView::FromRoutingID(routing_id); | |
69 } | |
70 | |
71 int callback_count_; | |
72 }; | |
73 | |
74 // This test verifies that visual state callbacks do not deadlock. In other | |
75 // words, the visual state callback should be received even if there are no | |
76 // pending updates or commits. | |
77 IN_PROC_BROWSER_TEST_F(VisualStateTest, CallbackDoesNotDeadlock) { | |
78 // This test relies on the fact that loading "about:blank" only requires a | |
79 // single commit. We first load "about:blank" and wait for this single | |
80 // commit. At that point we know that the page has stabilized and no | |
81 // further commits are expected. We then insert a visual state callback | |
82 // and verify that this causes an additional commit in order to deliver | |
83 // the callback. | |
84 // Unfortunately, if loading "about:blank" changes and starts requiring | |
85 // two commits then this test will prove nothing. We could detect this | |
86 // with a high level of confidence if we used a timeout, but that's | |
87 // discouraged (see https://codereview.chromium.org/939673002). | |
88 NavigateToURL(shell(), GURL("about:blank")); | |
89 | |
90 // Wait for the commit corresponding to the load. | |
91 PostTaskToInProcessRendererAndWait( | |
92 base::Bind(&VisualStateTest::WaitForCommit, base::Unretained(this), | |
93 shell()->web_contents()->GetRoutingID())); | |
94 | |
95 // Try our best to check that there are no pending updates or commits. | |
96 PostTaskToInProcessRendererAndWait( | |
97 base::Bind(&VisualStateTest::AssertIsIdle, base::Unretained(this))); | |
98 | |
99 // Insert a visual state callback. | |
100 shell()->web_contents()->GetMainFrame()->InsertVisualStateCallback(base::Bind( | |
101 &VisualStateTest::InvokeVisualStateCallback, base::Unretained(this))); | |
102 | |
103 // Verify that the callback is invoked and a new commit completed. | |
104 PostTaskToInProcessRendererAndWait( | |
105 base::Bind(&VisualStateTest::WaitForCommit, base::Unretained(this), | |
106 shell()->web_contents()->GetRoutingID())); | |
107 EXPECT_EQ(1, GetCallbackCount()); | |
108 } | |
109 | |
110 } // namespace content | |
OLD | NEW |