summaryrefslogtreecommitdiffstats
path: root/chrome/browser/speech/speech_input_browsertest.cc
blob: d49cb3c6207f44b38d294d48ce85fa856bc22071 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/speech/speech_input_dispatcher_host.h"
#include "chrome/browser/speech/speech_input_manager.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"

namespace speech_input {
class FakeSpeechInputManager;
}

// This class does not need to be refcounted (typically done by PostTask) since
// it will outlive the test and gets released only when the test shuts down.
// Disabling refcounting here saves a bit of unnecessary code and the factory
// method can return a plain pointer below as required by the real code.
DISABLE_RUNNABLE_METHOD_REFCOUNT(speech_input::FakeSpeechInputManager);

namespace speech_input {

const char* kTestResult = "Pictures of the moon";

class FakeSpeechInputManager : public SpeechInputManager {
 public:
  FakeSpeechInputManager()
      : caller_id_(0),
        delegate_(NULL) {
  }

  std::string grammar() {
    return grammar_;
  }

  // SpeechInputManager methods.
  void StartRecognition(Delegate* delegate,
                        int caller_id,
                        int render_process_id,
                        int render_view_id,
                        const gfx::Rect& element_rect,
                        const std::string& language,
                        const std::string& grammar) {
    VLOG(1) << "StartRecognition invoked.";
    EXPECT_EQ(0, caller_id_);
    EXPECT_EQ(NULL, delegate_);
    caller_id_ = caller_id;
    delegate_ = delegate;
    grammar_ = grammar;
    // Give the fake result in a short while.
    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(this,
        &FakeSpeechInputManager::SetFakeRecognitionResult));
  }
  void CancelRecognition(int caller_id) {
    VLOG(1) << "CancelRecognition invoked.";
    EXPECT_EQ(caller_id_, caller_id);
    caller_id_ = 0;
    delegate_ = NULL;
  }
  void StopRecording(int caller_id) {
    VLOG(1) << "StopRecording invoked.";
    EXPECT_EQ(caller_id_, caller_id);
    // Nothing to do here since we aren't really recording.
  }

 private:
  void SetFakeRecognitionResult() {
    if (caller_id_) {  // Do a check in case we were cancelled..
      VLOG(1) << "Setting fake recognition result.";
      delegate_->DidCompleteRecording(caller_id_);
      SpeechInputResultArray results;
      results.push_back(SpeechInputResultItem(ASCIIToUTF16(kTestResult), 1.0));
      delegate_->SetRecognitionResult(caller_id_, results);
      delegate_->DidCompleteRecognition(caller_id_);
      caller_id_ = 0;
      delegate_ = NULL;
      VLOG(1) << "Finished setting fake recognition result.";
    }
  }

  int caller_id_;
  Delegate* delegate_;
  std::string grammar_;
};

class SpeechInputBrowserTest : public InProcessBrowserTest {
 public:
  // InProcessBrowserTest methods
  GURL testUrl(const FilePath::CharType* filename) {
    const FilePath kTestDir(FILE_PATH_LITERAL("speech"));
    return ui_test_utils::GetTestUrl(kTestDir, FilePath(filename));
  }

 protected:
  void LoadAndRunSpeechInputTest(const FilePath::CharType* filename) {
    // The test page calculates the speech button's coordinate in the page on
    // load & sets that coordinate in the URL fragment. We send mouse down & up
    // events at that coordinate to trigger speech recognition.
    GURL test_url = testUrl(filename);
    ui_test_utils::NavigateToURL(browser(), test_url);
    std::string coords = browser()->GetSelectedTabContents()->GetURL().ref();
    VLOG(1) << "Coordinates given by script: " << coords;
    int comma_pos = coords.find(',');
    ASSERT_NE(-1, comma_pos);
    int x = 0;
    ASSERT_TRUE(base::StringToInt(coords.substr(0, comma_pos).c_str(), &x));
    int y = 0;
    ASSERT_TRUE(base::StringToInt(coords.substr(comma_pos + 1).c_str(), &y));

    WebKit::WebMouseEvent mouse_event;
    mouse_event.type = WebKit::WebInputEvent::MouseDown;
    mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
    mouse_event.x = x;
    mouse_event.y = y;
    mouse_event.clickCount = 1;
    TabContents* tab_contents = browser()->GetSelectedTabContents();
    tab_contents->render_view_host()->ForwardMouseEvent(mouse_event);
    mouse_event.type = WebKit::WebInputEvent::MouseUp;
    tab_contents->render_view_host()->ForwardMouseEvent(mouse_event);

    // The fake speech input manager would receive the speech input
    // request and return the test string as recognition result. The test page
    // then sets the URL fragment as 'pass' if it received the expected string.
    ui_test_utils::WaitForNavigations(&tab_contents->controller(), 1);
    EXPECT_EQ("pass", browser()->GetSelectedTabContents()->GetURL().ref());
  }

  // InProcessBrowserTest methods.
  virtual void SetUpInProcessBrowserTestFixture() {
    speech_input_manager_ = &fake_speech_input_manager_;

    // Inject the fake manager factory so that the test result is returned to
    // the web page.
    SpeechInputDispatcherHost::set_manager_accessor(&fakeManagerAccessor);
  }

  virtual void TearDownInProcessBrowserTestFixture() {
    speech_input_manager_ = NULL;
  }

  // Factory method.
  static SpeechInputManager* fakeManagerAccessor() {
    return speech_input_manager_;
  }

  FakeSpeechInputManager fake_speech_input_manager_;

  // This is used by the static |fakeManagerAccessor|, and it is a pointer
  // rather than a direct instance per the style guide.
  static SpeechInputManager* speech_input_manager_;
};

SpeechInputManager* SpeechInputBrowserTest::speech_input_manager_ = NULL;

// TODO(satish): Once this flakiness has been fixed, add a second test here to
// check for sending many clicks in succession to the speech button and verify
// that it doesn't cause any crash but works as expected. This should act as the
// test for http://crbug.com/59173
#if defined(GOOGLE_CHROME_BUILD)
// The tests are disabled for release branches since the speech input API is
// disabled on the release branches.
#define MAYBE_TestBasicRecognition DISABLED_TestBasicRecognition
#elif defined(OS_WIN)
// Marked as FLAKY due to http://crbug.com/51337
#define MAYBE_TestBasicRecognition FLAKY_TestBasicRecognition
#else
#define MAYBE_TestBasicRecognition TestBasicRecognition
#endif
IN_PROC_BROWSER_TEST_F(SpeechInputBrowserTest, MAYBE_TestBasicRecognition) {
  LoadAndRunSpeechInputTest(FILE_PATH_LITERAL("basic_recognition.html"));
  EXPECT_TRUE(fake_speech_input_manager_.grammar().empty());
}

#if defined(GOOGLE_CHROME_BUILD)
// The tests are disabled for release branches since the speech input API is
// disabled on the release branches.
#define MAYBE_GrammarAttribute DISABLED_GrammarAttribute
#elif defined(OS_WIN)
// Marked as FLAKY due to http://crbug.com/51337
#define MAYBE_GrammarAttribute FLAKY_GrammarAttribute
#else
#define MAYBE_GrammarAttribute GrammarAttribute
#endif
IN_PROC_BROWSER_TEST_F(SpeechInputBrowserTest, MAYBE_GrammarAttribute) {
  LoadAndRunSpeechInputTest(FILE_PATH_LITERAL("grammar_attribute.html"));
  EXPECT_EQ("http://example.com/grammar.xml",
            fake_speech_input_manager_.grammar());
}

} //  namespace speech_input