blob: a518c43cac622e9066236d8d64f7b4fb113ca214 [file] [log] [blame]
[email protected]e2dc7a92013-01-23 22:19:241// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
timvolodine7ef691f42016-08-12 00:18:225#include "components/spellcheck/renderer/spellcheck_language.h"
[email protected]e2dc7a92013-01-23 22:19:246
dchenge73d8520c2015-12-27 01:19:097#include <utility>
8
[email protected]e2dc7a92013-01-23 22:19:249#include "base/logging.h"
timvolodine7ef691f42016-08-12 00:18:2210#include "components/spellcheck/renderer/spellcheck_worditerator.h"
11#include "components/spellcheck/renderer/spelling_engine.h"
[email protected]e2dc7a92013-01-23 22:19:2412
Ben Goodger03c39c22017-10-26 23:45:3713SpellcheckLanguage::SpellcheckLanguage(
14 service_manager::LocalInterfaceProvider* embedder_provider)
15 : platform_spelling_engine_(CreateNativeSpellingEngine(embedder_provider)) {
[email protected]e2dc7a92013-01-23 22:19:2416}
17
18SpellcheckLanguage::~SpellcheckLanguage() {
19}
20
[email protected]008e3b32014-03-25 06:01:4821void SpellcheckLanguage::Init(base::File file, const std::string& language) {
Zinovy Nis701103b2018-05-10 22:59:3822 DCHECK(platform_spelling_engine_);
dchenge73d8520c2015-12-27 01:19:0923 platform_spelling_engine_->Init(std::move(file));
[email protected]e2dc7a92013-01-23 22:19:2424
25 character_attributes_.SetDefaultLanguage(language);
26 text_iterator_.Reset();
27 contraction_iterator_.Reset();
28}
29
30bool SpellcheckLanguage::InitializeIfNeeded() {
Zinovy Nis701103b2018-05-10 22:59:3831 DCHECK(platform_spelling_engine_);
[email protected]e2dc7a92013-01-23 22:19:2432 return platform_spelling_engine_->InitializeIfNeeded();
33}
34
juliusa99884d892015-08-15 02:49:1935SpellcheckLanguage::SpellcheckWordResult SpellcheckLanguage::SpellCheckWord(
36 const base::char16* text_begin,
37 int position_in_text,
38 int text_length,
[email protected]e2dc7a92013-01-23 22:19:2439 int tag,
juliusa99884d892015-08-15 02:49:1940 int* skip_or_misspelling_start,
41 int* skip_or_misspelling_len,
[email protected]12469f92013-12-04 22:50:0742 std::vector<base::string16>* optional_suggestions) {
juliusa99884d892015-08-15 02:49:1943 int remaining_text_len = text_length - position_in_text;
44 DCHECK(remaining_text_len >= 0);
45 DCHECK(skip_or_misspelling_start && skip_or_misspelling_len)
46 << "Out vars must be given.";
[email protected]e2dc7a92013-01-23 22:19:2447
48 // Do nothing if we need to delay initialization. (Rather than blocking,
49 // report the word as correctly spelled.)
50 if (InitializeIfNeeded())
juliusa99884d892015-08-15 02:49:1951 return IS_CORRECT;
[email protected]e2dc7a92013-01-23 22:19:2452
53 // Do nothing if spell checking is disabled.
Zinovy Nis701103b2018-05-10 22:59:3854 if (!platform_spelling_engine_ || !platform_spelling_engine_->IsEnabled())
juliusa99884d892015-08-15 02:49:1955 return IS_CORRECT;
[email protected]e2dc7a92013-01-23 22:19:2456
juliusa99884d892015-08-15 02:49:1957 *skip_or_misspelling_start = 0;
58 *skip_or_misspelling_len = 0;
59 if (remaining_text_len == 0)
60 return IS_CORRECT; // No input means always spelled correctly.
[email protected]e2dc7a92013-01-23 22:19:2461
[email protected]12469f92013-12-04 22:50:0762 base::string16 word;
[email protected]e2dc7a92013-01-23 22:19:2463 int word_start;
64 int word_length;
65 if (!text_iterator_.IsInitialized() &&
66 !text_iterator_.Initialize(&character_attributes_, true)) {
67 // We failed to initialize text_iterator_, return as spelled correctly.
68 VLOG(1) << "Failed to initialize SpellcheckWordIterator";
juliusa99884d892015-08-15 02:49:1969 return IS_CORRECT;
[email protected]e2dc7a92013-01-23 22:19:2470 }
71
juliusa99884d892015-08-15 02:49:1972 text_iterator_.SetText(text_begin + position_in_text, remaining_text_len);
Zinovy Nis701103b2018-05-10 22:59:3873 DCHECK(platform_spelling_engine_);
juliusa4f336a62015-08-13 01:36:4274 for (SpellcheckWordIterator::WordIteratorStatus status =
75 text_iterator_.GetNextWord(&word, &word_start, &word_length);
76 status != SpellcheckWordIterator::IS_END_OF_TEXT;
77 status = text_iterator_.GetNextWord(&word, &word_start, &word_length)) {
juliusa99884d892015-08-15 02:49:1978 // Found a character that is not able to be spellchecked so determine how
79 // long the sequence of uncheckable characters is and then return.
80 if (status == SpellcheckWordIterator::IS_SKIPPABLE) {
81 *skip_or_misspelling_start = position_in_text + word_start;
82 while (status == SpellcheckWordIterator::IS_SKIPPABLE) {
83 *skip_or_misspelling_len += word_length;
84 status = text_iterator_.GetNextWord(&word, &word_start, &word_length);
85 }
86 return IS_SKIPPABLE;
87 }
juliusa4f336a62015-08-13 01:36:4288
[email protected]e2dc7a92013-01-23 22:19:2489 // Found a word (or a contraction) that the spellchecker can check the
90 // spelling of.
[email protected]9d379a72013-03-26 11:09:0491 if (platform_spelling_engine_->CheckSpelling(word, tag))
[email protected]e2dc7a92013-01-23 22:19:2492 continue;
93
94 // If the given word is a concatenated word of two or more valid words
95 // (e.g. "hello:hello"), we should treat it as a valid word.
96 if (IsValidContraction(word, tag))
97 continue;
98
juliusa99884d892015-08-15 02:49:1999 *skip_or_misspelling_start = position_in_text + word_start;
100 *skip_or_misspelling_len = word_length;
[email protected]e2dc7a92013-01-23 22:19:24101
102 // Get the list of suggested words.
[email protected]9d379a72013-03-26 11:09:04103 if (optional_suggestions) {
104 platform_spelling_engine_->FillSuggestionList(word,
105 optional_suggestions);
106 }
juliusa99884d892015-08-15 02:49:19107 return IS_MISSPELLED;
[email protected]e2dc7a92013-01-23 22:19:24108 }
109
juliusa99884d892015-08-15 02:49:19110 return IS_CORRECT;
[email protected]e2dc7a92013-01-23 22:19:24111}
112
[email protected]e2dc7a92013-01-23 22:19:24113// Returns whether or not the given string is a valid contraction.
114// This function is a fall-back when the SpellcheckWordIterator class
115// returns a concatenated word which is not in the selected dictionary
116// (e.g. "in'n'out") but each word is valid.
[email protected]12469f92013-12-04 22:50:07117bool SpellcheckLanguage::IsValidContraction(const base::string16& contraction,
[email protected]e2dc7a92013-01-23 22:19:24118 int tag) {
119 if (!contraction_iterator_.IsInitialized() &&
120 !contraction_iterator_.Initialize(&character_attributes_, false)) {
121 // We failed to initialize the word iterator, return as spelled correctly.
122 VLOG(1) << "Failed to initialize contraction_iterator_";
123 return true;
124 }
125
126 contraction_iterator_.SetText(contraction.c_str(), contraction.length());
127
[email protected]12469f92013-12-04 22:50:07128 base::string16 word;
[email protected]e2dc7a92013-01-23 22:19:24129 int word_start;
130 int word_length;
[email protected]9d379a72013-03-26 11:09:04131
Zinovy Nis701103b2018-05-10 22:59:38132 DCHECK(platform_spelling_engine_);
juliusa4f336a62015-08-13 01:36:42133 for (SpellcheckWordIterator::WordIteratorStatus status =
134 contraction_iterator_.GetNextWord(&word, &word_start, &word_length);
135 status != SpellcheckWordIterator::IS_END_OF_TEXT;
136 status = contraction_iterator_.GetNextWord(&word, &word_start,
137 &word_length)) {
138 if (status == SpellcheckWordIterator::IS_SKIPPABLE)
139 continue;
140
[email protected]9d379a72013-03-26 11:09:04141 if (!platform_spelling_engine_->CheckSpelling(word, tag))
[email protected]e2dc7a92013-01-23 22:19:24142 return false;
143 }
144 return true;
145}
146
147bool SpellcheckLanguage::IsEnabled() {
Zinovy Nis701103b2018-05-10 22:59:38148 DCHECK(platform_spelling_engine_);
[email protected]e2dc7a92013-01-23 22:19:24149 return platform_spelling_engine_->IsEnabled();
150}