// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "components/test_runner/mock_spell_check.h" #include "base/logging.h" #include "components/test_runner/test_common.h" #include "third_party/WebKit/public/platform/WebCString.h" namespace test_runner { namespace { void Append(blink::WebVector* data, const blink::WebString& item) { blink::WebVector result(data->size() + 1); for (size_t i = 0; i < data->size(); ++i) result[i] = (*data)[i]; result[data->size()] = item; data->swap(result); } } // namespace MockSpellCheck::MockSpellCheck() : initialized_(false) { } MockSpellCheck::~MockSpellCheck() { } bool MockSpellCheck::SpellCheckWord(const blink::WebString& text, int* misspelled_offset, int* misspelled_length) { DCHECK(misspelled_offset); DCHECK(misspelled_length); // Initialize this spellchecker. InitializeIfNeeded(); // Reset the result values as our spellchecker does. *misspelled_offset = 0; *misspelled_length = 0; // Convert to a base::string16 because we store base::string16 instances in // misspelled_words_ and blink::WebString has no find(). base::string16 string_text = text; int skipped_length = 0; while (!string_text.empty()) { // Extract the first possible English word from the given string. // The given string may include non-ASCII characters or numbers. So, we // should filter out such characters before start looking up our // misspelled-word table. // (This is a simple version of our SpellCheckWordIterator class.) // If the given string doesn't include any ASCII characters, we can treat // the string as valid one. base::string16::iterator first_char = std::find_if(string_text.begin(), string_text.end(), IsASCIIAlpha); if (first_char == string_text.end()) return true; int word_offset = std::distance(string_text.begin(), first_char); int max_word_length = static_cast(string_text.length()) - word_offset; int word_length; base::string16 word; // Look up our misspelled-word table to check if the extracted word is a // known misspelled word, and return the offset and the length of the // extracted word if this word is a known misspelled word. // (See the comment in MockSpellCheck::InitializeIfNeeded() why we use a // misspelled-word table.) for (size_t i = 0; i < misspelled_words_.size(); ++i) { word_length = static_cast(misspelled_words_.at(i).length()) > max_word_length ? max_word_length : static_cast(misspelled_words_.at(i).length()); word = string_text.substr(word_offset, word_length); if (word == misspelled_words_.at(i) && (static_cast(string_text.length()) == word_offset + word_length || IsNotASCIIAlpha(string_text[word_offset + word_length]))) { *misspelled_offset = word_offset + skipped_length; *misspelled_length = word_length; break; } } if (*misspelled_length > 0) break; base::string16::iterator last_char = std::find_if( string_text.begin() + word_offset, string_text.end(), IsNotASCIIAlpha); if (last_char == string_text.end()) word_length = static_cast(string_text.length()) - word_offset; else word_length = std::distance(first_char, last_char); DCHECK_LT(0, word_offset + word_length); string_text = string_text.substr(word_offset + word_length); skipped_length += word_offset + word_length; } return false; } bool MockSpellCheck::HasInCache(const blink::WebString& word) { return word == blink::WebString::fromUTF8("Spell wellcome. Is it broken?") || word == blink::WebString::fromUTF8("Spell wellcome.\x007F"); } bool MockSpellCheck::IsMultiWordMisspelling( const blink::WebString& text, std::vector* results) { if (text == blink::WebString::fromUTF8("Helllo wordl.")) { results->push_back(blink::WebTextCheckingResult( blink::WebTextDecorationTypeSpelling, 0, 6, blink::WebString("Hello"))); results->push_back(blink::WebTextCheckingResult( blink::WebTextDecorationTypeSpelling, 7, 5, blink::WebString("world"))); return true; } return false; } void MockSpellCheck::FillSuggestionList( const blink::WebString& word, blink::WebVector* suggestions) { if (word == blink::WebString::fromUTF8("wellcome")) Append(suggestions, blink::WebString::fromUTF8("welcome")); else if (word == blink::WebString::fromUTF8("upper case")) Append(suggestions, blink::WebString::fromUTF8("uppercase")); else if (word == blink::WebString::fromUTF8("Helllo")) Append(suggestions, blink::WebString::fromUTF8("Hello")); else if (word == blink::WebString::fromUTF8("wordl")) Append(suggestions, blink::WebString::fromUTF8("world")); } bool MockSpellCheck::InitializeIfNeeded() { // Exit if we have already initialized this object. if (initialized_) return false; // Create a table that consists of misspelled words used in WebKit layout // tests. // Since WebKit layout tests don't have so many misspelled words as // well-spelled words, it is easier to compare the given word with misspelled // ones than to compare with well-spelled ones. static const char* misspelled_words[] = { // These words are known misspelled words in webkit tests. // If there are other misspelled words in webkit tests, please add them in // this array. "foo", "Foo", "baz", "fo", "LibertyF", "chello", "xxxtestxxx", "XXxxx", "Textx", "blockquoted", "asd", "Lorem", "Nunc", "Curabitur", "eu", "adlj", "adaasj", "sdklj", "jlkds", "jsaada", "jlda", "zz", "contentEditable", // The following words are used by unit tests. "ifmmp", "qwertyuiopasd", "qwertyuiopasdf", "upper case", "wellcome"}; misspelled_words_.clear(); for (size_t i = 0; i < arraysize(misspelled_words); ++i) misspelled_words_.push_back( base::string16(misspelled_words[i], misspelled_words[i] + strlen(misspelled_words[i]))); // Mark as initialized to prevent this object from being initialized twice // or more. initialized_ = true; // Since this MockSpellCheck class doesn't download dictionaries, this // function always returns false. return false; } } // namespace test_runner