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