12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_service.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_member.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_factory.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_host_metrics.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_platform_mac.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/spellchecker/spelling_service_client.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/pref_names.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/spellcheck_messages.h" 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "components/user_prefs/user_prefs.h" 19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "content/public/browser/browser_context.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_service.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_types.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/render_process_host.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_platform_file.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using chrome::spellcheck_common::WordList; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(rlp): I do not like globals, but keeping these for now during 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// transition. 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// An event used by browser tests to receive status events from this class and 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// its derived classes. 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::WaitableEvent* g_status_event = NULL; 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpellcheckService::EventType g_status_type = 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpellcheckService::BDICT_NOTINITIALIZED; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)SpellcheckService::SpellcheckService(content::BrowserContext* context) 38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : context_(context), 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_(this) { 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PrefService* prefs = user_prefs::UserPrefs::Get(context); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pref_change_registrar_.Init(prefs); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string language_code; 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string country_code; 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::spellcheck_common::GetISOLanguageCountryCodeFromLocale( 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) prefs->GetString(prefs::kSpellCheckDictionary), 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &language_code, 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &country_code); 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) feedback_sender_.reset(new spellcheck::FeedbackSender( 51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) context->GetRequestContext(), language_code, country_code)); 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pref_change_registrar_.Add( 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prefs::kEnableAutoSpellCorrect, 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SpellcheckService::OnEnableAutoSpellCorrectChanged, 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pref_change_registrar_.Add( 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prefs::kSpellCheckDictionary, 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SpellcheckService::OnSpellCheckDictionaryChanged, 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pref_change_registrar_.Add( 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prefs::kSpellCheckUseSpellingService, 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SpellcheckService::OnUseSpellingServiceChanged, 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pref_change_registrar_.Add( 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prefs::kEnableContinuousSpellcheck, 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SpellcheckService::InitForAllRenderers, 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnSpellCheckDictionaryChanged(); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) custom_dictionary_.reset(new SpellcheckCustomDictionary(context_->GetPath())); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) custom_dictionary_->AddObserver(this); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) custom_dictionary_->Load(); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) registrar_.Add(this, 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::NOTIFICATION_RENDERER_PROCESS_CREATED, 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::NotificationService::AllSources()); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpellcheckService::~SpellcheckService() { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remove pref observers 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pref_change_registrar_.RemoveAll(); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SpellcheckService::GetSpellCheckLanguages( 88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) content::BrowserContext* context, 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<std::string>* languages) { 90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PrefService* prefs = user_prefs::UserPrefs::Get(context); 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StringPrefMember accept_languages_pref; 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StringPrefMember dictionary_language_pref; 93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) accept_languages_pref.Init(prefs::kAcceptLanguages, prefs); 94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dictionary_language_pref.Init(prefs::kSpellCheckDictionary, prefs); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string dictionary_language = dictionary_language_pref.GetValue(); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Now scan through the list of accept languages, and find possible mappings 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from this list to the existing list of spell check languages. 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<std::string> accept_languages; 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_MACOSX) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (spellcheck_mac::SpellCheckerAvailable()) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) spellcheck_mac::GetAvailableLanguages(&accept_languages); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::SplitString(accept_languages_pref.GetValue(), ',', &accept_languages); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::SplitString(accept_languages_pref.GetValue(), ',', &accept_languages); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // !OS_MACOSX 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetSpellCheckLanguagesFromAcceptLanguages( 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) accept_languages, dictionary_language, languages); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < languages->size(); ++i) { 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*languages)[i] == dictionary_language) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return i; 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::GetSpellCheckLanguagesFromAcceptLanguages( 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<std::string>& accept_languages, 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& dictionary_language, 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<std::string>* languages) { 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The current dictionary language should be there. 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) languages->push_back(dictionary_language); 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<std::string>::const_iterator i = accept_languages.begin(); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i != accept_languages.end(); ++i) { 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string language = 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::spellcheck_common::GetCorrespondingSpellCheckLanguage(*i); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!language.empty() && 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::find(languages->begin(), languages->end(), language) == 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) languages->end()) { 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) languages->push_back(language); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpellcheckService::SignalStatusEvent( 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpellcheckService::EventType status_type) { 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!g_status_event) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_status_type = status_type; 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_status_event->Signal(); 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::StartRecordingMetrics(bool spellcheck_enabled) { 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) metrics_.reset(new SpellCheckHostMetrics()); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) metrics_->RecordEnabledStats(spellcheck_enabled); 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnUseSpellingServiceChanged(); 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::InitForRenderer(content::RenderProcessHost* process) { 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) content::BrowserContext* context = process->GetBrowserContext(); 162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (SpellcheckServiceFactory::GetForContext(context) != this) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PrefService* prefs = user_prefs::UserPrefs::Get(context); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC::PlatformFileForTransit file = IPC::InvalidPlatformFileForTransit(); 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (hunspell_dictionary_->GetDictionaryFile().IsValid()) { 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file = IPC::GetFileHandleForProcess( 17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) hunspell_dictionary_->GetDictionaryFile().GetPlatformFile(), 17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) process->GetHandle(), false); 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) process->Send(new SpellCheckMsg_Init( 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file, 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) custom_dictionary_->GetWords(), 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hunspell_dictionary_->GetLanguage(), 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prefs->GetBoolean(prefs::kEnableAutoSpellCorrect))); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) process->Send(new SpellCheckMsg_EnableSpellCheck( 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prefs->GetBoolean(prefs::kEnableContinuousSpellcheck))); 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpellCheckHostMetrics* SpellcheckService::GetMetrics() const { 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return metrics_.get(); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpellcheckCustomDictionary* SpellcheckService::GetCustomDictionary() { 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return custom_dictionary_.get(); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpellcheckHunspellDictionary* SpellcheckService::GetHunspellDictionary() { 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return hunspell_dictionary_.get(); 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)spellcheck::FeedbackSender* SpellcheckService::GetFeedbackSender() { 19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return feedback_sender_.get(); 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool SpellcheckService::LoadExternalDictionary(std::string language, 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string locale, 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string path, 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DictionaryFormat format) { 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool SpellcheckService::UnloadExternalDictionary(std::string path) { 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::Observe(int type, 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const content::NotificationSource& source, 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const content::NotificationDetails& details) { 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_CREATED); 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::RenderProcessHost* process = 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Source<content::RenderProcessHost>(source).ptr(); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InitForRenderer(process); 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::OnCustomDictionaryLoaded() { 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InitForAllRenderers(); 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::OnCustomDictionaryChanged( 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpellcheckCustomDictionary::Change& dictionary_change) { 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (content::RenderProcessHost::iterator i( 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::RenderProcessHost::AllHostsIterator()); 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !i.IsAtEnd(); i.Advance()) { 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i.GetCurrentValue()->Send(new SpellCheckMsg_CustomDictionaryChanged( 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dictionary_change.to_add(), 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dictionary_change.to_remove())); 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::OnHunspellDictionaryInitialized() { 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InitForAllRenderers(); 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::OnHunspellDictionaryDownloadBegin() { 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::OnHunspellDictionaryDownloadSuccess() { 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::OnHunspellDictionaryDownloadFailure() { 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::AttachStatusEvent(base::WaitableEvent* status_event) { 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) g_status_event = status_event; 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpellcheckService::EventType SpellcheckService::GetStatusEvent() { 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return g_status_type; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::InitForAllRenderers() { 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (content::RenderProcessHost::iterator i( 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::RenderProcessHost::AllHostsIterator()); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !i.IsAtEnd(); i.Advance()) { 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::RenderProcessHost* process = i.GetCurrentValue(); 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (process && process->GetHandle()) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InitForRenderer(process); 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::OnEnableAutoSpellCorrectChanged() { 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool enabled = pref_change_registrar_.prefs()->GetBoolean( 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prefs::kEnableAutoSpellCorrect); 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (content::RenderProcessHost::iterator i( 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::RenderProcessHost::AllHostsIterator()); 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !i.IsAtEnd(); i.Advance()) { 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::RenderProcessHost* process = i.GetCurrentValue(); 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) process->Send(new SpellCheckMsg_EnableAutoSpellCorrect(enabled)); 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::OnSpellCheckDictionaryChanged() { 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (hunspell_dictionary_.get()) 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hunspell_dictionary_->RemoveObserver(this); 285d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PrefService* prefs = user_prefs::UserPrefs::Get(context_); 286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(prefs); 287d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string dictionary = 289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) prefs->GetString(prefs::kSpellCheckDictionary); 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hunspell_dictionary_.reset(new SpellcheckHunspellDictionary( 291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dictionary, context_->GetRequestContext(), this)); 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hunspell_dictionary_->AddObserver(this); 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hunspell_dictionary_->Load(); 29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string language_code; 29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string country_code; 29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::spellcheck_common::GetISOLanguageCountryCodeFromLocale( 29790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) dictionary, &language_code, &country_code); 29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) feedback_sender_->OnLanguageCountryChange(language_code, country_code); 299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UpdateFeedbackSenderState(); 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpellcheckService::OnUseSpellingServiceChanged() { 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool enabled = pref_change_registrar_.prefs()->GetBoolean( 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prefs::kSpellCheckUseSpellingService); 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (metrics_) 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) metrics_->RecordSpellingServiceStats(enabled); 307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UpdateFeedbackSenderState(); 308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SpellcheckService::UpdateFeedbackSenderState() { 311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (SpellingServiceClient::IsAvailable( 312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) context_, SpellingServiceClient::SPELLCHECK)) { 313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) feedback_sender_->StartFeedbackCollection(); 314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) feedback_sender_->StopFeedbackCollection(); 316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 318