1 // 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 5 #ifndef COMPONENTS_SPELLCHECK_RENDERER_SPELLCHECK_H_ 6 #define COMPONENTS_SPELLCHECK_RENDERER_SPELLCHECK_H_ 7 8 #include <memory> 9 #include <set> 10 #include <string> 11 #include <vector> 12 13 #include "base/files/file.h" 14 #include "base/gtest_prod_util.h" 15 #include "base/macros.h" 16 #include "base/memory/weak_ptr.h" 17 #include "base/observer_list.h" 18 #include "base/strings/string16.h" 19 #include "build/build_config.h" 20 #include "components/spellcheck/common/spellcheck.mojom.h" 21 #include "components/spellcheck/common/spellcheck_common.h" 22 #include "components/spellcheck/renderer/custom_dictionary_engine.h" 23 #include "components/spellcheck/spellcheck_buildflags.h" 24 #include "mojo/public/cpp/bindings/pending_receiver.h" 25 #include "mojo/public/cpp/bindings/receiver_set.h" 26 27 class SpellcheckLanguage; 28 struct SpellCheckResult; 29 30 namespace blink { 31 class WebTextCheckingCompletion; 32 struct WebTextCheckingResult; 33 template <typename T> class WebVector; 34 class WebString; 35 } 36 37 namespace service_manager { 38 class LocalInterfaceProvider; 39 } 40 41 class DictionaryUpdateObserver { 42 public: 43 virtual ~DictionaryUpdateObserver() = default; 44 // |words_added| is newly added words to dictionary as correct words. 45 // OnDictionaryUpdated should be called even if |words_added| empty. 46 virtual void OnDictionaryUpdated( 47 const blink::WebVector<blink::WebString>& words_added) = 0; 48 }; 49 50 // TODO(morrita): Needs reorg with SpellCheckProvider. 51 // See http://crbug.com/73699. 52 // Shared spellchecking logic/data for a RenderProcess. All RenderViews use 53 // this object to perform spellchecking tasks. 54 class SpellCheck : public base::SupportsWeakPtr<SpellCheck>, 55 public spellcheck::mojom::SpellChecker { 56 public: 57 // TODO(groby): I wonder if this can be private, non-mac only. 58 class SpellcheckRequest; 59 enum ResultFilter { 60 // Do not modify results. 61 DO_NOT_MODIFY = 1, 62 // Use Hunspell to double-check the results from the spelling service 63 // (enhanced spell check). If Hunspell doesn't find a mistake, it most 64 // likely means it was a grammar mistake, not a spelling mistake. 65 USE_HUNSPELL_FOR_GRAMMAR, 66 // Use Hunspell to double-check the results from the native spell checker 67 // for locales that it doesn't support. If Hunspell doesn't find a mistake, 68 // it means the misspelling was a false positive, since the word is 69 // correctly spelled in at least one locale. 70 USE_HUNSPELL_FOR_HYBRID_CHECK, 71 }; 72 73 explicit SpellCheck( 74 service_manager::LocalInterfaceProvider* embedder_provider); 75 ~SpellCheck() override; 76 77 void AddSpellcheckLanguage(base::File file, const std::string& language); 78 79 // If there are no dictionary files, then this requests them from the browser 80 // and does not block. In this case it returns true. 81 // If there are dictionary files, but their Hunspell has not been loaded, then 82 // this loads their Hunspell. 83 // If each dictionary file's Hunspell is already loaded, this does nothing. In 84 // both the latter cases it returns false, meaning that it is OK to continue 85 // spellchecking. 86 bool InitializeIfNeeded(); 87 88 // SpellCheck a word. 89 // Returns true if spelled correctly for any language in |languages_|, false 90 // otherwise. 91 // If any spellcheck languages failed to initialize, always returns true. 92 // The |tag| parameter should either be a unique identifier for the document 93 // that the word came from (if the current platform requires it), or 0. 94 // In addition, finds the suggested words for a given word 95 // and puts them into |*optional_suggestions|. 96 // If the word is spelled correctly, the vector is empty. 97 // If optional_suggestions is NULL, suggested words will not be looked up. 98 // Note that doing suggest lookups can be slow. 99 bool SpellCheckWord(const base::char16* text_begin, 100 size_t position_in_text, 101 size_t text_length, 102 int tag, 103 size_t* misspelling_start, 104 size_t* misspelling_len, 105 std::vector<base::string16>* optional_suggestions); 106 107 // Overload of SpellCheckWord where the replacement suggestions are kept 108 // separately per language, instead of combined into a single list. This is 109 // useful if the suggestions must be merged with another list of suggestions, 110 // for example in the case of the Windows hybrid spellchecker. 111 bool SpellCheckWord( 112 const base::char16* text_begin, 113 size_t position_in_text, 114 size_t text_length, 115 int tag, 116 size_t* misspelling_start, 117 size_t* misspelling_len, 118 spellcheck::PerLanguageSuggestions* optional_per_language_suggestions); 119 120 // Overload of SpellCheckWord for skipping optional suggestions with a 121 // nullptr, used to disambiguate between the other two overloads. 122 bool SpellCheckWord(const base::char16* text_begin, 123 size_t position_in_text, 124 size_t text_length, 125 int tag, 126 size_t* misspelling_start, 127 size_t* misspelling_len, 128 std::nullptr_t null_suggestions_ptr); 129 130 #if BUILDFLAG(USE_RENDERER_SPELLCHECKER) 131 // SpellCheck a paragraph. 132 // Returns true if |text| is correctly spelled, false otherwise. 133 // If the spellchecker failed to initialize, always returns true. 134 bool SpellCheckParagraph( 135 const base::string16& text, 136 blink::WebVector<blink::WebTextCheckingResult>* results); 137 138 // Requests to spellcheck the specified text in the background. This function 139 // posts a background task and calls SpellCheckParagraph() in the task. 140 void RequestTextChecking( 141 const base::string16& text, 142 std::unique_ptr<blink::WebTextCheckingCompletion> completion); 143 #endif 144 145 // Creates a list of WebTextCheckingResult objects (used by WebKit) from a 146 // list of SpellCheckResult objects (used by Chrome). This function also 147 // checks misspelled words returned by the Spelling service and changes the 148 // underline colors of contextually-misspelled words. 149 void CreateTextCheckingResults( 150 ResultFilter filter, 151 int line_offset, 152 const base::string16& line_text, 153 const std::vector<SpellCheckResult>& spellcheck_results, 154 blink::WebVector<blink::WebTextCheckingResult>* textcheck_results); 155 156 bool IsSpellcheckEnabled(); 157 158 // Add observer on dictionary update event. 159 void AddDictionaryUpdateObserver(DictionaryUpdateObserver* observer); 160 // Remove observer on dictionary update event. 161 void RemoveDictionaryUpdateObserver(DictionaryUpdateObserver* observer); 162 163 // Binds receivers for the SpellChecker interface. 164 void BindReceiver( 165 mojo::PendingReceiver<spellcheck::mojom::SpellChecker> receiver); 166 167 // Returns the current number of spell check languages. 168 // Overridden by tests in spellcheck_provider_test.cc (FakeSpellCheck class). 169 virtual size_t LanguageCount(); 170 171 // Returns the current number of spell check languages with enabled engines. 172 // Overridden by tests in spellcheck_provider_test.cc (FakeSpellCheck class). 173 virtual size_t EnabledLanguageCount(); 174 175 private: 176 friend class SpellCheckTest; 177 friend class FakeSpellCheck; 178 FRIEND_TEST_ALL_PREFIXES(SpellCheckTest, GetAutoCorrectionWord_EN_US); 179 FRIEND_TEST_ALL_PREFIXES(SpellCheckTest, 180 RequestSpellCheckMultipleTimesWithoutInitialization); 181 182 // spellcheck::mojom::SpellChecker: 183 void Initialize( 184 std::vector<spellcheck::mojom::SpellCheckBDictLanguagePtr> dictionaries, 185 const std::vector<std::string>& custom_words, 186 bool enable) override; 187 void CustomDictionaryChanged( 188 const std::vector<std::string>& words_added, 189 const std::vector<std::string>& words_removed) override; 190 191 // Performs dictionary update notification. 192 void NotifyDictionaryObservers( 193 const blink::WebVector<blink::WebString>& words_added); 194 195 #if BUILDFLAG(USE_RENDERER_SPELLCHECKER) 196 // Posts delayed spellcheck task and clear it if any. 197 // Takes ownership of |request|. 198 void PostDelayedSpellCheckTask(SpellcheckRequest* request); 199 200 // Performs spell checking from the request queue. 201 void PerformSpellCheck(SpellcheckRequest* request); 202 203 // The parameters of a pending background-spellchecking request. When WebKit 204 // sends a background-spellchecking request before initializing hunspell, 205 // we save its parameters and start spellchecking after we finish 206 // initializing hunspell. (When WebKit sends two or more requests, we cancel 207 // the previous requests so we do not have to use vectors.) 208 std::unique_ptr<SpellcheckRequest> pending_request_param_; 209 #endif 210 211 // Receivers for SpellChecker clients. 212 mojo::ReceiverSet<spellcheck::mojom::SpellChecker> receivers_; 213 214 // A vector of objects used to actually check spelling, one for each enabled 215 // language. 216 std::vector<std::unique_ptr<SpellcheckLanguage>> languages_; 217 218 // Custom dictionary spelling engine. 219 CustomDictionaryEngine custom_dictionary_; 220 221 service_manager::LocalInterfaceProvider* embedder_provider_; 222 223 // Remember state for spellchecking. 224 bool spellcheck_enabled_; 225 226 // Observers of update dictionary events. 227 base::ObserverList<DictionaryUpdateObserver>::Unchecked 228 dictionary_update_observers_; 229 230 base::WeakPtrFactory<SpellCheck> weak_factory_{this}; 231 232 DISALLOW_COPY_AND_ASSIGN(SpellCheck); 233 }; 234 235 #endif // COMPONENTS_SPELLCHECK_RENDERER_SPELLCHECK_H_ 236