5b576c7e636bbe41e77739c4de28764b2dd57caf
[WebKit-https.git] / Tools / DumpRenderTree / chromium / MockWebSpeechInputController.cpp
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 "config.h"
27 #include "MockWebSpeechInputController.h"
28
29 #include "Task.h"
30 #include "WebSpeechInputListener.h"
31 #include <public/WebCString.h>
32 #include <public/WebVector.h>
33 #include <wtf/text/CString.h>
34 #include <wtf/text/StringBuilder.h>
35
36 #if ENABLE(INPUT_SPEECH)
37
38 using namespace WebKit;
39 using namespace WebTestRunner;
40
41 PassOwnPtr<MockWebSpeechInputController> MockWebSpeechInputController::create(WebSpeechInputListener* listener)
42 {
43     return adoptPtr(new MockWebSpeechInputController(listener));
44 }
45
46 void MockWebSpeechInputController::addMockRecognitionResult(const WebString& result, double confidence, const WebString& language)
47 {
48     WebSpeechInputResult res;
49     res.assign(result, confidence);
50
51     if (language.isEmpty())
52         m_resultsForEmptyLanguage.append(res);
53     else {
54         String langString = String::fromUTF8(language.utf8().data());
55         if (!m_recognitionResults.contains(langString))
56             m_recognitionResults.set(langString, Vector<WebSpeechInputResult>());
57         m_recognitionResults.find(langString)->value.append(res);
58     }
59 }
60
61 void MockWebSpeechInputController::setDumpRect(bool dumpRect)
62 {
63     m_dumpRect = dumpRect;
64 }
65
66 void MockWebSpeechInputController::clearResults()
67 {
68     m_resultsForEmptyLanguage.clear();
69     m_recognitionResults.clear();
70     m_dumpRect = false;
71 }
72
73 bool MockWebSpeechInputController::startRecognition(int requestId, const WebRect& elementRect, const WebString& language, const WebString& grammar, const WebSecurityOrigin& origin)
74 {
75     if (m_speechTask)
76         return false;
77
78     m_requestId = requestId;
79     m_requestRect = elementRect;
80     m_recording = true;
81     m_language = String::fromUTF8(language.utf8().data());
82
83     m_speechTask = new SpeechTask(this);
84     postTask(m_speechTask);
85
86     return true;
87 }
88
89 void MockWebSpeechInputController::cancelRecognition(int requestId)
90 {
91     if (m_speechTask) {
92         ASSERT(requestId == m_requestId);
93
94         m_speechTask->stop();
95         m_recording = false;
96         m_listener->didCompleteRecognition(m_requestId);
97         m_requestId = 0;
98     }
99 }
100
101 void MockWebSpeechInputController::stopRecording(int requestId)
102 {
103     ASSERT(requestId == m_requestId);
104     if (m_speechTask && m_recording) {
105         m_speechTask->stop();
106         speechTaskFired();
107     }
108 }
109
110 MockWebSpeechInputController::MockWebSpeechInputController(WebSpeechInputListener* listener)
111     : m_listener(listener)
112     , m_speechTask(0)
113     , m_recording(false)
114     , m_requestId(-1)
115     , m_dumpRect(false)
116 {
117 }
118
119 static WebSpeechInputResultArray makeRectResult(const WebRect& rect)
120 {
121     StringBuilder sb;
122     sb.append(String::number(rect.x));
123     sb.append(",");
124     sb.append(String::number(rect.y));
125     sb.append(",");
126     sb.append(String::number(rect.width));
127     sb.append(",");
128     sb.append(String::number(rect.height));
129
130     WebSpeechInputResult res;
131     res.assign(WebString(sb.characters(), sb.length()), 1.0);
132
133     WebSpeechInputResultArray results;
134     results.assign(&res, 1);
135     return results;
136 }
137
138 void MockWebSpeechInputController::speechTaskFired()
139 {
140     if (m_recording) {
141         m_recording = false;
142         m_listener->didCompleteRecording(m_requestId);
143
144         m_speechTask = new SpeechTask(this);
145         postTask(m_speechTask);
146     } else {
147         bool noResultsFound = false;
148         // We take a copy of the requestId here so that if scripts destroyed the input element
149         // inside one of the callbacks below, we'll still know what this session's requestId was.
150         int requestId = m_requestId;
151         m_requestId = 0;
152
153         if (m_dumpRect) {
154             m_listener->setRecognitionResult(requestId, makeRectResult(m_requestRect));
155         } else if (m_language.isEmpty()) {
156             // Empty language case must be handled separately to avoid problems with HashMap and empty keys.
157             if (!m_resultsForEmptyLanguage.isEmpty())
158                 m_listener->setRecognitionResult(requestId, m_resultsForEmptyLanguage);
159             else
160                 noResultsFound = true;
161         } else {
162             if (m_recognitionResults.contains(m_language))
163                 m_listener->setRecognitionResult(requestId, m_recognitionResults.get(m_language));
164             else
165                 noResultsFound = true;
166         }
167
168         if (noResultsFound) {
169             // Can't avoid setting a result even if no result was set for the given language.
170             // This would avoid generating the events used to check the results and the test would timeout.
171             String error("error: no result found for language '");
172             error.append(m_language);
173             error.append("'");
174
175             WebSpeechInputResult res;
176             res.assign(WebString::fromUTF8(error.utf8().data()), 1.0);
177
178             Vector<WebSpeechInputResult> results;
179             results.append(res);
180
181             m_listener->setRecognitionResult(requestId, results);
182         }
183     }
184 }
185
186 MockWebSpeechInputController::SpeechTask::SpeechTask(MockWebSpeechInputController* mock)
187     : WebMethodTask<MockWebSpeechInputController>::WebMethodTask(mock)
188 {
189 }
190
191 void MockWebSpeechInputController::SpeechTask::stop()
192 {
193     m_object->m_speechTask = 0;
194     cancel();
195     delete(this);
196 }
197
198 void MockWebSpeechInputController::SpeechTask::runIfValid()
199 {
200     m_object->m_speechTask = 0;
201     m_object->speechTaskFired();
202 }
203
204 #endif