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 3// found in the LICENSE file. 4 5#include "base/command_line.h" 6#include "base/files/file_path.h" 7#include "base/memory/scoped_ptr.h" 8#include "base/message_loop/message_loop.h" 9#include "base/strings/string_number_conversions.h" 10#include "base/strings/utf_string_conversions.h" 11#include "content/browser/renderer_host/render_view_host_impl.h" 12#include "content/browser/web_contents/web_contents_impl.h" 13#include "content/public/browser/notification_types.h" 14#include "content/public/browser/web_contents.h" 15#include "content/public/common/content_switches.h" 16#include "content/public/common/speech_recognition_error.h" 17#include "content/public/common/speech_recognition_result.h" 18#include "content/public/common/url_constants.h" 19#include "content/public/test/fake_speech_recognition_manager.h" 20#include "content/public/test/test_utils.h" 21#include "content/shell/shell.h" 22#include "content/test/content_browser_test.h" 23#include "content/test/content_browser_test_utils.h" 24#include "third_party/WebKit/public/web/WebInputEvent.h" 25 26namespace content { 27 28class SpeechRecognitionBrowserTest : public ContentBrowserTest { 29 public: 30 // ContentBrowserTest methods 31 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 32 EXPECT_TRUE(!command_line->HasSwitch(switches::kDisableSpeechInput)); 33 } 34 35 protected: 36 void LoadAndStartSpeechRecognitionTest(const char* filename) { 37 // The test page calculates the speech button's coordinate in the page on 38 // load & sets that coordinate in the URL fragment. We send mouse down & up 39 // events at that coordinate to trigger speech recognition. 40 GURL test_url = GetTestUrl("speech", filename); 41 NavigateToURL(shell(), test_url); 42 43 WebKit::WebMouseEvent mouse_event; 44 mouse_event.type = WebKit::WebInputEvent::MouseDown; 45 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft; 46 mouse_event.x = 0; 47 mouse_event.y = 0; 48 mouse_event.clickCount = 1; 49 WebContents* web_contents = shell()->web_contents(); 50 51 WindowedNotificationObserver observer( 52 NOTIFICATION_LOAD_STOP, 53 Source<NavigationController>(&web_contents->GetController())); 54 web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); 55 mouse_event.type = WebKit::WebInputEvent::MouseUp; 56 web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); 57 fake_speech_recognition_manager_.WaitForRecognitionStarted(); 58 59 // We should wait for a navigation event, raised by the test page JS code 60 // upon the onwebkitspeechchange event, in all cases except when the 61 // speech response is inhibited. 62 if (fake_speech_recognition_manager_.should_send_fake_response()) 63 observer.Wait(); 64 } 65 66 void RunSpeechRecognitionTest(const char* filename) { 67 // The fake speech input manager would receive the speech input 68 // request and return the test string as recognition result. The test page 69 // then sets the URL fragment as 'pass' if it received the expected string. 70 LoadAndStartSpeechRecognitionTest(filename); 71 72 EXPECT_EQ("pass", shell()->web_contents()->GetURL().ref()); 73 } 74 75 // ContentBrowserTest methods. 76 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 77 fake_speech_recognition_manager_.set_should_send_fake_response(true); 78 speech_recognition_manager_ = &fake_speech_recognition_manager_; 79 80 // Inject the fake manager factory so that the test result is returned to 81 // the web page. 82 SpeechRecognitionManager::SetManagerForTests(speech_recognition_manager_); 83 } 84 85 virtual void TearDownInProcessBrowserTestFixture() OVERRIDE { 86 speech_recognition_manager_ = NULL; 87 } 88 89 FakeSpeechRecognitionManager fake_speech_recognition_manager_; 90 91 // This is used by the static |fakeManager|, and it is a pointer rather than a 92 // direct instance per the style guide. 93 static SpeechRecognitionManager* speech_recognition_manager_; 94}; 95 96SpeechRecognitionManager* 97 SpeechRecognitionBrowserTest::speech_recognition_manager_ = NULL; 98 99// TODO(satish): Once this flakiness has been fixed, add a second test here to 100// check for sending many clicks in succession to the speech button and verify 101// that it doesn't cause any crash but works as expected. This should act as the 102// test for http://crbug.com/59173 103// 104// TODO(satish): Similar to above, once this flakiness has been fixed add 105// another test here to check that when speech recognition is in progress and 106// a renderer crashes, we get a call to 107// SpeechRecognitionManager::CancelAllRequestsWithDelegate. 108IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, TestBasicRecognition) { 109 RunSpeechRecognitionTest("basic_recognition.html"); 110 EXPECT_TRUE(fake_speech_recognition_manager_.grammar().empty()); 111} 112 113IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, GrammarAttribute) { 114 RunSpeechRecognitionTest("grammar_attribute.html"); 115 EXPECT_EQ("http://example.com/grammar.xml", 116 fake_speech_recognition_manager_.grammar()); 117} 118 119// Flaky on Linux, Windows and Mac http://crbug.com/140765. 120IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, DISABLED_TestCancelAll) { 121 // The test checks that the cancel-all callback gets issued when a session 122 // is pending, so don't send a fake response. 123 // We are not expecting a navigation event being raised from the JS of the 124 // test page JavaScript in this case. 125 fake_speech_recognition_manager_.set_should_send_fake_response(false); 126 127 LoadAndStartSpeechRecognitionTest("basic_recognition.html"); 128 129 // Make the renderer crash. This should trigger 130 // InputTagSpeechDispatcherHost to cancel all pending sessions. 131 NavigateToURL(shell(), GURL(kChromeUICrashURL)); 132 133 EXPECT_TRUE(fake_speech_recognition_manager_.did_cancel_all()); 134} 135 136} // namespace content 137