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