OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 #include "chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h" | 5 #include "chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h" |
6 | 6 |
7 #include "base/files/file_util.h" | 7 #include "base/files/file_util.h" |
8 #include "base/files/memory_mapped_file.h" | 8 #include "base/files/memory_mapped_file.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "net/url_request/url_request_context_getter.h" | 21 #include "net/url_request/url_request_context_getter.h" |
22 #include "third_party/hunspell/google/bdict.h" | 22 #include "third_party/hunspell/google/bdict.h" |
23 #include "url/gurl.h" | 23 #include "url/gurl.h" |
24 | 24 |
25 using content::BrowserThread; | 25 using content::BrowserThread; |
26 | 26 |
27 namespace { | 27 namespace { |
28 | 28 |
29 // Close the file. | 29 // Close the file. |
30 void CloseDictionary(base::File file) { | 30 void CloseDictionary(base::File file) { |
31 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 31 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
32 file.Close(); | 32 file.Close(); |
33 } | 33 } |
34 | 34 |
35 // Saves |data| to file at |path|. Returns true on successful save, otherwise | 35 // Saves |data| to file at |path|. Returns true on successful save, otherwise |
36 // returns false. | 36 // returns false. |
37 bool SaveDictionaryData(scoped_ptr<std::string> data, | 37 bool SaveDictionaryData(scoped_ptr<std::string> data, |
38 const base::FilePath& path) { | 38 const base::FilePath& path) { |
39 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 39 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
40 | 40 |
41 size_t bytes_written = | 41 size_t bytes_written = |
42 base::WriteFile(path, data->data(), data->length()); | 42 base::WriteFile(path, data->data(), data->length()); |
43 if (bytes_written != data->length()) { | 43 if (bytes_written != data->length()) { |
44 bool success = false; | 44 bool success = false; |
45 #if defined(OS_WIN) | 45 #if defined(OS_WIN) |
46 base::FilePath dict_dir; | 46 base::FilePath dict_dir; |
47 PathService::Get(chrome::DIR_USER_DATA, &dict_dir); | 47 PathService::Get(chrome::DIR_USER_DATA, &dict_dir); |
48 base::FilePath fallback_file_path = | 48 base::FilePath fallback_file_path = |
49 dict_dir.Append(path.BaseName()); | 49 dict_dir.Append(path.BaseName()); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 request_context_getter_(request_context_getter), | 99 request_context_getter_(request_context_getter), |
100 spellcheck_service_(spellcheck_service), | 100 spellcheck_service_(spellcheck_service), |
101 download_status_(DOWNLOAD_NONE), | 101 download_status_(DOWNLOAD_NONE), |
102 weak_ptr_factory_(this) { | 102 weak_ptr_factory_(this) { |
103 } | 103 } |
104 | 104 |
105 SpellcheckHunspellDictionary::~SpellcheckHunspellDictionary() { | 105 SpellcheckHunspellDictionary::~SpellcheckHunspellDictionary() { |
106 } | 106 } |
107 | 107 |
108 void SpellcheckHunspellDictionary::Load() { | 108 void SpellcheckHunspellDictionary::Load() { |
109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 109 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
110 | 110 |
111 #if defined(OS_MACOSX) | 111 #if defined(OS_MACOSX) |
112 if (spellcheck_mac::SpellCheckerAvailable() && | 112 if (spellcheck_mac::SpellCheckerAvailable() && |
113 spellcheck_mac::PlatformSupportsLanguage(language_)) { | 113 spellcheck_mac::PlatformSupportsLanguage(language_)) { |
114 use_platform_spellchecker_ = true; | 114 use_platform_spellchecker_ = true; |
115 spellcheck_mac::SetLanguage(language_); | 115 spellcheck_mac::SetLanguage(language_); |
116 base::MessageLoop::current()->PostTask(FROM_HERE, | 116 base::MessageLoop::current()->PostTask(FROM_HERE, |
117 base::Bind( | 117 base::Bind( |
118 &SpellcheckHunspellDictionary::InformListenersOfInitialization, | 118 &SpellcheckHunspellDictionary::InformListenersOfInitialization, |
119 weak_ptr_factory_.GetWeakPtr())); | 119 weak_ptr_factory_.GetWeakPtr())); |
120 return; | 120 return; |
121 } | 121 } |
122 #endif // OS_MACOSX | 122 #endif // OS_MACOSX |
123 | 123 |
124 BrowserThread::PostTaskAndReplyWithResult( | 124 BrowserThread::PostTaskAndReplyWithResult( |
125 BrowserThread::FILE, | 125 BrowserThread::FILE, |
126 FROM_HERE, | 126 FROM_HERE, |
127 base::Bind(&InitializeDictionaryLocation, language_), | 127 base::Bind(&InitializeDictionaryLocation, language_), |
128 base::Bind( | 128 base::Bind( |
129 &SpellcheckHunspellDictionary::InitializeDictionaryLocationComplete, | 129 &SpellcheckHunspellDictionary::InitializeDictionaryLocationComplete, |
130 weak_ptr_factory_.GetWeakPtr())); | 130 weak_ptr_factory_.GetWeakPtr())); |
131 } | 131 } |
132 | 132 |
133 void SpellcheckHunspellDictionary::RetryDownloadDictionary( | 133 void SpellcheckHunspellDictionary::RetryDownloadDictionary( |
134 net::URLRequestContextGetter* request_context_getter) { | 134 net::URLRequestContextGetter* request_context_getter) { |
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 135 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
136 request_context_getter_ = request_context_getter; | 136 request_context_getter_ = request_context_getter; |
137 DownloadDictionary(GetDictionaryURL()); | 137 DownloadDictionary(GetDictionaryURL()); |
138 } | 138 } |
139 | 139 |
140 bool SpellcheckHunspellDictionary::IsReady() const { | 140 bool SpellcheckHunspellDictionary::IsReady() const { |
141 return GetDictionaryFile().IsValid() || IsUsingPlatformChecker(); | 141 return GetDictionaryFile().IsValid() || IsUsingPlatformChecker(); |
142 } | 142 } |
143 | 143 |
144 const base::File& SpellcheckHunspellDictionary::GetDictionaryFile() const { | 144 const base::File& SpellcheckHunspellDictionary::GetDictionaryFile() const { |
145 return dictionary_file_.file; | 145 return dictionary_file_.file; |
146 } | 146 } |
147 | 147 |
148 const std::string& SpellcheckHunspellDictionary::GetLanguage() const { | 148 const std::string& SpellcheckHunspellDictionary::GetLanguage() const { |
149 return language_; | 149 return language_; |
150 } | 150 } |
151 | 151 |
152 bool SpellcheckHunspellDictionary::IsUsingPlatformChecker() const { | 152 bool SpellcheckHunspellDictionary::IsUsingPlatformChecker() const { |
153 return use_platform_spellchecker_; | 153 return use_platform_spellchecker_; |
154 } | 154 } |
155 | 155 |
156 void SpellcheckHunspellDictionary::AddObserver(Observer* observer) { | 156 void SpellcheckHunspellDictionary::AddObserver(Observer* observer) { |
157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 157 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
158 observers_.AddObserver(observer); | 158 observers_.AddObserver(observer); |
159 } | 159 } |
160 | 160 |
161 void SpellcheckHunspellDictionary::RemoveObserver(Observer* observer) { | 161 void SpellcheckHunspellDictionary::RemoveObserver(Observer* observer) { |
162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 162 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
163 observers_.RemoveObserver(observer); | 163 observers_.RemoveObserver(observer); |
164 } | 164 } |
165 | 165 |
166 bool SpellcheckHunspellDictionary::IsDownloadInProgress() { | 166 bool SpellcheckHunspellDictionary::IsDownloadInProgress() { |
167 return download_status_ == DOWNLOAD_IN_PROGRESS; | 167 return download_status_ == DOWNLOAD_IN_PROGRESS; |
168 } | 168 } |
169 | 169 |
170 bool SpellcheckHunspellDictionary::IsDownloadFailure() { | 170 bool SpellcheckHunspellDictionary::IsDownloadFailure() { |
171 return download_status_ == DOWNLOAD_FAILED; | 171 return download_status_ == DOWNLOAD_FAILED; |
172 } | 172 } |
173 | 173 |
174 void SpellcheckHunspellDictionary::OnURLFetchComplete( | 174 void SpellcheckHunspellDictionary::OnURLFetchComplete( |
175 const net::URLFetcher* source) { | 175 const net::URLFetcher* source) { |
176 DCHECK(source); | 176 DCHECK(source); |
177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 177 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
178 scoped_ptr<net::URLFetcher> fetcher_destructor(fetcher_.release()); | 178 scoped_ptr<net::URLFetcher> fetcher_destructor(fetcher_.release()); |
179 | 179 |
180 if ((source->GetResponseCode() / 100) != 2) { | 180 if ((source->GetResponseCode() / 100) != 2) { |
181 // Initialize will not try to download the file a second time. | 181 // Initialize will not try to download the file a second time. |
182 InformListenersOfDownloadFailure(); | 182 InformListenersOfDownloadFailure(); |
183 return; | 183 return; |
184 } | 184 } |
185 | 185 |
186 // Basic sanity check on the dictionary. There's a small chance of 200 status | 186 // Basic sanity check on the dictionary. There's a small chance of 200 status |
187 // code for a body that represents some form of failure. | 187 // code for a body that represents some form of failure. |
(...skipping 29 matching lines...) Expand all Loading... |
217 "http://cache.pack.google.com/edgedl/chrome/dict/"; | 217 "http://cache.pack.google.com/edgedl/chrome/dict/"; |
218 std::string bdict_file = dictionary_file_.path.BaseName().MaybeAsASCII(); | 218 std::string bdict_file = dictionary_file_.path.BaseName().MaybeAsASCII(); |
219 | 219 |
220 DCHECK(!bdict_file.empty()); | 220 DCHECK(!bdict_file.empty()); |
221 | 221 |
222 return GURL(std::string(kDownloadServerUrl) + | 222 return GURL(std::string(kDownloadServerUrl) + |
223 base::StringToLowerASCII(bdict_file)); | 223 base::StringToLowerASCII(bdict_file)); |
224 } | 224 } |
225 | 225 |
226 void SpellcheckHunspellDictionary::DownloadDictionary(GURL url) { | 226 void SpellcheckHunspellDictionary::DownloadDictionary(GURL url) { |
227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 227 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
228 DCHECK(request_context_getter_); | 228 DCHECK(request_context_getter_); |
229 | 229 |
230 download_status_ = DOWNLOAD_IN_PROGRESS; | 230 download_status_ = DOWNLOAD_IN_PROGRESS; |
231 FOR_EACH_OBSERVER(Observer, observers_, OnHunspellDictionaryDownloadBegin()); | 231 FOR_EACH_OBSERVER(Observer, observers_, OnHunspellDictionaryDownloadBegin()); |
232 | 232 |
233 fetcher_.reset(net::URLFetcher::Create(url, net::URLFetcher::GET, this)); | 233 fetcher_.reset(net::URLFetcher::Create(url, net::URLFetcher::GET, this)); |
234 fetcher_->SetRequestContext(request_context_getter_); | 234 fetcher_->SetRequestContext(request_context_getter_); |
235 fetcher_->SetLoadFlags( | 235 fetcher_->SetLoadFlags( |
236 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); | 236 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); |
237 fetcher_->Start(); | 237 fetcher_->Start(); |
238 // Attempt downloading the dictionary only once. | 238 // Attempt downloading the dictionary only once. |
239 request_context_getter_ = NULL; | 239 request_context_getter_ = NULL; |
240 } | 240 } |
241 | 241 |
242 // The default_dictionary_file can either come from the standard list of | 242 // The default_dictionary_file can either come from the standard list of |
243 // hunspell dictionaries (determined in InitializeDictionaryLocation), or it | 243 // hunspell dictionaries (determined in InitializeDictionaryLocation), or it |
244 // can be passed in via an extension. In either case, the file is checked for | 244 // can be passed in via an extension. In either case, the file is checked for |
245 // existence so that it's not re-downloaded. | 245 // existence so that it's not re-downloaded. |
246 // For systemwide installations on Windows, the default directory may not | 246 // For systemwide installations on Windows, the default directory may not |
247 // have permissions for download. In that case, the alternate directory for | 247 // have permissions for download. In that case, the alternate directory for |
248 // download is chrome::DIR_USER_DATA. | 248 // download is chrome::DIR_USER_DATA. |
249 SpellcheckHunspellDictionary::DictionaryFile | 249 SpellcheckHunspellDictionary::DictionaryFile |
250 SpellcheckHunspellDictionary::OpenDictionaryFile(const base::FilePath& path) { | 250 SpellcheckHunspellDictionary::OpenDictionaryFile(const base::FilePath& path) { |
251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 251 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
252 DictionaryFile dictionary; | 252 DictionaryFile dictionary; |
253 | 253 |
254 #if defined(OS_WIN) | 254 #if defined(OS_WIN) |
255 // Check if the dictionary exists in the fallback location. If so, use it | 255 // Check if the dictionary exists in the fallback location. If so, use it |
256 // rather than downloading anew. | 256 // rather than downloading anew. |
257 base::FilePath user_dir; | 257 base::FilePath user_dir; |
258 PathService::Get(chrome::DIR_USER_DATA, &user_dir); | 258 PathService::Get(chrome::DIR_USER_DATA, &user_dir); |
259 base::FilePath fallback = user_dir.Append(path.BaseName()); | 259 base::FilePath fallback = user_dir.Append(path.BaseName()); |
260 if (!base::PathExists(path) && base::PathExists(fallback)) | 260 if (!base::PathExists(path) && base::PathExists(fallback)) |
261 dictionary.path = fallback; | 261 dictionary.path = fallback; |
(...skipping 22 matching lines...) Expand all Loading... |
284 } | 284 } |
285 | 285 |
286 return dictionary.Pass(); | 286 return dictionary.Pass(); |
287 } | 287 } |
288 | 288 |
289 // The default place where the spellcheck dictionary resides is | 289 // The default place where the spellcheck dictionary resides is |
290 // chrome::DIR_APP_DICTIONARIES. | 290 // chrome::DIR_APP_DICTIONARIES. |
291 SpellcheckHunspellDictionary::DictionaryFile | 291 SpellcheckHunspellDictionary::DictionaryFile |
292 SpellcheckHunspellDictionary::InitializeDictionaryLocation( | 292 SpellcheckHunspellDictionary::InitializeDictionaryLocation( |
293 const std::string& language) { | 293 const std::string& language) { |
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 294 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
295 | 295 |
296 // Initialize the BDICT path. Initialization should be in the FILE thread | 296 // Initialize the BDICT path. Initialization should be in the FILE thread |
297 // because it checks if there is a "Dictionaries" directory and create it. | 297 // because it checks if there is a "Dictionaries" directory and create it. |
298 base::FilePath dict_dir; | 298 base::FilePath dict_dir; |
299 PathService::Get(chrome::DIR_APP_DICTIONARIES, &dict_dir); | 299 PathService::Get(chrome::DIR_APP_DICTIONARIES, &dict_dir); |
300 base::FilePath dict_path = | 300 base::FilePath dict_path = |
301 chrome::spellcheck_common::GetVersionedFileName(language, dict_dir); | 301 chrome::spellcheck_common::GetVersionedFileName(language, dict_dir); |
302 | 302 |
303 return OpenDictionaryFile(dict_path); | 303 return OpenDictionaryFile(dict_path); |
304 } | 304 } |
305 | 305 |
306 void SpellcheckHunspellDictionary::InitializeDictionaryLocationComplete( | 306 void SpellcheckHunspellDictionary::InitializeDictionaryLocationComplete( |
307 DictionaryFile file) { | 307 DictionaryFile file) { |
308 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 308 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
309 dictionary_file_ = file.Pass(); | 309 dictionary_file_ = file.Pass(); |
310 | 310 |
311 if (!dictionary_file_.file.IsValid()) { | 311 if (!dictionary_file_.file.IsValid()) { |
312 | 312 |
313 // Notify browser tests that this dictionary is corrupted. Skip downloading | 313 // Notify browser tests that this dictionary is corrupted. Skip downloading |
314 // the dictionary in browser tests. | 314 // the dictionary in browser tests. |
315 // TODO(rouslan): Remove this test-only case. | 315 // TODO(rouslan): Remove this test-only case. |
316 if (spellcheck_service_->SignalStatusEvent( | 316 if (spellcheck_service_->SignalStatusEvent( |
317 SpellcheckService::BDICT_CORRUPTED)) { | 317 SpellcheckService::BDICT_CORRUPTED)) { |
318 request_context_getter_ = NULL; | 318 request_context_getter_ = NULL; |
319 } | 319 } |
320 | 320 |
321 if (request_context_getter_) { | 321 if (request_context_getter_) { |
322 // Download from the UI thread to check that |request_context_getter_| is | 322 // Download from the UI thread to check that |request_context_getter_| is |
323 // still valid. | 323 // still valid. |
324 DownloadDictionary(GetDictionaryURL()); | 324 DownloadDictionary(GetDictionaryURL()); |
325 return; | 325 return; |
326 } | 326 } |
327 } | 327 } |
328 | 328 |
329 InformListenersOfInitialization(); | 329 InformListenersOfInitialization(); |
330 } | 330 } |
331 | 331 |
332 void SpellcheckHunspellDictionary::SaveDictionaryDataComplete( | 332 void SpellcheckHunspellDictionary::SaveDictionaryDataComplete( |
333 bool dictionary_saved) { | 333 bool dictionary_saved) { |
334 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 334 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
335 | 335 |
336 if (dictionary_saved) { | 336 if (dictionary_saved) { |
337 download_status_ = DOWNLOAD_NONE; | 337 download_status_ = DOWNLOAD_NONE; |
338 FOR_EACH_OBSERVER(Observer, | 338 FOR_EACH_OBSERVER(Observer, |
339 observers_, | 339 observers_, |
340 OnHunspellDictionaryDownloadSuccess()); | 340 OnHunspellDictionaryDownloadSuccess()); |
341 Load(); | 341 Load(); |
342 } else { | 342 } else { |
343 InformListenersOfDownloadFailure(); | 343 InformListenersOfDownloadFailure(); |
344 InformListenersOfInitialization(); | 344 InformListenersOfInitialization(); |
345 } | 345 } |
346 } | 346 } |
347 | 347 |
348 void SpellcheckHunspellDictionary::InformListenersOfInitialization() { | 348 void SpellcheckHunspellDictionary::InformListenersOfInitialization() { |
349 FOR_EACH_OBSERVER(Observer, observers_, OnHunspellDictionaryInitialized()); | 349 FOR_EACH_OBSERVER(Observer, observers_, OnHunspellDictionaryInitialized()); |
350 } | 350 } |
351 | 351 |
352 void SpellcheckHunspellDictionary::InformListenersOfDownloadFailure() { | 352 void SpellcheckHunspellDictionary::InformListenersOfDownloadFailure() { |
353 download_status_ = DOWNLOAD_FAILED; | 353 download_status_ = DOWNLOAD_FAILED; |
354 FOR_EACH_OBSERVER(Observer, | 354 FOR_EACH_OBSERVER(Observer, |
355 observers_, | 355 observers_, |
356 OnHunspellDictionaryDownloadFailure()); | 356 OnHunspellDictionaryDownloadFailure()); |
357 } | 357 } |
OLD | NEW |