| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_host_impl.h" | 5 #include "chrome/browser/spellchecker/spellcheck_host_impl.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 SpellCheckProfileProvider* profile, | 83 SpellCheckProfileProvider* profile, |
| 84 const std::string& language, | 84 const std::string& language, |
| 85 net::URLRequestContextGetter* request_context_getter, | 85 net::URLRequestContextGetter* request_context_getter, |
| 86 SpellCheckHostMetrics* metrics) | 86 SpellCheckHostMetrics* metrics) |
| 87 : profile_(profile), | 87 : profile_(profile), |
| 88 language_(language), | 88 language_(language), |
| 89 file_(base::kInvalidPlatformFileValue), | 89 file_(base::kInvalidPlatformFileValue), |
| 90 tried_to_download_(false), | 90 tried_to_download_(false), |
| 91 use_platform_spellchecker_(false), | 91 use_platform_spellchecker_(false), |
| 92 request_context_getter_(request_context_getter), | 92 request_context_getter_(request_context_getter), |
| 93 metrics_(metrics) { | 93 metrics_(metrics), |
| 94 ALLOW_THIS_IN_INITIALIZER_LIST(service_task_factory_(this)) { |
| 94 DCHECK(profile_); | 95 DCHECK(profile_); |
| 95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 96 | 97 |
| 97 FilePath personal_file_directory; | 98 FilePath personal_file_directory; |
| 98 PathService::Get(chrome::DIR_USER_DATA, &personal_file_directory); | 99 PathService::Get(chrome::DIR_USER_DATA, &personal_file_directory); |
| 99 custom_dictionary_file_ = | 100 custom_dictionary_file_ = |
| 100 personal_file_directory.Append(chrome::kCustomDictionaryFileName); | 101 personal_file_directory.Append(chrome::kCustomDictionaryFileName); |
| 101 | 102 |
| 102 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, | 103 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
| 103 NotificationService::AllSources()); | 104 NotificationService::AllSources()); |
| 104 } | 105 } |
| 105 | 106 |
| 106 SpellCheckHostImpl::~SpellCheckHostImpl() { | 107 SpellCheckHostImpl::~SpellCheckHostImpl() { |
| 107 if (file_ != base::kInvalidPlatformFileValue) | 108 if (file_ != base::kInvalidPlatformFileValue) |
| 108 base::ClosePlatformFile(file_); | 109 base::ClosePlatformFile(file_); |
| 109 } | 110 } |
| 110 | 111 |
| 111 void SpellCheckHostImpl::Initialize() { | 112 void SpellCheckHostImpl::Initialize() { |
| 112 if (SpellCheckerPlatform::SpellCheckerAvailable() && | 113 if (SpellCheckerPlatform::SpellCheckerAvailable() && |
| 113 SpellCheckerPlatform::PlatformSupportsLanguage(language_)) { | 114 SpellCheckerPlatform::PlatformSupportsLanguage(language_)) { |
| 114 #if defined(OS_MACOSX) | 115 #if defined(OS_MACOSX) |
| 115 RecordSpellCheckStats(true, language_); | 116 RecordSpellCheckStats(true, language_); |
| 116 #endif | 117 #endif |
| 117 use_platform_spellchecker_ = true; | 118 use_platform_spellchecker_ = true; |
| 118 SpellCheckerPlatform::SetLanguage(language_); | 119 SpellCheckerPlatform::SetLanguage(language_); |
| 119 MessageLoop::current()->PostTask(FROM_HERE, | 120 MessageLoop::current()->PostTask(FROM_HERE, |
| 120 NewRunnableMethod(this, | 121 service_task_factory_.NewRunnableMethod( |
| 121 &SpellCheckHostImpl::InformProfileOfInitialization)); | 122 &SpellCheckHostImpl::InformProfileOfInitialization)); |
| 122 return; | 123 return; |
| 123 } | 124 } |
| 124 | 125 |
| 125 #if defined(OS_MACOSX) | 126 #if defined(OS_MACOSX) |
| 126 RecordSpellCheckStats(false, language_); | 127 RecordSpellCheckStats(false, language_); |
| 127 #endif | 128 #endif |
| 128 | 129 |
| 129 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 130 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 130 NewRunnableMethod(this, | 131 service_task_factory_.NewRunnableMethod( |
| 131 &SpellCheckHostImpl::InitializeDictionaryLocation)); | 132 &SpellCheckHostImpl::InitializeDictionaryLocation)); |
| 132 } | 133 } |
| 133 | 134 |
| 134 void SpellCheckHostImpl::UnsetProfile() { | 135 void SpellCheckHostImpl::UnsetProfile() { |
| 135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 136 | 137 |
| 137 profile_ = NULL; | 138 profile_ = NULL; |
| 138 request_context_getter_ = NULL; | 139 request_context_getter_ = NULL; |
| 139 fetcher_.reset(); | 140 fetcher_.reset(); |
| 140 registrar_.RemoveAll(); | 141 registrar_.RemoveAll(); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 167 GetLanguage(), | 168 GetLanguage(), |
| 168 prefs->GetBoolean(prefs::kEnableAutoSpellCorrect))); | 169 prefs->GetBoolean(prefs::kEnableAutoSpellCorrect))); |
| 169 } | 170 } |
| 170 | 171 |
| 171 void SpellCheckHostImpl::AddWord(const std::string& word) { | 172 void SpellCheckHostImpl::AddWord(const std::string& word) { |
| 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 173 | 174 |
| 174 if (profile_) | 175 if (profile_) |
| 175 profile_->CustomWordAddedLocally(word); | 176 profile_->CustomWordAddedLocally(word); |
| 176 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 177 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 177 NewRunnableMethod(this, | 178 service_task_factory_.NewRunnableMethod( |
| 178 &SpellCheckHostImpl::WriteWordToCustomDictionary, word)); | 179 &SpellCheckHostImpl::WriteWordToCustomDictionary, word)); |
| 179 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); | 180 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); |
| 180 !i.IsAtEnd(); i.Advance()) { | 181 !i.IsAtEnd(); i.Advance()) { |
| 181 i.GetCurrentValue()->Send(new SpellCheckMsg_WordAdded(word)); | 182 i.GetCurrentValue()->Send(new SpellCheckMsg_WordAdded(word)); |
| 182 } | 183 } |
| 183 } | 184 } |
| 184 | 185 |
| 185 void SpellCheckHostImpl::InitializeDictionaryLocation() { | 186 void SpellCheckHostImpl::InitializeDictionaryLocation() { |
| 186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 187 | 188 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 base::PLATFORM_FILE_READ | base::PLATFORM_FILE_OPEN, | 224 base::PLATFORM_FILE_READ | base::PLATFORM_FILE_OPEN, |
| 224 NULL, NULL); | 225 NULL, NULL); |
| 225 } | 226 } |
| 226 | 227 |
| 227 // File didn't exist. Download it. | 228 // File didn't exist. Download it. |
| 228 if (file_ == base::kInvalidPlatformFileValue && !tried_to_download_ && | 229 if (file_ == base::kInvalidPlatformFileValue && !tried_to_download_ && |
| 229 request_context_getter_) { | 230 request_context_getter_) { |
| 230 // We download from the ui thread because we need to know that | 231 // We download from the ui thread because we need to know that |
| 231 // |request_context_getter_| is still valid before initiating the download. | 232 // |request_context_getter_| is still valid before initiating the download. |
| 232 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 233 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 233 NewRunnableMethod(this, &SpellCheckHostImpl::DownloadDictionary)); | 234 service_task_factory_.NewRunnableMethod( |
| 235 &SpellCheckHostImpl::DownloadDictionary)); |
| 234 return; | 236 return; |
| 235 } | 237 } |
| 236 | 238 |
| 237 request_context_getter_ = NULL; | 239 request_context_getter_ = NULL; |
| 238 | 240 |
| 239 scoped_ptr<CustomWordList> custom_words(new CustomWordList()); | 241 scoped_ptr<CustomWordList> custom_words(new CustomWordList()); |
| 240 if (file_ != base::kInvalidPlatformFileValue) { | 242 if (file_ != base::kInvalidPlatformFileValue) { |
| 241 // Load custom dictionary. | 243 // Load custom dictionary. |
| 242 std::string contents; | 244 std::string contents; |
| 243 file_util::ReadFileToString(custom_dictionary_file_, &contents); | 245 file_util::ReadFileToString(custom_dictionary_file_, &contents); |
| 244 CustomWordList list_of_words; | 246 CustomWordList list_of_words; |
| 245 base::SplitString(contents, '\n', &list_of_words); | 247 base::SplitString(contents, '\n', &list_of_words); |
| 246 for (size_t i = 0; i < list_of_words.size(); ++i) | 248 for (size_t i = 0; i < list_of_words.size(); ++i) |
| 247 custom_words->push_back(list_of_words[i]); | 249 custom_words->push_back(list_of_words[i]); |
| 248 } | 250 } |
| 249 | 251 |
| 250 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 252 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 251 NewRunnableMethod( | 253 service_task_factory_.NewRunnableMethod( |
| 252 this, | |
| 253 &SpellCheckHostImpl::InformProfileOfInitializationWithCustomWords, | 254 &SpellCheckHostImpl::InformProfileOfInitializationWithCustomWords, |
| 254 custom_words.release())); | 255 custom_words.release())); |
| 255 } | 256 } |
| 256 | 257 |
| 257 void SpellCheckHostImpl::InitializeOnFileThread() { | 258 void SpellCheckHostImpl::InitializeOnFileThread() { |
| 258 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 259 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 259 | 260 |
| 260 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 261 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 261 NewRunnableMethod(this, &SpellCheckHostImpl::Initialize)); | 262 service_task_factory_.NewRunnableMethod( |
| 263 &SpellCheckHostImpl::Initialize)); |
| 262 } | 264 } |
| 263 | 265 |
| 264 void SpellCheckHostImpl::InformProfileOfInitialization() { | 266 void SpellCheckHostImpl::InformProfileOfInitialization() { |
| 265 InformProfileOfInitializationWithCustomWords(NULL); | 267 InformProfileOfInitializationWithCustomWords(NULL); |
| 266 } | 268 } |
| 267 | 269 |
| 268 void SpellCheckHostImpl::InformProfileOfInitializationWithCustomWords( | 270 void SpellCheckHostImpl::InformProfileOfInitializationWithCustomWords( |
| 269 CustomWordList* custom_words) { | 271 CustomWordList* custom_words) { |
| 270 // Non-null |custom_words| should be given only if the profile is available | 272 // Non-null |custom_words| should be given only if the profile is available |
| 271 // for simplifying the life-cycle management of the word list. | 273 // for simplifying the life-cycle management of the word list. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 // that represents some form of failure. | 343 // that represents some form of failure. |
| 342 if (data.size() < 4 || data[0] != 'B' || data[1] != 'D' || data[2] != 'i' || | 344 if (data.size() < 4 || data[0] != 'B' || data[1] != 'D' || data[2] != 'i' || |
| 343 data[3] != 'c') { | 345 data[3] != 'c') { |
| 344 LOG(ERROR) << "Failure to download dictionary."; | 346 LOG(ERROR) << "Failure to download dictionary."; |
| 345 InitializeOnFileThread(); | 347 InitializeOnFileThread(); |
| 346 return; | 348 return; |
| 347 } | 349 } |
| 348 | 350 |
| 349 data_ = data; | 351 data_ = data; |
| 350 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 352 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 351 NewRunnableMethod(this, &SpellCheckHostImpl::SaveDictionaryData)); | 353 service_task_factory_.NewRunnableMethod( |
| 354 &SpellCheckHostImpl::SaveDictionaryData)); |
| 352 } | 355 } |
| 353 | 356 |
| 354 void SpellCheckHostImpl::Observe(int type, | 357 void SpellCheckHostImpl::Observe(int type, |
| 355 const NotificationSource& source, | 358 const NotificationSource& source, |
| 356 const NotificationDetails& details) { | 359 const NotificationDetails& details) { |
| 357 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_CREATED); | 360 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_CREATED); |
| 358 RenderProcessHost* process = Source<RenderProcessHost>(source).ptr(); | 361 RenderProcessHost* process = Source<RenderProcessHost>(source).ptr(); |
| 359 InitForRenderer(process); | 362 InitForRenderer(process); |
| 360 } | 363 } |
| 361 | 364 |
| 362 void SpellCheckHostImpl::SaveDictionaryData() { | 365 void SpellCheckHostImpl::SaveDictionaryData() { |
| 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 364 | 367 |
| 365 // To prevent corrupted dictionary data from causing a renderer crash, scan | 368 // To prevent corrupted dictionary data from causing a renderer crash, scan |
| 366 // the dictionary data and verify it is sane before save it to a file. | 369 // the dictionary data and verify it is sane before save it to a file. |
| 367 bool verified = hunspell::BDict::Verify(data_.data(), data_.size()); | 370 bool verified = hunspell::BDict::Verify(data_.data(), data_.size()); |
| 368 if (metrics_) | 371 if (metrics_) |
| 369 metrics_->RecordDictionaryCorruptionStats(!verified); | 372 metrics_->RecordDictionaryCorruptionStats(!verified); |
| 370 if (!verified) { | 373 if (!verified) { |
| 371 LOG(ERROR) << "Failure to verify the downloaded dictionary."; | 374 LOG(ERROR) << "Failure to verify the downloaded dictionary."; |
| 372 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 375 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 373 NewRunnableMethod(this, | 376 service_task_factory_.NewRunnableMethod( |
| 374 &SpellCheckHostImpl::InformProfileOfInitialization)); | 377 &SpellCheckHostImpl::InformProfileOfInitialization)); |
| 375 return; | 378 return; |
| 376 } | 379 } |
| 377 | 380 |
| 378 size_t bytes_written = | 381 size_t bytes_written = |
| 379 file_util::WriteFile(bdict_file_path_, data_.data(), data_.length()); | 382 file_util::WriteFile(bdict_file_path_, data_.data(), data_.length()); |
| 380 if (bytes_written != data_.length()) { | 383 if (bytes_written != data_.length()) { |
| 381 bool success = false; | 384 bool success = false; |
| 382 #if defined(OS_WIN) | 385 #if defined(OS_WIN) |
| 383 bdict_file_path_ = GetFallbackFilePath(bdict_file_path_); | 386 bdict_file_path_ = GetFallbackFilePath(bdict_file_path_); |
| 384 bytes_written = | 387 bytes_written = |
| 385 file_util::WriteFile(GetFallbackFilePath(bdict_file_path_), | 388 file_util::WriteFile(GetFallbackFilePath(bdict_file_path_), |
| 386 data_.data(), data_.length()); | 389 data_.data(), data_.length()); |
| 387 if (bytes_written == data_.length()) | 390 if (bytes_written == data_.length()) |
| 388 success = true; | 391 success = true; |
| 389 #endif | 392 #endif |
| 390 data_.clear(); | 393 data_.clear(); |
| 391 | 394 |
| 392 if (!success) { | 395 if (!success) { |
| 393 LOG(ERROR) << "Failure to save dictionary."; | 396 LOG(ERROR) << "Failure to save dictionary."; |
| 394 file_util::Delete(bdict_file_path_, false); | 397 file_util::Delete(bdict_file_path_, false); |
| 395 // To avoid trying to load a partially saved dictionary, shortcut the | 398 // To avoid trying to load a partially saved dictionary, shortcut the |
| 396 // Initialize() call. | 399 // Initialize() call. |
| 397 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 400 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 398 NewRunnableMethod(this, | 401 service_task_factory_.NewRunnableMethod( |
| 399 &SpellCheckHostImpl::InformProfileOfInitialization)); | 402 &SpellCheckHostImpl::InformProfileOfInitialization)); |
| 400 return; | 403 return; |
| 401 } | 404 } |
| 402 } | 405 } |
| 403 | 406 |
| 404 data_.clear(); | 407 data_.clear(); |
| 405 Initialize(); | 408 Initialize(); |
| 406 } | 409 } |
| 407 | 410 |
| 408 bool SpellCheckHostImpl::VerifyBDict(const FilePath& path) const { | 411 bool SpellCheckHostImpl::VerifyBDict(const FilePath& path) const { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 432 return file_; | 435 return file_; |
| 433 } | 436 } |
| 434 | 437 |
| 435 const std::string& SpellCheckHostImpl::GetLanguage() const { | 438 const std::string& SpellCheckHostImpl::GetLanguage() const { |
| 436 return language_; | 439 return language_; |
| 437 } | 440 } |
| 438 | 441 |
| 439 bool SpellCheckHostImpl::IsUsingPlatformChecker() const { | 442 bool SpellCheckHostImpl::IsUsingPlatformChecker() const { |
| 440 return use_platform_spellchecker_; | 443 return use_platform_spellchecker_; |
| 441 } | 444 } |
| OLD | NEW |