1/* 2 * Copyright (C) 2013 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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "SpellCheckClient.h" 32 33#include "MockGrammarCheck.h" 34#include "public/testing/WebTestDelegate.h" 35#include "public/web/WebTextCheckingCompletion.h" 36#include "public/web/WebTextCheckingResult.h" 37 38using namespace WebKit; 39using namespace std; 40 41namespace WebTestRunner { 42 43namespace { 44 45class HostMethodTask : public WebMethodTask<SpellCheckClient> { 46public: 47 typedef void (SpellCheckClient::*CallbackMethodType)(); 48 HostMethodTask(SpellCheckClient* object, CallbackMethodType callback) 49 : WebMethodTask<SpellCheckClient>(object) 50 , m_callback(callback) 51 { } 52 53 virtual void runIfValid() { (m_object->*m_callback)(); } 54 55private: 56 CallbackMethodType m_callback; 57}; 58 59} 60 61SpellCheckClient::SpellCheckClient() 62 : m_lastRequestedTextCheckingCompletion(0) 63{ 64} 65 66SpellCheckClient::~SpellCheckClient() 67{ 68} 69 70void SpellCheckClient::setDelegate(WebTestDelegate* delegate) 71{ 72 m_delegate = delegate; 73} 74 75// WebKit::WebSpellCheckClient 76void SpellCheckClient::spellCheck(const WebString& text, int& misspelledOffset, int& misspelledLength, WebVector<WebString>* optionalSuggestions) 77{ 78 // Check the spelling of the given text. 79 m_spellcheck.spellCheckWord(text, &misspelledOffset, &misspelledLength); 80} 81 82void SpellCheckClient::checkTextOfParagraph(const WebString& text, WebTextCheckingTypeMask mask, WebVector<WebTextCheckingResult>* webResults) 83{ 84 vector<WebTextCheckingResult> results; 85 if (mask & WebTextCheckingTypeSpelling) { 86 size_t offset = 0; 87 string16 data = text; 88 while (offset < data.length()) { 89 int misspelledPosition = 0; 90 int misspelledLength = 0; 91 m_spellcheck.spellCheckWord(data.substr(offset), &misspelledPosition, &misspelledLength); 92 if (!misspelledLength) 93 break; 94 WebTextCheckingResult result; 95 result.type = WebTextCheckingTypeSpelling; 96 result.location = offset + misspelledPosition; 97 result.length = misspelledLength; 98 results.push_back(result); 99 offset += misspelledPosition + misspelledLength; 100 } 101 } 102 if (mask & WebTextCheckingTypeGrammar) 103 MockGrammarCheck::checkGrammarOfString(text, &results); 104 webResults->assign(results); 105} 106 107void SpellCheckClient::requestCheckingOfText( 108 const WebString& text, 109 const WebVector<uint32_t>& markers, 110 const WebVector<unsigned>& markerOffsets, 111 WebTextCheckingCompletion* completion) 112{ 113 if (text.isEmpty()) { 114 if (completion) 115 completion->didCancelCheckingText(); 116 return; 117 } 118 119 m_lastRequestedTextCheckingCompletion = completion; 120 m_lastRequestedTextCheckString = text; 121 if (m_spellcheck.hasInCache(text)) 122 finishLastTextCheck(); 123 else 124 m_delegate->postDelayedTask(new HostMethodTask(this, &SpellCheckClient::finishLastTextCheck), 0); 125} 126 127void SpellCheckClient::finishLastTextCheck() 128{ 129 if (!m_lastRequestedTextCheckingCompletion) 130 return; 131 vector<WebTextCheckingResult> results; 132 int offset = 0; 133 string16 text = m_lastRequestedTextCheckString; 134 while (text.length()) { 135 int misspelledPosition = 0; 136 int misspelledLength = 0; 137 m_spellcheck.spellCheckWord(WebString(text), &misspelledPosition, &misspelledLength); 138 if (!misspelledLength) 139 break; 140 WebVector<WebString> suggestions; 141 m_spellcheck.fillSuggestionList(WebString(text.substr(misspelledPosition, misspelledLength)), &suggestions); 142 results.push_back(WebTextCheckingResult(WebTextCheckingTypeSpelling, offset + misspelledPosition, misspelledLength, suggestions.isEmpty() ? WebString() : suggestions[0])); 143 text = text.substr(misspelledPosition + misspelledLength); 144 offset += misspelledPosition + misspelledLength; 145 } 146 MockGrammarCheck::checkGrammarOfString(m_lastRequestedTextCheckString, &results); 147 m_lastRequestedTextCheckingCompletion->didFinishCheckingText(results); 148 m_lastRequestedTextCheckingCompletion = 0; 149} 150 151WebString SpellCheckClient::autoCorrectWord(const WebString&) 152{ 153 // Returns an empty string as Mac WebKit ('WebKitSupport/WebEditorClient.mm') 154 // does. (If this function returns a non-empty string, WebKit replaces the 155 // given misspelled string with the result one. This process executes some 156 // editor commands and causes layout-test failures.) 157 return WebString(); 158} 159 160} 161