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 |