| OLD | NEW |
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef CHROME_BROWSER_SPELLCHECKER_H_ | 5 #ifndef CHROME_RENDERER_SPELLCHECKER_SPELLCHECKER_H_ |
| 6 #define CHROME_BROWSER_SPELLCHECKER_H_ | 6 #define CHROME_RENDERER_SPELLCHECKER_SPELLCHECKER_H_ |
| 7 | 7 |
| 8 #include <queue> | 8 #include <queue> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "app/l10n_util.h" | 12 #include "app/l10n_util.h" |
| 13 #include "base/file_descriptor_posix.h" |
| 13 #include "base/string16.h" | 14 #include "base/string16.h" |
| 14 #include "base/task.h" | |
| 15 #include "base/time.h" | 15 #include "base/time.h" |
| 16 #include "chrome/browser/browser_process.h" | 16 #include "chrome/renderer/spellchecker/spellcheck_worditerator.h" |
| 17 #include "chrome/browser/net/url_fetcher.h" | |
| 18 #include "chrome/browser/profile.h" | |
| 19 #include "chrome/browser/spellcheck_worditerator.h" | |
| 20 #include "chrome/common/pref_names.h" | |
| 21 #include "chrome/common/pref_member.h" | |
| 22 #include "unicode/uscript.h" | 17 #include "unicode/uscript.h" |
| 23 | 18 |
| 24 class FilePath; | |
| 25 class Hunspell; | 19 class Hunspell; |
| 26 class PrefService; | 20 |
| 27 class Profile; | 21 namespace base { |
| 28 class MessageLoop; | 22 class FileDescriptor; |
| 29 class URLFetcher; | 23 } |
| 30 class URLRequestContextGetter; | |
| 31 | 24 |
| 32 namespace file_util { | 25 namespace file_util { |
| 33 class MemoryMappedFile; | 26 class MemoryMappedFile; |
| 34 } | 27 } |
| 35 | 28 |
| 36 // The Browser's Spell Checker. It checks and suggests corrections. | 29 class SpellCheck { |
| 37 // | |
| 38 // This object is not threadsafe. In normal usage (not unit tests) it lives on | |
| 39 // the I/O thread of the browser. It is threadsafe refcounted so that I/O thread | |
| 40 // and the profile on the main thread (which gives out references to it) can | |
| 41 // keep it. However, all usage of this must be on the I/O thread. | |
| 42 // | |
| 43 // This object should also be deleted on the I/O thread only. It owns a | |
| 44 // reference to URLRequestContext which in turn owns the cache, etc. and must be | |
| 45 // deleted on the I/O thread itself. | |
| 46 class SpellChecker : public base::RefCountedThreadSafe<SpellChecker>, | |
| 47 public URLFetcher::Delegate { | |
| 48 public: | 30 public: |
| 49 // Creates the spellchecker by reading dictionaries from the given directory, | 31 SpellCheck(); |
| 50 // and defaulting to the given language. Both strings must be provided. | |
| 51 // | |
| 52 // The request context is used to download dictionaries if they do not exist. | |
| 53 // This can be NULL if you don't want this (like in tests). | |
| 54 // The |custom_dictionary_file_name| should be left blank so that Spellchecker | |
| 55 // can figure out the custom dictionary file. It is non empty only for unit | |
| 56 // testing. | |
| 57 SpellChecker(const FilePath& dict_dir, | |
| 58 const std::string& language, | |
| 59 URLRequestContextGetter* request_context_getter, | |
| 60 const FilePath& custom_dictionary_file_name); | |
| 61 | 32 |
| 62 // Only delete on the I/O thread (see above). | 33 ~SpellCheck(); |
| 63 ~SpellChecker(); | 34 |
| 35 void Init(const base::FileDescriptor& bdict_fd, |
| 36 const std::vector<std::string>& custom_words, |
| 37 const std::string language); |
| 64 | 38 |
| 65 // SpellCheck a word. | 39 // SpellCheck a word. |
| 66 // Returns true if spelled correctly, false otherwise. | 40 // Returns true if spelled correctly, false otherwise. |
| 67 // If the spellchecker failed to initialize, always returns true. | 41 // If the spellchecker failed to initialize, always returns true. |
| 68 // The |tag| parameter should either be a unique identifier for the document | 42 // The |tag| parameter should either be a unique identifier for the document |
| 69 // that the word came from (if the current platform requires it), or 0. | 43 // that the word came from (if the current platform requires it), or 0. |
| 70 // In addition, finds the suggested words for a given word | 44 // In addition, finds the suggested words for a given word |
| 71 // and puts them into |*optional_suggestions|. | 45 // and puts them into |*optional_suggestions|. |
| 72 // If the word is spelled correctly, the vector is empty. | 46 // If the word is spelled correctly, the vector is empty. |
| 73 // If optional_suggestions is NULL, suggested words will not be looked up. | 47 // If optional_suggestions is NULL, suggested words will not be looked up. |
| 74 // Note that Doing suggest lookups can be slow. | 48 // Note that Doing suggest lookups can be slow. |
| 75 bool SpellCheckWord(const char16* in_word, | 49 bool SpellCheckWord(const char16* in_word, |
| 76 int in_word_len, | 50 int in_word_len, |
| 77 int tag, | 51 int tag, |
| 78 int* misspelling_start, | 52 int* misspelling_start, |
| 79 int* misspelling_len, | 53 int* misspelling_len, |
| 80 std::vector<string16>* optional_suggestions); | 54 std::vector<string16>* optional_suggestions); |
| 81 | 55 |
| 82 // Find a possible correctly spelled word for a misspelled word. Computes an | 56 // Find a possible correctly spelled word for a misspelled word. Computes an |
| 83 // empty string if input misspelled word is too long, there is ambiguity, or | 57 // empty string if input misspelled word is too long, there is ambiguity, or |
| 84 // the correct spelling cannot be determined. | 58 // the correct spelling cannot be determined. |
| 85 string16 GetAutoCorrectionWord(const string16& word, int tag); | 59 string16 GetAutoCorrectionWord(const string16& word, int tag); |
| 86 | 60 |
| 87 // Turn auto spell correct support ON or OFF. | 61 // Turn auto spell correct support ON or OFF. |
| 88 // |turn_on| = true means turn ON; false means turn OFF. | 62 // |turn_on| = true means turn ON; false means turn OFF. |
| 89 void EnableAutoSpellCorrect(bool turn_on); | 63 void EnableAutoSpellCorrect(bool turn_on); |
| 90 | 64 |
| 91 // Add custom word to the dictionary, which means: | 65 // Add a word to the custom list. This may be called before or after |
| 92 // a) Add it to the current hunspell object for immediate use, | 66 // |hunspell_| has been initialized. |
| 93 // b) Add the word to a file in disk for custom dictionary. | 67 void WordAdded(const std::string& word); |
| 94 void AddWord(const string16& word); | |
| 95 | |
| 96 // Get SpellChecker supported languages. | |
| 97 static void SpellCheckLanguages(std::vector<std::string>* languages); | |
| 98 | |
| 99 // This function computes a vector of strings which are to be displayed in | |
| 100 // the context menu over a text area for changing spell check languages. It | |
| 101 // returns the index of the current spell check language in the vector. | |
| 102 // TODO(port): this should take a vector of string16, but the implementation | |
| 103 // has some dependencies in l10n util that need porting first. | |
| 104 static int GetSpellCheckLanguages( | |
| 105 Profile* profile, | |
| 106 std::vector<std::string>* languages); | |
| 107 | |
| 108 // This function returns the corresponding language-region code for the | |
| 109 // spell check language. For example, for hi, it returns hi-IN. | |
| 110 static std::string GetSpellCheckLanguageRegion(std::string input_language); | |
| 111 | |
| 112 // This function returns ll (language code) from ll-RR where 'RR' (region | |
| 113 // code) is redundant. However, if the region code matters, it's preserved. | |
| 114 // That is, it returns 'hi' and 'en-GB' for 'hi-IN' and 'en-GB' respectively. | |
| 115 static std::string GetLanguageFromLanguageRegion(std::string input_language); | |
| 116 | 68 |
| 117 private: | 69 private: |
| 118 friend class ReadDictionaryTask; | 70 // Initializes the Hunspell dictionary, or does nothing if |hunspell_| is |
| 71 // non-null. This blocks. |
| 72 void InitializeHunspell(); |
| 119 | 73 |
| 120 // URLFetcher::Delegate implementation. Called when we finish downloading the | 74 // If there is no dictionary file, then this requests one from the browser |
| 121 // spellcheck dictionary; saves the dictionary to disk. | 75 // and does not block. In this case it returns true. |
| 122 virtual void OnURLFetchComplete(const URLFetcher* source, | 76 // If there is a dictionary file, but Hunspell has not been loaded, then |
| 123 const GURL& url, | 77 // this loads Hunspell. |
| 124 const URLRequestStatus& status, | 78 // If Hunspell is already loaded, this does nothing. In both the latter cases |
| 125 int response_code, | 79 // it returns false, meaning that it is OK to continue spellchecking. |
| 126 const ResponseCookies& cookies, | 80 bool InitializeIfNeeded(); |
| 127 const std::string& data); | |
| 128 | 81 |
| 129 // When called, relays the request to check the spelling to the proper | 82 // When called, relays the request to check the spelling to the proper |
| 130 // backend, either hunspell or a platform-specific backend. | 83 // backend, either hunspell or a platform-specific backend. |
| 131 bool CheckSpelling(const string16& word_to_check, int tag); | 84 bool CheckSpelling(const string16& word_to_check, int tag); |
| 132 | 85 |
| 133 // When called, relays the request to fill the list with suggestions to | 86 // When called, relays the request to fill the list with suggestions to |
| 134 // the proper backend, either hunspell or a platform-specific backend. | 87 // the proper backend, either hunspell or a platform-specific backend. |
| 135 void FillSuggestionList(const string16& wrong_word, | 88 void FillSuggestionList(const string16& wrong_word, |
| 136 std::vector<string16>* optional_suggestions); | 89 std::vector<string16>* optional_suggestions); |
| 137 | 90 |
| 138 // Initializes the Hunspell Dictionary. | |
| 139 bool Initialize(); | |
| 140 | |
| 141 // Called when |hunspell| is done loading, succesfully or not. If |hunspell| | |
| 142 // and |bdict_file| are non-NULL, assume ownership. | |
| 143 void HunspellInited(Hunspell* hunspell, | |
| 144 file_util::MemoryMappedFile* bdict_file, | |
| 145 bool file_existed); | |
| 146 | |
| 147 // Either start downloading a dictionary if we have not already, or do nothing | |
| 148 // if we have already tried to download one. | |
| 149 void DoDictionaryDownload(); | |
| 150 | |
| 151 // Returns whether or not the given word is a contraction of valid words | 91 // Returns whether or not the given word is a contraction of valid words |
| 152 // (e.g. "word:word"). | 92 // (e.g. "word:word"). |
| 153 bool IsValidContraction(const string16& word, int tag); | 93 bool IsValidContraction(const string16& word, int tag); |
| 154 | 94 |
| 155 // Return the file name of the dictionary, including the path and the version | 95 // Add the given custom word to |hunspell_|. |
| 156 // numbers. | 96 void AddWordToHunspell(const std::string& word); |
| 157 FilePath GetVersionedFileName(const std::string& language, | |
| 158 const FilePath& dict_dir); | |
| 159 | |
| 160 static std::string GetCorrespondingSpellCheckLanguage( | |
| 161 const std::string& language); | |
| 162 | |
| 163 // Start downloading a dictionary from the server. On completion, the | |
| 164 // OnURLFetchComplete() function is invoked. | |
| 165 void StartDictionaryDownload(const FilePath& file_name); | |
| 166 | |
| 167 // This method is called in the IO thread after dictionary download has | |
| 168 // completed in FILE thread. | |
| 169 void OnDictionarySaveComplete(); | |
| 170 | |
| 171 // The given path to the directory whether SpellChecker first tries to | |
| 172 // download the spellcheck bdic dictionary file. | |
| 173 FilePath given_dictionary_directory_; | |
| 174 | |
| 175 // Path to the custom dictionary file. | |
| 176 FilePath custom_dictionary_file_name_; | |
| 177 | |
| 178 // BDIC file name (e.g. en-US_1_1.bdic). | |
| 179 FilePath bdic_file_name_; | |
| 180 | 97 |
| 181 // We memory-map the BDict file. | 98 // We memory-map the BDict file. |
| 182 scoped_ptr<file_util::MemoryMappedFile> bdict_file_; | 99 scoped_ptr<file_util::MemoryMappedFile> bdict_file_; |
| 183 | 100 |
| 184 // The hunspell dictionary in use. | 101 // The hunspell dictionary in use. |
| 185 scoped_ptr<Hunspell> hunspell_; | 102 scoped_ptr<Hunspell> hunspell_; |
| 186 | 103 |
| 104 base::FileDescriptor fd_; |
| 105 std::vector<std::string> custom_words_; |
| 106 |
| 187 // Represents character attributes used for filtering out characters which | 107 // Represents character attributes used for filtering out characters which |
| 188 // are not supported by this SpellChecker object. | 108 // are not supported by this SpellCheck object. |
| 189 SpellcheckCharAttribute character_attributes_; | 109 SpellcheckCharAttribute character_attributes_; |
| 190 | 110 |
| 191 // Flag indicating whether we've tried to initialize. If we've already | |
| 192 // attempted initialiation, we won't retry to avoid failure loops. | |
| 193 bool tried_to_init_; | |
| 194 | |
| 195 // The language that this spellchecker works in. | |
| 196 std::string language_; | |
| 197 | |
| 198 // This object must only be used on the same thread. However, it is normally | |
| 199 // created on the UI thread. This checks calls to SpellCheckWord and the | |
| 200 // destructor to make sure we're only ever running on the same thread. | |
| 201 // | |
| 202 // This will be NULL if it is not initialized yet (not initialized in the | |
| 203 // constructor since that's on a different thread). | |
| 204 MessageLoop* worker_loop_; | |
| 205 | |
| 206 // Flag indicating whether we tried to download the dictionary file. | |
| 207 bool tried_to_download_dictionary_file_; | |
| 208 | |
| 209 // File Thread Message Loop. | |
| 210 MessageLoop* file_loop_; | |
| 211 | |
| 212 // Used for requests. MAY BE NULL which means don't try to download. | |
| 213 URLRequestContextGetter* request_context_getter_; | |
| 214 | |
| 215 // True when we're downloading or saving a dictionary. | |
| 216 bool obtaining_dictionary_; | |
| 217 | |
| 218 // Remember state for auto spell correct. | 111 // Remember state for auto spell correct. |
| 219 bool auto_spell_correct_turned_on_; | 112 bool auto_spell_correct_turned_on_; |
| 220 | 113 |
| 221 // True if a platform-specific spellchecking engine is being used, | 114 // True if a platform-specific spellchecking engine is being used, |
| 222 // and False if hunspell is being used. | 115 // and False if hunspell is being used. |
| 223 bool is_using_platform_spelling_engine_; | 116 bool is_using_platform_spelling_engine_; |
| 224 | 117 |
| 225 // URLFetcher to download a file in memory. | 118 // This flags whether we have ever been initialized, or have asked the browser |
| 226 scoped_ptr<URLFetcher> fetcher_; | 119 // for a dictionary. The value indicates whether we should request a |
| 120 // dictionary from the browser when the render view asks us to check the |
| 121 // spelling of a word. |
| 122 bool initialized_; |
| 227 | 123 |
| 228 // While Hunspell is loading, we add any new custom words to this queue. | 124 DISALLOW_COPY_AND_ASSIGN(SpellCheck); |
| 229 // We will add them to |hunspell_| when it is done loading. | |
| 230 std::queue<std::string> custom_words_; | |
| 231 | |
| 232 // Used for generating callbacks to spellchecker, since spellchecker is a | |
| 233 // non-reference counted object. | |
| 234 ScopedRunnableMethodFactory<SpellChecker> method_factory_; | |
| 235 | |
| 236 DISALLOW_COPY_AND_ASSIGN(SpellChecker); | |
| 237 }; | 125 }; |
| 238 | 126 |
| 239 #endif // CHROME_BROWSER_SPELLCHECKER_H_ | 127 #endif // CHROME_RENDERER_SPELLCHECKER_SPELLCHECKER_H_ |
| OLD | NEW |