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 |