OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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/bind.h" | |
6 #include "base/utf_string_conversions.h" | |
7 #include "chrome/browser/speech/speech_input_bubble_controller.h" | |
8 #include "chrome/browser/ui/browser.h" | |
9 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | |
10 #include "chrome/test/base/browser_with_test_window_test.h" | |
11 #include "chrome/test/base/testing_profile.h" | |
12 #include "content/test/test_browser_thread.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 #include "ui/gfx/rect.h" | |
15 | |
16 using content::BrowserThread; | |
17 using content::WebContents; | |
18 | |
19 class SkBitmap; | |
20 | |
21 namespace speech_input { | |
22 | |
23 // A mock bubble class which fakes a focus change or recognition cancel by the | |
24 // user and closing of the info bubble. | |
25 class MockSpeechInputBubble : public SpeechInputBubbleBase { | |
26 public: | |
27 enum BubbleType { | |
28 BUBBLE_TEST_FOCUS_CHANGED, | |
29 BUBBLE_TEST_CLICK_CANCEL, | |
30 BUBBLE_TEST_CLICK_TRY_AGAIN, | |
31 }; | |
32 | |
33 MockSpeechInputBubble(WebContents* web_contents, | |
34 Delegate* delegate, | |
35 const gfx::Rect&) | |
36 : SpeechInputBubbleBase(web_contents) { | |
37 VLOG(1) << "MockSpeechInputBubble created"; | |
38 MessageLoop::current()->PostTask( | |
39 FROM_HERE, base::Bind(&InvokeDelegate, delegate)); | |
40 } | |
41 | |
42 static void InvokeDelegate(Delegate* delegate) { | |
43 VLOG(1) << "MockSpeechInputBubble invoking delegate for type " << type_; | |
44 switch (type_) { | |
45 case BUBBLE_TEST_FOCUS_CHANGED: | |
46 delegate->InfoBubbleFocusChanged(); | |
47 break; | |
48 case BUBBLE_TEST_CLICK_CANCEL: | |
49 delegate->InfoBubbleButtonClicked(SpeechInputBubble::BUTTON_CANCEL); | |
50 break; | |
51 case BUBBLE_TEST_CLICK_TRY_AGAIN: | |
52 delegate->InfoBubbleButtonClicked(SpeechInputBubble::BUTTON_TRY_AGAIN); | |
53 break; | |
54 } | |
55 } | |
56 | |
57 static void set_type(BubbleType type) { | |
58 type_ = type; | |
59 } | |
60 static BubbleType type() { | |
61 return type_; | |
62 } | |
63 | |
64 virtual void Show() {} | |
65 virtual void Hide() {} | |
66 virtual void UpdateLayout() {} | |
67 virtual void UpdateImage() {} | |
68 | |
69 private: | |
70 static BubbleType type_; | |
71 }; | |
72 | |
73 // The test fixture. | |
74 class SpeechInputBubbleControllerTest | |
75 : public SpeechInputBubbleControllerDelegate, | |
76 public BrowserWithTestWindowTest { | |
77 public: | |
78 SpeechInputBubbleControllerTest() | |
79 : BrowserWithTestWindowTest(), | |
80 io_thread_(BrowserThread::IO), // constructs a new thread and loop | |
81 cancel_clicked_(false), | |
82 try_again_clicked_(false), | |
83 focus_changed_(false), | |
84 controller_(ALLOW_THIS_IN_INITIALIZER_LIST( | |
85 new SpeechInputBubbleController(this))) { | |
86 EXPECT_EQ(NULL, test_fixture_); | |
87 test_fixture_ = this; | |
88 } | |
89 | |
90 ~SpeechInputBubbleControllerTest() { | |
91 test_fixture_ = NULL; | |
92 } | |
93 | |
94 // SpeechInputBubbleControllerDelegate methods. | |
95 virtual void InfoBubbleButtonClicked(int caller_id, | |
96 SpeechInputBubble::Button button) { | |
97 VLOG(1) << "Received InfoBubbleButtonClicked for button " << button; | |
98 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
99 if (button == SpeechInputBubble::BUTTON_CANCEL) { | |
100 cancel_clicked_ = true; | |
101 } else if (button == SpeechInputBubble::BUTTON_TRY_AGAIN) { | |
102 try_again_clicked_ = true; | |
103 } | |
104 message_loop()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | |
105 } | |
106 | |
107 virtual void InfoBubbleFocusChanged(int caller_id) { | |
108 VLOG(1) << "Received InfoBubbleFocusChanged"; | |
109 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
110 focus_changed_ = true; | |
111 message_loop()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | |
112 } | |
113 | |
114 // testing::Test methods. | |
115 virtual void SetUp() { | |
116 BrowserWithTestWindowTest::SetUp(); | |
117 SpeechInputBubble::set_factory( | |
118 &SpeechInputBubbleControllerTest::CreateBubble); | |
119 io_thread_.Start(); | |
120 } | |
121 | |
122 virtual void TearDown() { | |
123 SpeechInputBubble::set_factory(NULL); | |
124 io_thread_.Stop(); | |
125 BrowserWithTestWindowTest::TearDown(); | |
126 } | |
127 | |
128 static void ActivateBubble() { | |
129 if (MockSpeechInputBubble::type() == | |
130 MockSpeechInputBubble::BUBBLE_TEST_FOCUS_CHANGED) { | |
131 test_fixture_->controller_->SetBubbleWarmUpMode(kBubbleCallerId); | |
132 } else { | |
133 test_fixture_->controller_->SetBubbleMessage(kBubbleCallerId, | |
134 ASCIIToUTF16("Test")); | |
135 } | |
136 } | |
137 | |
138 static SpeechInputBubble* CreateBubble(WebContents* web_contents, | |
139 SpeechInputBubble::Delegate* delegate, | |
140 const gfx::Rect& element_rect) { | |
141 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
142 // Set up to activate the bubble soon after it gets created, since we test | |
143 // events sent by the bubble and those are handled only when the bubble is | |
144 // active. | |
145 MessageLoop::current()->PostTask(FROM_HERE, | |
146 base::Bind(&ActivateBubble)); | |
147 | |
148 // The |tab_contents| parameter would be NULL since the dummy caller id | |
149 // passed to CreateBubble would not have matched any active tab. So get a | |
150 // real WebContents pointer from the test fixture and pass that, because | |
151 // the bubble controller registers for tab close notifications which need | |
152 // a valid WebContents. | |
153 TabContentsWrapper* wrapper = | |
154 test_fixture_->browser()->GetSelectedTabContentsWrapper(); | |
155 if (wrapper) | |
156 web_contents = wrapper->web_contents(); | |
157 return new MockSpeechInputBubble(web_contents, delegate, element_rect); | |
158 } | |
159 | |
160 protected: | |
161 // The main thread of the test is marked as the IO thread and we create a new | |
162 // one for the UI thread. | |
163 content::TestBrowserThread io_thread_; | |
164 bool cancel_clicked_; | |
165 bool try_again_clicked_; | |
166 bool focus_changed_; | |
167 scoped_refptr<SpeechInputBubbleController> controller_; | |
168 | |
169 static const int kBubbleCallerId; | |
170 static SpeechInputBubbleControllerTest* test_fixture_; | |
171 }; | |
172 | |
173 SpeechInputBubbleControllerTest* | |
174 SpeechInputBubbleControllerTest::test_fixture_ = NULL; | |
175 | |
176 const int SpeechInputBubbleControllerTest::kBubbleCallerId = 1; | |
177 | |
178 MockSpeechInputBubble::BubbleType MockSpeechInputBubble::type_ = | |
179 MockSpeechInputBubble::BUBBLE_TEST_FOCUS_CHANGED; | |
180 | |
181 // Test that the speech bubble UI gets created in the UI thread and that the | |
182 // focus changed callback comes back in the IO thread. | |
183 TEST_F(SpeechInputBubbleControllerTest, TestFocusChanged) { | |
184 MockSpeechInputBubble::set_type( | |
185 MockSpeechInputBubble::BUBBLE_TEST_FOCUS_CHANGED); | |
186 | |
187 controller_->CreateBubble(kBubbleCallerId, 1, 1, gfx::Rect(1, 1)); | |
188 MessageLoop::current()->Run(); | |
189 EXPECT_TRUE(focus_changed_); | |
190 EXPECT_FALSE(cancel_clicked_); | |
191 EXPECT_FALSE(try_again_clicked_); | |
192 controller_->CloseBubble(kBubbleCallerId); | |
193 } | |
194 | |
195 // Test that the speech bubble UI gets created in the UI thread and that the | |
196 // recognition cancelled callback comes back in the IO thread. | |
197 TEST_F(SpeechInputBubbleControllerTest, TestRecognitionCancelled) { | |
198 MockSpeechInputBubble::set_type( | |
199 MockSpeechInputBubble::BUBBLE_TEST_CLICK_CANCEL); | |
200 | |
201 controller_->CreateBubble(kBubbleCallerId, 1, 1, gfx::Rect(1, 1)); | |
202 MessageLoop::current()->Run(); | |
203 EXPECT_TRUE(cancel_clicked_); | |
204 EXPECT_FALSE(try_again_clicked_); | |
205 EXPECT_FALSE(focus_changed_); | |
206 controller_->CloseBubble(kBubbleCallerId); | |
207 } | |
208 | |
209 // Test that the speech bubble UI gets created in the UI thread and that the | |
210 // try-again button click event comes back in the IO thread. | |
211 TEST_F(SpeechInputBubbleControllerTest, TestTryAgainClicked) { | |
212 MockSpeechInputBubble::set_type( | |
213 MockSpeechInputBubble::BUBBLE_TEST_CLICK_TRY_AGAIN); | |
214 | |
215 controller_->CreateBubble(kBubbleCallerId, 1, 1, gfx::Rect(1, 1)); | |
216 MessageLoop::current()->Run(); | |
217 EXPECT_FALSE(cancel_clicked_); | |
218 EXPECT_TRUE(try_again_clicked_); | |
219 EXPECT_FALSE(focus_changed_); | |
220 controller_->CloseBubble(kBubbleCallerId); | |
221 } | |
222 | |
223 } // namespace speech_input | |
OLD | NEW |