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 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 28 #include "modules/speech/SpeechRecognition.h" 29 30 #include "bindings/core/v8/ExceptionState.h" 31 #include "core/dom/Document.h" 32 #include "core/dom/ExceptionCode.h" 33 #include "core/page/Page.h" 34 #include "modules/speech/SpeechRecognitionController.h" 35 #include "modules/speech/SpeechRecognitionError.h" 36 #include "modules/speech/SpeechRecognitionEvent.h" 37 38 namespace blink { 39 40 SpeechRecognition* SpeechRecognition::create(ExecutionContext* context) 41 { 42 SpeechRecognition* speechRecognition = adoptRefCountedGarbageCollectedWillBeNoop(new SpeechRecognition(context)); 43 speechRecognition->suspendIfNeeded(); 44 return speechRecognition; 45 } 46 47 void SpeechRecognition::start(ExceptionState& exceptionState) 48 { 49 ASSERT(m_controller); 50 if (m_started) { 51 exceptionState.throwDOMException(InvalidStateError, "recognition has already started."); 52 return; 53 } 54 55 m_finalResults.clear(); 56 m_controller->start(this, m_grammars.get(), m_lang, m_continuous, m_interimResults, m_maxAlternatives); 57 m_started = true; 58 } 59 60 void SpeechRecognition::stopFunction() 61 { 62 ASSERT(m_controller); 63 if (m_started && !m_stopping) { 64 m_stopping = true; 65 m_controller->stop(this); 66 } 67 } 68 69 void SpeechRecognition::abort() 70 { 71 ASSERT(m_controller); 72 if (m_started && !m_stopping) { 73 m_stopping = true; 74 m_controller->abort(this); 75 } 76 } 77 78 void SpeechRecognition::didStartAudio() 79 { 80 dispatchEvent(Event::create(EventTypeNames::audiostart)); 81 } 82 83 void SpeechRecognition::didStartSound() 84 { 85 dispatchEvent(Event::create(EventTypeNames::soundstart)); 86 } 87 88 void SpeechRecognition::didStartSpeech() 89 { 90 dispatchEvent(Event::create(EventTypeNames::speechstart)); 91 } 92 93 void SpeechRecognition::didEndSpeech() 94 { 95 dispatchEvent(Event::create(EventTypeNames::speechend)); 96 } 97 98 void SpeechRecognition::didEndSound() 99 { 100 dispatchEvent(Event::create(EventTypeNames::soundend)); 101 } 102 103 void SpeechRecognition::didEndAudio() 104 { 105 dispatchEvent(Event::create(EventTypeNames::audioend)); 106 } 107 108 void SpeechRecognition::didReceiveResults(const HeapVector<Member<SpeechRecognitionResult> >& newFinalResults, const HeapVector<Member<SpeechRecognitionResult> >& currentInterimResults) 109 { 110 unsigned long resultIndex = m_finalResults.size(); 111 112 for (size_t i = 0; i < newFinalResults.size(); ++i) 113 m_finalResults.append(newFinalResults[i]); 114 115 HeapVector<Member<SpeechRecognitionResult> > results = m_finalResults; 116 for (size_t i = 0; i < currentInterimResults.size(); ++i) 117 results.append(currentInterimResults[i]); 118 119 dispatchEvent(SpeechRecognitionEvent::createResult(resultIndex, results)); 120 } 121 122 void SpeechRecognition::didReceiveNoMatch(SpeechRecognitionResult* result) 123 { 124 dispatchEvent(SpeechRecognitionEvent::createNoMatch(result)); 125 } 126 127 void SpeechRecognition::didReceiveError(PassRefPtrWillBeRawPtr<SpeechRecognitionError> error) 128 { 129 dispatchEvent(error); 130 m_started = false; 131 } 132 133 void SpeechRecognition::didStart() 134 { 135 dispatchEvent(Event::create(EventTypeNames::start)); 136 } 137 138 void SpeechRecognition::didEnd() 139 { 140 m_started = false; 141 m_stopping = false; 142 if (!m_stoppedByActiveDOMObject) 143 dispatchEvent(Event::create(EventTypeNames::end)); 144 } 145 146 const AtomicString& SpeechRecognition::interfaceName() const 147 { 148 return EventTargetNames::SpeechRecognition; 149 } 150 151 ExecutionContext* SpeechRecognition::executionContext() const 152 { 153 return ActiveDOMObject::executionContext(); 154 } 155 156 void SpeechRecognition::stop() 157 { 158 m_stoppedByActiveDOMObject = true; 159 if (hasPendingActivity()) 160 abort(); 161 } 162 163 bool SpeechRecognition::hasPendingActivity() const 164 { 165 return m_started; 166 } 167 168 SpeechRecognition::SpeechRecognition(ExecutionContext* context) 169 : ActiveDOMObject(context) 170 , m_grammars(SpeechGrammarList::create()) // FIXME: The spec is not clear on the default value for the grammars attribute. 171 , m_continuous(false) 172 , m_interimResults(false) 173 , m_maxAlternatives(1) 174 , m_controller(nullptr) 175 , m_stoppedByActiveDOMObject(false) 176 , m_started(false) 177 , m_stopping(false) 178 { 179 Document* document = toDocument(executionContext()); 180 181 Page* page = document->page(); 182 ASSERT(page); 183 184 m_controller = SpeechRecognitionController::from(page); 185 ASSERT(m_controller); 186 187 // FIXME: Need to hook up with Page to get notified when the visibility changes. 188 } 189 190 SpeechRecognition::~SpeechRecognition() 191 { 192 } 193 194 void SpeechRecognition::trace(Visitor* visitor) 195 { 196 visitor->trace(m_grammars); 197 #if ENABLE(OILPAN) 198 visitor->trace(m_controller); 199 #endif 200 visitor->trace(m_finalResults); 201 EventTargetWithInlineData::trace(visitor); 202 } 203 204 } // namespace blink 205