Home | History | Annotate | Download | only in runner
      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 WebKit;
     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         WEBKIT_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     WEBKIT_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