| 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 |