| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/command_line.h" | 6 #include "base/command_line.h" |
| 7 #include "base/file_path.h" | 7 #include "base/file_path.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/string_number_conversions.h" | 10 #include "base/string_number_conversions.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #include "content/public/common/content_switches.h" | 21 #include "content/public/common/content_switches.h" |
| 22 #include "content/public/common/speech_recognition_error.h" | 22 #include "content/public/common/speech_recognition_error.h" |
| 23 #include "content/public/common/speech_recognition_result.h" | 23 #include "content/public/common/speech_recognition_result.h" |
| 24 #include "content/public/common/url_constants.h" | 24 #include "content/public/common/url_constants.h" |
| 25 #include "content/public/test/test_utils.h" | 25 #include "content/public/test/test_utils.h" |
| 26 #include "content/shell/shell.h" | 26 #include "content/shell/shell.h" |
| 27 #include "content/test/content_browser_test.h" | 27 #include "content/test/content_browser_test.h" |
| 28 #include "content/test/content_browser_test_utils.h" | 28 #include "content/test/content_browser_test_utils.h" |
| 29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" | 29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" |
| 30 | 30 |
| 31 using content::NavigationController; | 31 namespace content { |
| 32 using content::SpeechRecognitionEventListener; | |
| 33 using content::SpeechRecognitionSessionConfig; | |
| 34 using content::SpeechRecognitionSessionContext; | |
| 35 using content::WebContents; | |
| 36 | |
| 37 namespace speech { | |
| 38 class FakeSpeechRecognitionManager; | |
| 39 } | |
| 40 | |
| 41 namespace speech { | |
| 42 | 32 |
| 43 const char kTestResult[] = "Pictures of the moon"; | 33 const char kTestResult[] = "Pictures of the moon"; |
| 44 | 34 |
| 45 class FakeSpeechRecognitionManager : public content::SpeechRecognitionManager { | 35 class FakeSpeechRecognitionManager : public SpeechRecognitionManager { |
| 46 public: | 36 public: |
| 47 FakeSpeechRecognitionManager() | 37 FakeSpeechRecognitionManager() |
| 48 : session_id_(0), | 38 : session_id_(0), |
| 49 listener_(NULL), | 39 listener_(NULL), |
| 50 did_cancel_all_(false), | 40 did_cancel_all_(false), |
| 51 should_send_fake_response_(true), | 41 should_send_fake_response_(true), |
| 52 recognition_started_event_(false, false) { | 42 recognition_started_event_(false, false) { |
| 53 } | 43 } |
| 54 | 44 |
| 55 std::string grammar() { | 45 std::string grammar() { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 67 bool should_send_fake_response() { | 57 bool should_send_fake_response() { |
| 68 return should_send_fake_response_; | 58 return should_send_fake_response_; |
| 69 } | 59 } |
| 70 | 60 |
| 71 base::WaitableEvent& recognition_started_event() { | 61 base::WaitableEvent& recognition_started_event() { |
| 72 return recognition_started_event_; | 62 return recognition_started_event_; |
| 73 } | 63 } |
| 74 | 64 |
| 75 // SpeechRecognitionManager methods. | 65 // SpeechRecognitionManager methods. |
| 76 virtual int CreateSession( | 66 virtual int CreateSession( |
| 77 const content::SpeechRecognitionSessionConfig& config) OVERRIDE { | 67 const SpeechRecognitionSessionConfig& config) OVERRIDE { |
| 78 VLOG(1) << "FAKE CreateSession invoked."; | 68 VLOG(1) << "FAKE CreateSession invoked."; |
| 79 EXPECT_EQ(0, session_id_); | 69 EXPECT_EQ(0, session_id_); |
| 80 EXPECT_EQ(NULL, listener_); | 70 EXPECT_EQ(NULL, listener_); |
| 81 listener_ = config.event_listener; | 71 listener_ = config.event_listener; |
| 82 if (config.grammars.size() > 0) | 72 if (config.grammars.size() > 0) |
| 83 grammar_ = config.grammars[0].url; | 73 grammar_ = config.grammars[0].url; |
| 84 session_ctx_ = config.initial_context; | 74 session_ctx_ = config.initial_context; |
| 85 session_config_ = config; | 75 session_config_ = config; |
| 86 session_id_ = 1; | 76 session_id_ = 1; |
| 87 return session_id_; | 77 return session_id_; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 113 listener_ = NULL; | 103 listener_ = NULL; |
| 114 } | 104 } |
| 115 | 105 |
| 116 virtual void StopAudioCaptureForSession(int session_id) OVERRIDE { | 106 virtual void StopAudioCaptureForSession(int session_id) OVERRIDE { |
| 117 VLOG(1) << "StopRecording invoked."; | 107 VLOG(1) << "StopRecording invoked."; |
| 118 EXPECT_EQ(session_id_, session_id); | 108 EXPECT_EQ(session_id_, session_id); |
| 119 // Nothing to do here since we aren't really recording. | 109 // Nothing to do here since we aren't really recording. |
| 120 } | 110 } |
| 121 | 111 |
| 122 virtual void AbortAllSessionsForListener( | 112 virtual void AbortAllSessionsForListener( |
| 123 content::SpeechRecognitionEventListener* listener) OVERRIDE { | 113 SpeechRecognitionEventListener* listener) OVERRIDE { |
| 124 VLOG(1) << "CancelAllRequestsWithDelegate invoked."; | 114 VLOG(1) << "CancelAllRequestsWithDelegate invoked."; |
| 125 // listener_ is set to NULL if a fake result was received (see below), so | 115 // listener_ is set to NULL if a fake result was received (see below), so |
| 126 // check that listener_ matches the incoming parameter only when there is | 116 // check that listener_ matches the incoming parameter only when there is |
| 127 // no fake result sent. | 117 // no fake result sent. |
| 128 EXPECT_TRUE(should_send_fake_response_ || listener_ == listener); | 118 EXPECT_TRUE(should_send_fake_response_ || listener_ == listener); |
| 129 did_cancel_all_ = true; | 119 did_cancel_all_ = true; |
| 130 } | 120 } |
| 131 | 121 |
| 132 virtual void AbortAllSessionsForRenderView(int render_process_id, | 122 virtual void AbortAllSessionsForRenderView(int render_process_id, |
| 133 int render_view_id) OVERRIDE { | 123 int render_view_id) OVERRIDE { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 145 session_ctx_.render_view_id == render_view_id && | 135 session_ctx_.render_view_id == render_view_id && |
| 146 session_ctx_.request_id == request_id; | 136 session_ctx_.request_id == request_id; |
| 147 } | 137 } |
| 148 | 138 |
| 149 virtual const SpeechRecognitionSessionConfig& GetSessionConfig( | 139 virtual const SpeechRecognitionSessionConfig& GetSessionConfig( |
| 150 int session_id) const OVERRIDE { | 140 int session_id) const OVERRIDE { |
| 151 EXPECT_EQ(session_id, session_id_); | 141 EXPECT_EQ(session_id, session_id_); |
| 152 return session_config_; | 142 return session_config_; |
| 153 } | 143 } |
| 154 | 144 |
| 155 virtual content::SpeechRecognitionSessionContext GetSessionContext( | 145 virtual SpeechRecognitionSessionContext GetSessionContext( |
| 156 int session_id) const OVERRIDE { | 146 int session_id) const OVERRIDE { |
| 157 EXPECT_EQ(session_id, session_id_); | 147 EXPECT_EQ(session_id, session_id_); |
| 158 return session_ctx_; | 148 return session_ctx_; |
| 159 } | 149 } |
| 160 | 150 |
| 161 private: | 151 private: |
| 162 void SetFakeRecognitionResult() { | 152 void SetFakeRecognitionResult() { |
| 163 if (session_id_) { // Do a check in case we were cancelled.. | 153 if (session_id_) { // Do a check in case we were cancelled.. |
| 164 VLOG(1) << "Setting fake recognition result."; | 154 VLOG(1) << "Setting fake recognition result."; |
| 165 listener_->OnAudioEnd(session_id_); | 155 listener_->OnAudioEnd(session_id_); |
| 166 content::SpeechRecognitionResult results; | 156 SpeechRecognitionResult results; |
| 167 results.hypotheses.push_back(content::SpeechRecognitionHypothesis( | 157 results.hypotheses.push_back(SpeechRecognitionHypothesis( |
| 168 ASCIIToUTF16(kTestResult), 1.0)); | 158 ASCIIToUTF16(kTestResult), 1.0)); |
| 169 listener_->OnRecognitionResult(session_id_, results); | 159 listener_->OnRecognitionResult(session_id_, results); |
| 170 listener_->OnRecognitionEnd(session_id_); | 160 listener_->OnRecognitionEnd(session_id_); |
| 171 session_id_ = 0; | 161 session_id_ = 0; |
| 172 listener_ = NULL; | 162 listener_ = NULL; |
| 173 VLOG(1) << "Finished setting fake recognition result."; | 163 VLOG(1) << "Finished setting fake recognition result."; |
| 174 } | 164 } |
| 175 } | 165 } |
| 176 | 166 |
| 177 int session_id_; | 167 int session_id_; |
| 178 SpeechRecognitionEventListener* listener_; | 168 SpeechRecognitionEventListener* listener_; |
| 179 SpeechRecognitionSessionConfig session_config_; | 169 SpeechRecognitionSessionConfig session_config_; |
| 180 SpeechRecognitionSessionContext session_ctx_; | 170 SpeechRecognitionSessionContext session_ctx_; |
| 181 std::string grammar_; | 171 std::string grammar_; |
| 182 bool did_cancel_all_; | 172 bool did_cancel_all_; |
| 183 bool should_send_fake_response_; | 173 bool should_send_fake_response_; |
| 184 base::WaitableEvent recognition_started_event_; | 174 base::WaitableEvent recognition_started_event_; |
| 185 }; | 175 }; |
| 186 | 176 |
| 187 class SpeechRecognitionBrowserTest : public content::ContentBrowserTest { | 177 class SpeechRecognitionBrowserTest : public ContentBrowserTest { |
| 188 public: | 178 public: |
| 189 // ContentBrowserTest methods | 179 // ContentBrowserTest methods |
| 190 virtual void SetUpCommandLine(CommandLine* command_line) { | 180 virtual void SetUpCommandLine(CommandLine* command_line) { |
| 191 EXPECT_TRUE(!command_line->HasSwitch(switches::kDisableSpeechInput)); | 181 EXPECT_TRUE(!command_line->HasSwitch(switches::kDisableSpeechInput)); |
| 192 } | 182 } |
| 193 | 183 |
| 194 protected: | 184 protected: |
| 195 void LoadAndStartSpeechRecognitionTest(const char* filename) { | 185 void LoadAndStartSpeechRecognitionTest(const char* filename) { |
| 196 // The test page calculates the speech button's coordinate in the page on | 186 // The test page calculates the speech button's coordinate in the page on |
| 197 // load & sets that coordinate in the URL fragment. We send mouse down & up | 187 // load & sets that coordinate in the URL fragment. We send mouse down & up |
| 198 // events at that coordinate to trigger speech recognition. | 188 // events at that coordinate to trigger speech recognition. |
| 199 GURL test_url = content::GetTestUrl("speech", filename); | 189 GURL test_url = GetTestUrl("speech", filename); |
| 200 content::NavigateToURL(shell(), test_url); | 190 NavigateToURL(shell(), test_url); |
| 201 | 191 |
| 202 WebKit::WebMouseEvent mouse_event; | 192 WebKit::WebMouseEvent mouse_event; |
| 203 mouse_event.type = WebKit::WebInputEvent::MouseDown; | 193 mouse_event.type = WebKit::WebInputEvent::MouseDown; |
| 204 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft; | 194 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft; |
| 205 mouse_event.x = 0; | 195 mouse_event.x = 0; |
| 206 mouse_event.y = 0; | 196 mouse_event.y = 0; |
| 207 mouse_event.clickCount = 1; | 197 mouse_event.clickCount = 1; |
| 208 WebContents* web_contents = shell()->web_contents(); | 198 WebContents* web_contents = shell()->web_contents(); |
| 209 | 199 |
| 210 content::WindowedNotificationObserver observer( | 200 WindowedNotificationObserver observer( |
| 211 content::NOTIFICATION_LOAD_STOP, | 201 NOTIFICATION_LOAD_STOP, |
| 212 content::Source<NavigationController>(&web_contents->GetController())); | 202 Source<NavigationController>(&web_contents->GetController())); |
| 213 web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); | 203 web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); |
| 214 mouse_event.type = WebKit::WebInputEvent::MouseUp; | 204 mouse_event.type = WebKit::WebInputEvent::MouseUp; |
| 215 web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); | 205 web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); |
| 216 fake_speech_recognition_manager_.recognition_started_event().Wait(); | 206 fake_speech_recognition_manager_.recognition_started_event().Wait(); |
| 217 | 207 |
| 218 // We should wait for a navigation event, raised by the test page JS code | 208 // We should wait for a navigation event, raised by the test page JS code |
| 219 // upon the onwebkitspeechchange event, in all cases except when the | 209 // upon the onwebkitspeechchange event, in all cases except when the |
| 220 // speech response is inhibited. | 210 // speech response is inhibited. |
| 221 if (fake_speech_recognition_manager_.should_send_fake_response()) | 211 if (fake_speech_recognition_manager_.should_send_fake_response()) |
| 222 observer.Wait(); | 212 observer.Wait(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 243 } | 233 } |
| 244 | 234 |
| 245 virtual void TearDownInProcessBrowserTestFixture() { | 235 virtual void TearDownInProcessBrowserTestFixture() { |
| 246 speech_recognition_manager_ = NULL; | 236 speech_recognition_manager_ = NULL; |
| 247 } | 237 } |
| 248 | 238 |
| 249 FakeSpeechRecognitionManager fake_speech_recognition_manager_; | 239 FakeSpeechRecognitionManager fake_speech_recognition_manager_; |
| 250 | 240 |
| 251 // This is used by the static |fakeManager|, and it is a pointer rather than a | 241 // This is used by the static |fakeManager|, and it is a pointer rather than a |
| 252 // direct instance per the style guide. | 242 // direct instance per the style guide. |
| 253 static content::SpeechRecognitionManager* speech_recognition_manager_; | 243 static SpeechRecognitionManager* speech_recognition_manager_; |
| 254 }; | 244 }; |
| 255 | 245 |
| 256 content::SpeechRecognitionManager* | 246 SpeechRecognitionManager* |
| 257 SpeechRecognitionBrowserTest::speech_recognition_manager_ = NULL; | 247 SpeechRecognitionBrowserTest::speech_recognition_manager_ = NULL; |
| 258 | 248 |
| 259 // TODO(satish): Once this flakiness has been fixed, add a second test here to | 249 // TODO(satish): Once this flakiness has been fixed, add a second test here to |
| 260 // check for sending many clicks in succession to the speech button and verify | 250 // check for sending many clicks in succession to the speech button and verify |
| 261 // that it doesn't cause any crash but works as expected. This should act as the | 251 // that it doesn't cause any crash but works as expected. This should act as the |
| 262 // test for http://crbug.com/59173 | 252 // test for http://crbug.com/59173 |
| 263 // | 253 // |
| 264 // TODO(satish): Similar to above, once this flakiness has been fixed add | 254 // TODO(satish): Similar to above, once this flakiness has been fixed add |
| 265 // another test here to check that when speech recognition is in progress and | 255 // another test here to check that when speech recognition is in progress and |
| 266 // a renderer crashes, we get a call to | 256 // a renderer crashes, we get a call to |
| (...skipping 14 matching lines...) Expand all Loading... |
| 281 // The test checks that the cancel-all callback gets issued when a session | 271 // The test checks that the cancel-all callback gets issued when a session |
| 282 // is pending, so don't send a fake response. | 272 // is pending, so don't send a fake response. |
| 283 // We are not expecting a navigation event being raised from the JS of the | 273 // We are not expecting a navigation event being raised from the JS of the |
| 284 // test page JavaScript in this case. | 274 // test page JavaScript in this case. |
| 285 fake_speech_recognition_manager_.set_should_send_fake_response(false); | 275 fake_speech_recognition_manager_.set_should_send_fake_response(false); |
| 286 | 276 |
| 287 LoadAndStartSpeechRecognitionTest("basic_recognition.html"); | 277 LoadAndStartSpeechRecognitionTest("basic_recognition.html"); |
| 288 | 278 |
| 289 // Make the renderer crash. This should trigger | 279 // Make the renderer crash. This should trigger |
| 290 // InputTagSpeechDispatcherHost to cancel all pending sessions. | 280 // InputTagSpeechDispatcherHost to cancel all pending sessions. |
| 291 content::NavigateToURL(shell(), GURL(chrome::kChromeUICrashURL)); | 281 NavigateToURL(shell(), GURL(chrome::kChromeUICrashURL)); |
| 292 | 282 |
| 293 EXPECT_TRUE(fake_speech_recognition_manager_.did_cancel_all()); | 283 EXPECT_TRUE(fake_speech_recognition_manager_.did_cancel_all()); |
| 294 } | 284 } |
| 295 | 285 |
| 296 } // namespace speech | 286 } // namespace content |
| OLD | NEW |