1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "MockWebSpeechRecognizer.h"
27
28 #include "public/testing/WebTestDelegate.h"
29 #include "public/web/WebSpeechRecognitionResult.h"
30 #include "public/web/WebSpeechRecognizerClient.h"
31
32 using namespace blink;
33 using namespace std;
34
35 namespace WebTestRunner {
36
37 namespace {
38
39 // Task class for calling a client function that does not take any parameters.
40 typedef void (WebSpeechRecognizerClient::*ClientFunctionPointer)(const WebSpeechRecognitionHandle&);
41 class ClientCallTask : public MockWebSpeechRecognizer::Task {
42 public:
ClientCallTask(MockWebSpeechRecognizer * mock,ClientFunctionPointer function)43 ClientCallTask(MockWebSpeechRecognizer* mock, ClientFunctionPointer function)
44 : MockWebSpeechRecognizer::Task(mock)
45 , m_function(function)
46 {
47 }
48
run()49 virtual void run() OVERRIDE { (m_recognizer->client()->*m_function)(m_recognizer->handle()); }
50
51 private:
52 ClientFunctionPointer m_function;
53 };
54
55 // Task for delivering a result event.
56 class ResultTask : public MockWebSpeechRecognizer::Task {
57 public:
ResultTask(MockWebSpeechRecognizer * mock,const WebString transcript,float confidence)58 ResultTask(MockWebSpeechRecognizer* mock, const WebString transcript, float confidence)
59 : MockWebSpeechRecognizer::Task(mock)
60 , m_transcript(transcript)
61 , m_confidence(confidence)
62 {
63 }
64
run()65 virtual void run() OVERRIDE
66 {
67 WebVector<WebString> transcripts(static_cast<size_t>(1));
68 WebVector<float> confidences(static_cast<size_t>(1));
69 transcripts[0] = m_transcript;
70 confidences[0] = m_confidence;
71 WebVector<WebSpeechRecognitionResult> finalResults(static_cast<size_t>(1));
72 WebVector<WebSpeechRecognitionResult> interimResults;
73 finalResults[0].assign(transcripts, confidences, true);
74
75 m_recognizer->client()->didReceiveResults(m_recognizer->handle(), finalResults, interimResults);
76 }
77
78 private:
79 WebString m_transcript;
80 float m_confidence;
81 };
82
83 // Task for delivering a nomatch event.
84 class NoMatchTask : public MockWebSpeechRecognizer::Task {
85 public:
NoMatchTask(MockWebSpeechRecognizer * mock)86 NoMatchTask(MockWebSpeechRecognizer* mock) : MockWebSpeechRecognizer::Task(mock) { }
run()87 virtual void run() OVERRIDE { m_recognizer->client()->didReceiveNoMatch(m_recognizer->handle(), WebSpeechRecognitionResult()); }
88 };
89
90 // Task for delivering an error event.
91 class ErrorTask : public MockWebSpeechRecognizer::Task {
92 public:
ErrorTask(MockWebSpeechRecognizer * mock,WebSpeechRecognizerClient::ErrorCode code,const WebString & message)93 ErrorTask(MockWebSpeechRecognizer* mock, WebSpeechRecognizerClient::ErrorCode code, const WebString& message)
94 : MockWebSpeechRecognizer::Task(mock)
95 , m_code(code)
96 , m_message(message)
97 {
98 }
99
run()100 virtual void run() OVERRIDE { m_recognizer->client()->didReceiveError(m_recognizer->handle(), m_message, m_code); }
101
102 private:
103 WebSpeechRecognizerClient::ErrorCode m_code;
104 WebString m_message;
105 };
106
107 } // namespace
108
MockWebSpeechRecognizer()109 MockWebSpeechRecognizer::MockWebSpeechRecognizer()
110 : m_wasAborted(false)
111 , m_taskQueueRunning(false)
112 , m_delegate(0)
113 {
114 }
115
~MockWebSpeechRecognizer()116 MockWebSpeechRecognizer::~MockWebSpeechRecognizer()
117 {
118 clearTaskQueue();
119 }
120
setDelegate(WebTestDelegate * delegate)121 void MockWebSpeechRecognizer::setDelegate(WebTestDelegate* delegate)
122 {
123 m_delegate = delegate;
124 }
125
start(const WebSpeechRecognitionHandle & handle,const WebSpeechRecognitionParams & params,WebSpeechRecognizerClient * client)126 void MockWebSpeechRecognizer::start(const WebSpeechRecognitionHandle& handle, const WebSpeechRecognitionParams& params, WebSpeechRecognizerClient* client)
127 {
128 m_wasAborted = false;
129 m_handle = handle;
130 m_client = client;
131
132 m_taskQueue.push_back(new ClientCallTask(this, &WebSpeechRecognizerClient::didStart));
133 m_taskQueue.push_back(new ClientCallTask(this, &WebSpeechRecognizerClient::didStartAudio));
134 m_taskQueue.push_back(new ClientCallTask(this, &WebSpeechRecognizerClient::didStartSound));
135
136 if (!m_mockTranscripts.empty()) {
137 BLINK_ASSERT(m_mockTranscripts.size() == m_mockConfidences.size());
138
139 for (size_t i = 0; i < m_mockTranscripts.size(); ++i)
140 m_taskQueue.push_back(new ResultTask(this, m_mockTranscripts[i], m_mockConfidences[i]));
141
142 m_mockTranscripts.clear();
143 m_mockConfidences.clear();
144 } else
145 m_taskQueue.push_back(new NoMatchTask(this));
146
147 m_taskQueue.push_back(new ClientCallTask(this, &WebSpeechRecognizerClient::didEndSound));
148 m_taskQueue.push_back(new ClientCallTask(this, &WebSpeechRecognizerClient::didEndAudio));
149 m_taskQueue.push_back(new ClientCallTask(this, &WebSpeechRecognizerClient::didEnd));
150
151 startTaskQueue();
152 }
153
stop(const WebSpeechRecognitionHandle & handle,WebSpeechRecognizerClient * client)154 void MockWebSpeechRecognizer::stop(const WebSpeechRecognitionHandle& handle, WebSpeechRecognizerClient* client)
155 {
156 m_handle = handle;
157 m_client = client;
158
159 // FIXME: Implement.
160 BLINK_ASSERT_NOT_REACHED();
161 }
162
abort(const WebSpeechRecognitionHandle & handle,WebSpeechRecognizerClient * client)163 void MockWebSpeechRecognizer::abort(const WebSpeechRecognitionHandle& handle, WebSpeechRecognizerClient* client)
164 {
165 m_handle = handle;
166 m_client = client;
167
168 clearTaskQueue();
169 m_wasAborted = true;
170 m_taskQueue.push_back(new ClientCallTask(this, &WebSpeechRecognizerClient::didEnd));
171 startTaskQueue();
172 }
173
addMockResult(const WebString & transcript,float confidence)174 void MockWebSpeechRecognizer::addMockResult(const WebString& transcript, float confidence)
175 {
176 m_mockTranscripts.push_back(transcript);
177 m_mockConfidences.push_back(confidence);
178 }
179
setError(const WebString & error,const WebString & message)180 void MockWebSpeechRecognizer::setError(const WebString& error, const WebString& message)
181 {
182 WebSpeechRecognizerClient::ErrorCode code;
183 if (error == "OtherError")
184 code = WebSpeechRecognizerClient::OtherError;
185 else if (error == "NoSpeechError")
186 code = WebSpeechRecognizerClient::NoSpeechError;
187 else if (error == "AbortedError")
188 code = WebSpeechRecognizerClient::AbortedError;
189 else if (error == "AudioCaptureError")
190 code = WebSpeechRecognizerClient::AudioCaptureError;
191 else if (error == "NetworkError")
192 code = WebSpeechRecognizerClient::NetworkError;
193 else if (error == "NotAllowedError")
194 code = WebSpeechRecognizerClient::NotAllowedError;
195 else if (error == "ServiceNotAllowedError")
196 code = WebSpeechRecognizerClient::ServiceNotAllowedError;
197 else if (error == "BadGrammarError")
198 code = WebSpeechRecognizerClient::BadGrammarError;
199 else if (error == "LanguageNotSupportedError")
200 code = WebSpeechRecognizerClient::LanguageNotSupportedError;
201 else
202 return;
203
204 clearTaskQueue();
205 m_taskQueue.push_back(new ErrorTask(this, code, message));
206 m_taskQueue.push_back(new ClientCallTask(this, &WebSpeechRecognizerClient::didEnd));
207 startTaskQueue();
208 }
209
startTaskQueue()210 void MockWebSpeechRecognizer::startTaskQueue()
211 {
212 if (m_taskQueueRunning)
213 return;
214 m_delegate->postTask(new StepTask(this));
215 m_taskQueueRunning = true;
216 }
217
clearTaskQueue()218 void MockWebSpeechRecognizer::clearTaskQueue()
219 {
220 while (!m_taskQueue.empty()) {
221 delete m_taskQueue.front();
222 m_taskQueue.pop_front();
223 }
224 m_taskQueueRunning = false;
225 }
226
runIfValid()227 void MockWebSpeechRecognizer::StepTask::runIfValid()
228 {
229 if (m_object->m_taskQueue.empty()) {
230 m_object->m_taskQueueRunning = false;
231 return;
232 }
233
234 Task* task = m_object->m_taskQueue.front();
235 m_object->m_taskQueue.pop_front();
236 task->run();
237 delete task;
238
239 if (m_object->m_taskQueue.empty()) {
240 m_object->m_taskQueueRunning = false;
241 return;
242 }
243
244 m_object->m_delegate->postTask(new StepTask(m_object));
245 }
246
247 }
248