| 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_service.h" | 5 #include "chrome/browser/spellchecker/spellcheck_service.h" |
| 6 | 6 |
| 7 #include "base/platform_file.h" | 7 #include "base/platform_file.h" |
| 8 #include "base/string_split.h" | 8 #include "base/string_split.h" |
| 9 #include "base/synchronization/waitable_event.h" | 9 #include "base/synchronization/waitable_event.h" |
| 10 #include "chrome/browser/api/prefs/pref_member.h" | 10 #include "chrome/browser/api/prefs/pref_member.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 pref_change_registrar_.Add(prefs::kEnableAutoSpellCorrect, this); | 44 pref_change_registrar_.Add(prefs::kEnableAutoSpellCorrect, this); |
| 45 | 45 |
| 46 hunspell_dictionary_.reset(new SpellcheckHunspellDictionary( | 46 hunspell_dictionary_.reset(new SpellcheckHunspellDictionary( |
| 47 profile, prefs->GetString(prefs::kSpellCheckDictionary), | 47 profile, prefs->GetString(prefs::kSpellCheckDictionary), |
| 48 profile->GetRequestContext(), this)); | 48 profile->GetRequestContext(), this)); |
| 49 // TODO(rlp): This should be the load function so we can loop through all | 49 // TODO(rlp): This should be the load function so we can loop through all |
| 50 // dictionaries easily. | 50 // dictionaries easily. |
| 51 hunspell_dictionary_->Initialize(); | 51 hunspell_dictionary_->Initialize(); |
| 52 | 52 |
| 53 custom_dictionary_.reset(new SpellcheckCustomDictionary(profile_)); | 53 custom_dictionary_.reset(new SpellcheckCustomDictionary(profile_)); |
| 54 custom_dictionary_->AddObserver(this); |
| 54 custom_dictionary_->Load(); | 55 custom_dictionary_->Load(); |
| 55 | 56 |
| 56 registrar_.Add(weak_ptr_factory_.GetWeakPtr(), | 57 registrar_.Add(weak_ptr_factory_.GetWeakPtr(), |
| 57 content::NOTIFICATION_RENDERER_PROCESS_CREATED, | 58 content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
| 58 content::NotificationService::AllSources()); | 59 content::NotificationService::AllSources()); |
| 59 | 60 |
| 60 } | 61 } |
| 61 | 62 |
| 62 SpellcheckService::~SpellcheckService() { | 63 SpellcheckService::~SpellcheckService() { |
| 63 // Remove pref observers | 64 // Remove pref observers |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 SpellcheckService::EventType status_type) { | 125 SpellcheckService::EventType status_type) { |
| 125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 126 | 127 |
| 127 if (!g_status_event) | 128 if (!g_status_event) |
| 128 return false; | 129 return false; |
| 129 g_status_type = status_type; | 130 g_status_type = status_type; |
| 130 g_status_event->Signal(); | 131 g_status_event->Signal(); |
| 131 return true; | 132 return true; |
| 132 } | 133 } |
| 133 | 134 |
| 134 // static | |
| 135 void SpellcheckService::AttachStatusEvent(base::WaitableEvent* status_event) { | |
| 136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 137 | |
| 138 g_status_event = status_event; | |
| 139 } | |
| 140 | |
| 141 // static | |
| 142 SpellcheckService::EventType SpellcheckService::WaitStatusEvent() { | |
| 143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 144 | |
| 145 if (g_status_event) | |
| 146 g_status_event->Wait(); | |
| 147 return g_status_type; | |
| 148 } | |
| 149 | |
| 150 void SpellcheckService::Initialize() { | |
| 151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 152 hunspell_dictionary_->Initialize(); | |
| 153 } | |
| 154 | |
| 155 void SpellcheckService::StartRecordingMetrics(bool spellcheck_enabled) { | 135 void SpellcheckService::StartRecordingMetrics(bool spellcheck_enabled) { |
| 156 metrics_.reset(new SpellCheckHostMetrics()); | 136 metrics_.reset(new SpellCheckHostMetrics()); |
| 157 metrics_->RecordEnabledStats(spellcheck_enabled); | 137 metrics_->RecordEnabledStats(spellcheck_enabled); |
| 158 } | 138 } |
| 159 | 139 |
| 140 void SpellcheckService::InitForAllRenderers() { |
| 141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 142 for (content::RenderProcessHost::iterator i( |
| 143 content::RenderProcessHost::AllHostsIterator()); |
| 144 !i.IsAtEnd(); i.Advance()) { |
| 145 content::RenderProcessHost* process = i.GetCurrentValue(); |
| 146 if (process) |
| 147 InitForRenderer(process); |
| 148 } |
| 149 } |
| 150 |
| 160 void SpellcheckService::InitForRenderer(content::RenderProcessHost* process) { | 151 void SpellcheckService::InitForRenderer(content::RenderProcessHost* process) { |
| 161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 162 | 153 |
| 163 Profile* profile = Profile::FromBrowserContext(process->GetBrowserContext()); | 154 Profile* profile = Profile::FromBrowserContext(process->GetBrowserContext()); |
| 164 if (SpellcheckServiceFactory::GetForProfile(profile) != this) | 155 if (SpellcheckServiceFactory::GetForProfile(profile) != this) |
| 165 return; | 156 return; |
| 166 | 157 |
| 167 PrefService* prefs = profile->GetPrefs(); | 158 PrefService* prefs = profile->GetPrefs(); |
| 168 IPC::PlatformFileForTransit file = IPC::InvalidPlatformFileForTransit(); | 159 IPC::PlatformFileForTransit file = IPC::InvalidPlatformFileForTransit(); |
| 169 | 160 |
| 170 if (hunspell_dictionary_->GetDictionaryFile() != | 161 if (hunspell_dictionary_->GetDictionaryFile() != |
| 171 base::kInvalidPlatformFileValue) { | 162 base::kInvalidPlatformFileValue) { |
| 172 #if defined(OS_POSIX) | 163 #if defined(OS_POSIX) |
| 173 file = base::FileDescriptor(hunspell_dictionary_->GetDictionaryFile(), | 164 file = base::FileDescriptor(hunspell_dictionary_->GetDictionaryFile(), |
| 174 false); | 165 false); |
| 175 #elif defined(OS_WIN) | 166 #elif defined(OS_WIN) |
| 176 BOOL ok = ::DuplicateHandle(::GetCurrentProcess(), | 167 BOOL ok = ::DuplicateHandle(::GetCurrentProcess(), |
| 177 hunspell_dictionary_->GetDictionaryFile(), | 168 hunspell_dictionary_->GetDictionaryFile(), |
| 178 process->GetHandle(), | 169 process->GetHandle(), |
| 179 &file, | 170 &file, |
| 180 0, | 171 0, |
| 181 false, | 172 false, |
| 182 DUPLICATE_SAME_ACCESS); | 173 DUPLICATE_SAME_ACCESS); |
| 183 DCHECK(ok) << ::GetLastError(); | 174 DCHECK(ok) << ::GetLastError(); |
| 184 #endif | 175 #endif |
| 185 } | 176 } |
| 186 | 177 |
| 187 WordList custom_words = GetCustomDictionary()->GetCustomWords(); | |
| 188 | |
| 189 process->Send(new SpellCheckMsg_Init( | 178 process->Send(new SpellCheckMsg_Init( |
| 190 file, | 179 file, |
| 191 custom_words, | 180 custom_dictionary_->GetWords(), |
| 192 hunspell_dictionary_->GetLanguage(), | 181 hunspell_dictionary_->GetLanguage(), |
| 193 prefs->GetBoolean(prefs::kEnableAutoSpellCorrect))); | 182 prefs->GetBoolean(prefs::kEnableAutoSpellCorrect))); |
| 194 } | 183 } |
| 195 | 184 |
| 185 bool SpellcheckService::IsReady() const { |
| 186 return hunspell_dictionary_->IsReady(); |
| 187 } |
| 188 |
| 189 const base::PlatformFile& SpellcheckService::GetDictionaryFile() const { |
| 190 return hunspell_dictionary_->GetDictionaryFile(); |
| 191 } |
| 192 |
| 193 const std::string& SpellcheckService::GetLanguage() const { |
| 194 return hunspell_dictionary_->GetLanguage(); |
| 195 } |
| 196 |
| 197 bool SpellcheckService::IsUsingPlatformChecker() const { |
| 198 return hunspell_dictionary_->IsUsingPlatformChecker(); |
| 199 } |
| 200 |
| 201 SpellCheckHostMetrics* SpellcheckService::GetMetrics() const { |
| 202 return metrics_.get(); |
| 203 } |
| 204 |
| 205 SpellcheckCustomDictionary* SpellcheckService::GetCustomDictionary() { |
| 206 return custom_dictionary_.get(); |
| 207 } |
| 208 |
| 196 void SpellcheckService::Observe(int type, | 209 void SpellcheckService::Observe(int type, |
| 197 const content::NotificationSource& source, | 210 const content::NotificationSource& source, |
| 198 const content::NotificationDetails& details) { | 211 const content::NotificationDetails& details) { |
| 199 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_CREATED); | 212 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_CREATED); |
| 200 content::RenderProcessHost* process = | 213 content::RenderProcessHost* process = |
| 201 content::Source<content::RenderProcessHost>(source).ptr(); | 214 content::Source<content::RenderProcessHost>(source).ptr(); |
| 202 InitForRenderer(process); | 215 InitForRenderer(process); |
| 203 } | 216 } |
| 204 | 217 |
| 205 void SpellcheckService::OnPreferenceChanged(PrefServiceBase* prefs, | 218 void SpellcheckService::OnPreferenceChanged(PrefServiceBase* prefs, |
| 206 const std::string& pref_name_in) { | 219 const std::string& pref_name_in) { |
| 207 DCHECK(prefs); | 220 DCHECK(prefs); |
| 208 if (pref_name_in == prefs::kSpellCheckDictionary || | 221 if (pref_name_in == prefs::kSpellCheckDictionary || |
| 209 pref_name_in == prefs::kEnableSpellCheck) { | 222 pref_name_in == prefs::kEnableSpellCheck) { |
| 210 InformProfileOfInitializationWithCustomWords(NULL); | 223 InitForAllRenderers(); |
| 211 } else if (pref_name_in == prefs::kEnableAutoSpellCorrect) { | 224 } else if (pref_name_in == prefs::kEnableAutoSpellCorrect) { |
| 212 bool enabled = prefs->GetBoolean(prefs::kEnableAutoSpellCorrect); | 225 bool enabled = prefs->GetBoolean(prefs::kEnableAutoSpellCorrect); |
| 213 for (content::RenderProcessHost::iterator i( | 226 for (content::RenderProcessHost::iterator i( |
| 214 content::RenderProcessHost::AllHostsIterator()); | 227 content::RenderProcessHost::AllHostsIterator()); |
| 215 !i.IsAtEnd(); i.Advance()) { | 228 !i.IsAtEnd(); i.Advance()) { |
| 216 content::RenderProcessHost* process = i.GetCurrentValue(); | 229 content::RenderProcessHost* process = i.GetCurrentValue(); |
| 217 process->Send(new SpellCheckMsg_EnableAutoSpellCorrect(enabled)); | 230 process->Send(new SpellCheckMsg_EnableAutoSpellCorrect(enabled)); |
| 218 } | 231 } |
| 219 } | 232 } |
| 220 } | 233 } |
| 221 | 234 |
| 222 SpellCheckHostMetrics* SpellcheckService::GetMetrics() const { | 235 void SpellcheckService::OnCustomDictionaryLoaded() { |
| 223 return metrics_.get(); | 236 InitForAllRenderers(); |
| 224 } | 237 } |
| 225 | 238 |
| 226 SpellcheckCustomDictionary* SpellcheckService::GetCustomDictionary() { | 239 void SpellcheckService::OnCustomDictionaryWordAdded(const std::string& word) { |
| 227 return custom_dictionary_.get(); | |
| 228 } | 240 } |
| 229 | 241 |
| 230 bool SpellcheckService::IsReady() const { | 242 void SpellcheckService::OnCustomDictionaryWordRemoved(const std::string& word) { |
| 231 return hunspell_dictionary_->IsReady(); | |
| 232 } | 243 } |
| 233 | 244 |
| 234 bool SpellcheckService::IsUsingPlatformChecker() const { | 245 // static |
| 235 return hunspell_dictionary_->IsUsingPlatformChecker(); | 246 void SpellcheckService::AttachStatusEvent(base::WaitableEvent* status_event) { |
| 247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 248 |
| 249 g_status_event = status_event; |
| 236 } | 250 } |
| 237 | 251 |
| 238 const base::PlatformFile& SpellcheckService::GetDictionaryFile() const { | 252 // static |
| 239 return hunspell_dictionary_->GetDictionaryFile(); | 253 SpellcheckService::EventType SpellcheckService::WaitStatusEvent() { |
| 240 } | |
| 241 | |
| 242 const std::string& SpellcheckService::GetLanguage() const { | |
| 243 return hunspell_dictionary_->GetLanguage(); | |
| 244 } | |
| 245 | |
| 246 // TODO(rlp): rename to something more logical. | |
| 247 void SpellcheckService::InformProfileOfInitializationWithCustomWords( | |
| 248 WordList* custom_words) { | |
| 249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 250 | 255 |
| 251 if (custom_words) { | 256 if (g_status_event) |
| 252 GetCustomDictionary()->SetCustomWordList(custom_words); | 257 g_status_event->Wait(); |
| 253 } | 258 return g_status_type; |
| 254 | |
| 255 for (content::RenderProcessHost::iterator i( | |
| 256 content::RenderProcessHost::AllHostsIterator()); | |
| 257 !i.IsAtEnd(); i.Advance()) { | |
| 258 content::RenderProcessHost* process = i.GetCurrentValue(); | |
| 259 if (process) | |
| 260 InitForRenderer(process); | |
| 261 } | |
| 262 } | 259 } |
| OLD | NEW |