| 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/spellcheck_host_impl.h" | 5 #include "chrome/browser/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" |
| 11 #include "base/path_service.h" | 11 #include "base/path_service.h" |
| 12 #include "base/string_split.h" | 12 #include "base/string_split.h" |
| 13 #include "base/threading/thread_restrictions.h" | 13 #include "base/threading/thread_restrictions.h" |
| 14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
| 15 #include "chrome/browser/prefs/pref_service.h" |
| 16 #include "chrome/browser/profiles/profile.h" |
| 15 #include "chrome/browser/spellcheck_host_observer.h" | 17 #include "chrome/browser/spellcheck_host_observer.h" |
| 16 #include "chrome/browser/spellchecker_platform_engine.h" | 18 #include "chrome/browser/spellchecker_platform_engine.h" |
| 17 #include "chrome/common/chrome_constants.h" | 19 #include "chrome/common/chrome_constants.h" |
| 18 #include "chrome/common/chrome_paths.h" | 20 #include "chrome/common/chrome_paths.h" |
| 21 #include "chrome/common/pref_names.h" |
| 19 #include "chrome/common/spellcheck_common.h" | 22 #include "chrome/common/spellcheck_common.h" |
| 23 #include "chrome/common/spellcheck_messages.h" |
| 24 #include "content/browser/renderer_host/render_process_host.h" |
| 20 #include "content/common/notification_service.h" | 25 #include "content/common/notification_service.h" |
| 21 #include "googleurl/src/gurl.h" | 26 #include "googleurl/src/gurl.h" |
| 22 #include "net/url_request/url_request_context_getter.h" | 27 #include "net/url_request/url_request_context_getter.h" |
| 23 #include "third_party/hunspell/google/bdict.h" | 28 #include "third_party/hunspell/google/bdict.h" |
| 24 #include "ui/base/l10n/l10n_util.h" | 29 #include "ui/base/l10n/l10n_util.h" |
| 25 #if defined(OS_MACOSX) | 30 #if defined(OS_MACOSX) |
| 26 #include "base/metrics/histogram.h" | 31 #include "base/metrics/histogram.h" |
| 27 #endif | 32 #endif |
| 28 | 33 |
| 29 namespace { | 34 namespace { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 tried_to_download_(false), | 88 tried_to_download_(false), |
| 84 use_platform_spellchecker_(false), | 89 use_platform_spellchecker_(false), |
| 85 request_context_getter_(request_context_getter) { | 90 request_context_getter_(request_context_getter) { |
| 86 DCHECK(observer_); | 91 DCHECK(observer_); |
| 87 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 88 | 93 |
| 89 FilePath personal_file_directory; | 94 FilePath personal_file_directory; |
| 90 PathService::Get(chrome::DIR_USER_DATA, &personal_file_directory); | 95 PathService::Get(chrome::DIR_USER_DATA, &personal_file_directory); |
| 91 custom_dictionary_file_ = | 96 custom_dictionary_file_ = |
| 92 personal_file_directory.Append(chrome::kCustomDictionaryFileName); | 97 personal_file_directory.Append(chrome::kCustomDictionaryFileName); |
| 98 |
| 99 registrar_.Add(this, NotificationType::RENDERER_PROCESS_CREATED, |
| 100 NotificationService::AllSources()); |
| 93 } | 101 } |
| 94 | 102 |
| 95 SpellCheckHostImpl::~SpellCheckHostImpl() { | 103 SpellCheckHostImpl::~SpellCheckHostImpl() { |
| 96 if (file_ != base::kInvalidPlatformFileValue) | 104 if (file_ != base::kInvalidPlatformFileValue) |
| 97 base::ClosePlatformFile(file_); | 105 base::ClosePlatformFile(file_); |
| 98 } | 106 } |
| 99 | 107 |
| 100 void SpellCheckHostImpl::Initialize() { | 108 void SpellCheckHostImpl::Initialize() { |
| 101 if (SpellCheckerPlatform::SpellCheckerAvailable() && | 109 if (SpellCheckerPlatform::SpellCheckerAvailable() && |
| 102 SpellCheckerPlatform::PlatformSupportsLanguage(language_)) { | 110 SpellCheckerPlatform::PlatformSupportsLanguage(language_)) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 119 NewRunnableMethod(this, | 127 NewRunnableMethod(this, |
| 120 &SpellCheckHostImpl::InitializeDictionaryLocation)); | 128 &SpellCheckHostImpl::InitializeDictionaryLocation)); |
| 121 } | 129 } |
| 122 | 130 |
| 123 void SpellCheckHostImpl::UnsetObserver() { | 131 void SpellCheckHostImpl::UnsetObserver() { |
| 124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 125 | 133 |
| 126 observer_ = NULL; | 134 observer_ = NULL; |
| 127 request_context_getter_ = NULL; | 135 request_context_getter_ = NULL; |
| 128 fetcher_.reset(); | 136 fetcher_.reset(); |
| 137 registrar_.RemoveAll(); |
| 138 } |
| 139 |
| 140 void SpellCheckHostImpl::InitForRenderer(RenderProcessHost* process) { |
| 141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 142 |
| 143 PrefService* prefs = process->profile()->GetPrefs(); |
| 144 IPC::PlatformFileForTransit file; |
| 145 |
| 146 if (GetDictionaryFile() != base::kInvalidPlatformFileValue) { |
| 147 #if defined(OS_POSIX) |
| 148 file = base::FileDescriptor(GetDictionaryFile(), false); |
| 149 #elif defined(OS_WIN) |
| 150 ::DuplicateHandle(::GetCurrentProcess(), |
| 151 GetDictionaryFile(), |
| 152 process->GetHandle(), |
| 153 &file, |
| 154 0, |
| 155 false, |
| 156 DUPLICATE_SAME_ACCESS); |
| 157 #endif |
| 158 } |
| 159 |
| 160 process->Send(new SpellCheckMsg_Init( |
| 161 file, |
| 162 GetCustomWords(), |
| 163 GetLanguage(), |
| 164 prefs->GetBoolean(prefs::kEnableAutoSpellCorrect))); |
| 129 } | 165 } |
| 130 | 166 |
| 131 void SpellCheckHostImpl::AddWord(const std::string& word) { | 167 void SpellCheckHostImpl::AddWord(const std::string& word) { |
| 132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 133 | 169 |
| 134 custom_words_.push_back(word); | 170 custom_words_.push_back(word); |
| 135 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 171 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 136 NewRunnableMethod(this, | 172 NewRunnableMethod(this, |
| 137 &SpellCheckHostImpl::WriteWordToCustomDictionary, word)); | 173 &SpellCheckHostImpl::WriteWordToCustomDictionary, word)); |
| 138 NotificationService::current()->Notify( | 174 |
| 139 NotificationType::SPELLCHECK_WORD_ADDED, | 175 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); |
| 140 Source<SpellCheckHost>(this), NotificationService::NoDetails()); | 176 !i.IsAtEnd(); i.Advance()) { |
| 177 i.GetCurrentValue()->Send(new SpellCheckMsg_WordAdded(GetLastAddedFile())); |
| 178 } |
| 141 } | 179 } |
| 142 | 180 |
| 143 void SpellCheckHostImpl::InitializeDictionaryLocation() { | 181 void SpellCheckHostImpl::InitializeDictionaryLocation() { |
| 144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 145 | 183 |
| 146 // Initialize the BDICT path. This initialization should be in the FILE thread | 184 // Initialize the BDICT path. This initialization should be in the FILE thread |
| 147 // because it checks if there is a "Dictionaries" directory and create it. | 185 // because it checks if there is a "Dictionaries" directory and create it. |
| 148 if (bdict_file_path_.empty()) | 186 if (bdict_file_path_.empty()) |
| 149 bdict_file_path_ = GetFirstChoiceFilePath(language_); | 187 bdict_file_path_ = GetFirstChoiceFilePath(language_); |
| 150 | 188 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 | 242 |
| 205 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 243 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 206 NewRunnableMethod(this, &SpellCheckHostImpl::Initialize)); | 244 NewRunnableMethod(this, &SpellCheckHostImpl::Initialize)); |
| 207 } | 245 } |
| 208 | 246 |
| 209 void SpellCheckHostImpl::InformObserverOfInitialization() { | 247 void SpellCheckHostImpl::InformObserverOfInitialization() { |
| 210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 211 | 249 |
| 212 if (observer_) | 250 if (observer_) |
| 213 observer_->SpellCheckHostInitialized(); | 251 observer_->SpellCheckHostInitialized(); |
| 252 |
| 253 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); |
| 254 !i.IsAtEnd(); i.Advance()) { |
| 255 InitForRenderer(i.GetCurrentValue()); |
| 256 } |
| 214 } | 257 } |
| 215 | 258 |
| 216 void SpellCheckHostImpl::DownloadDictionary() { | 259 void SpellCheckHostImpl::DownloadDictionary() { |
| 217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 218 | 261 |
| 219 if (!request_context_getter_) { | 262 if (!request_context_getter_) { |
| 220 InitializeOnFileThread(); | 263 InitializeOnFileThread(); |
| 221 return; | 264 return; |
| 222 } | 265 } |
| 223 | 266 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 LOG(ERROR) << "Failure to download dictionary."; | 317 LOG(ERROR) << "Failure to download dictionary."; |
| 275 InitializeOnFileThread(); | 318 InitializeOnFileThread(); |
| 276 return; | 319 return; |
| 277 } | 320 } |
| 278 | 321 |
| 279 data_ = data; | 322 data_ = data; |
| 280 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 323 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 281 NewRunnableMethod(this, &SpellCheckHostImpl::SaveDictionaryData)); | 324 NewRunnableMethod(this, &SpellCheckHostImpl::SaveDictionaryData)); |
| 282 } | 325 } |
| 283 | 326 |
| 327 void SpellCheckHostImpl::Observe(NotificationType type, |
| 328 const NotificationSource& source, |
| 329 const NotificationDetails& details) { |
| 330 DCHECK(type == NotificationType::RENDERER_PROCESS_CREATED); |
| 331 RenderProcessHost* process = Source<RenderProcessHost>(source).ptr(); |
| 332 InitForRenderer(process); |
| 333 } |
| 334 |
| 284 void SpellCheckHostImpl::SaveDictionaryData() { | 335 void SpellCheckHostImpl::SaveDictionaryData() { |
| 285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 286 | 337 |
| 287 // To prevent corrupted dictionary data from causing a renderer crash, scan | 338 // To prevent corrupted dictionary data from causing a renderer crash, scan |
| 288 // the dictionary data and verify it is sane before save it to a file. | 339 // the dictionary data and verify it is sane before save it to a file. |
| 289 if (!hunspell::BDict::Verify(data_.data(), data_.size())) { | 340 if (!hunspell::BDict::Verify(data_.data(), data_.size())) { |
| 290 LOG(ERROR) << "Failure to verify the downloaded dictionary."; | 341 LOG(ERROR) << "Failure to verify the downloaded dictionary."; |
| 291 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 342 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 292 NewRunnableMethod(this, | 343 NewRunnableMethod(this, |
| 293 &SpellCheckHostImpl::InformObserverOfInitialization)); | 344 &SpellCheckHostImpl::InformObserverOfInitialization)); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 return custom_words_.back(); | 387 return custom_words_.back(); |
| 337 } | 388 } |
| 338 | 389 |
| 339 const std::string& SpellCheckHostImpl::GetLanguage() const { | 390 const std::string& SpellCheckHostImpl::GetLanguage() const { |
| 340 return language_; | 391 return language_; |
| 341 } | 392 } |
| 342 | 393 |
| 343 bool SpellCheckHostImpl::IsUsingPlatformChecker() const { | 394 bool SpellCheckHostImpl::IsUsingPlatformChecker() const { |
| 344 return use_platform_spellchecker_; | 395 return use_platform_spellchecker_; |
| 345 } | 396 } |
| OLD | NEW |