Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Side by Side Diff: chrome/browser/spellchecker/spellcheck_service.cc

Issue 2244083002: Componentize spellcheck [4]: spellcheck/browser and android java-side. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <set> 7 #include <set>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/strings/string_split.h" 10 #include "base/strings/string_split.h"
11 #include "base/supports_user_data.h" 11 #include "base/supports_user_data.h"
12 #include "base/synchronization/waitable_event.h" 12 #include "base/synchronization/waitable_event.h"
13 #include "build/build_config.h" 13 #include "build/build_config.h"
14 #include "chrome/browser/spellchecker/feedback_sender.h"
15 #include "chrome/browser/spellchecker/spellcheck_factory.h" 14 #include "chrome/browser/spellchecker/spellcheck_factory.h"
16 #include "chrome/browser/spellchecker/spellcheck_host_metrics.h"
17 #include "chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h" 15 #include "chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h"
18 #include "chrome/browser/spellchecker/spellcheck_platform.h"
19 #include "chrome/browser/spellchecker/spelling_service_client.h"
20 #include "chrome/common/pref_names.h" 16 #include "chrome/common/pref_names.h"
21 #include "components/prefs/pref_member.h" 17 #include "components/prefs/pref_member.h"
22 #include "components/prefs/pref_service.h" 18 #include "components/prefs/pref_service.h"
19 #include "components/spellcheck/browser/feedback_sender.h"
20 #include "components/spellcheck/browser/pref_names.h"
21 #include "components/spellcheck/browser/spellcheck_host_metrics.h"
22 #include "components/spellcheck/browser/spellcheck_platform.h"
23 #include "components/spellcheck/browser/spelling_service_client.h"
23 #include "components/spellcheck/common/spellcheck_bdict_language.h" 24 #include "components/spellcheck/common/spellcheck_bdict_language.h"
24 #include "components/spellcheck/common/spellcheck_common.h" 25 #include "components/spellcheck/common/spellcheck_common.h"
25 #include "components/spellcheck/common/spellcheck_messages.h" 26 #include "components/spellcheck/common/spellcheck_messages.h"
26 #include "components/user_prefs/user_prefs.h" 27 #include "components/user_prefs/user_prefs.h"
27 #include "content/public/browser/browser_context.h" 28 #include "content/public/browser/browser_context.h"
28 #include "content/public/browser/browser_thread.h" 29 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/notification_service.h" 30 #include "content/public/browser/notification_service.h"
30 #include "content/public/browser/notification_types.h" 31 #include "content/public/browser/notification_types.h"
31 #include "content/public/browser/render_process_host.h" 32 #include "content/public/browser/render_process_host.h"
32 #include "content/public/browser/storage_partition.h" 33 #include "content/public/browser/storage_partition.h"
33 #include "ipc/ipc_platform_file.h" 34 #include "ipc/ipc_platform_file.h"
34 35
35 using content::BrowserThread; 36 using content::BrowserThread;
36 37
37 // TODO(rlp): I do not like globals, but keeping these for now during 38 // TODO(rlp): I do not like globals, but keeping these for now during
38 // transition. 39 // transition.
39 // An event used by browser tests to receive status events from this class and 40 // An event used by browser tests to receive status events from this class and
40 // its derived classes. 41 // its derived classes.
41 base::WaitableEvent* g_status_event = NULL; 42 base::WaitableEvent* g_status_event = NULL;
42 SpellcheckService::EventType g_status_type = 43 SpellcheckService::EventType g_status_type =
43 SpellcheckService::BDICT_NOTINITIALIZED; 44 SpellcheckService::BDICT_NOTINITIALIZED;
44 45
45 SpellcheckService::SpellcheckService(content::BrowserContext* context) 46 SpellcheckService::SpellcheckService(content::BrowserContext* context)
46 : context_(context), 47 : context_(context),
47 weak_ptr_factory_(this) { 48 weak_ptr_factory_(this) {
48 DCHECK_CURRENTLY_ON(BrowserThread::UI); 49 DCHECK_CURRENTLY_ON(BrowserThread::UI);
49 PrefService* prefs = user_prefs::UserPrefs::Get(context); 50 PrefService* prefs = user_prefs::UserPrefs::Get(context);
50 pref_change_registrar_.Init(prefs); 51 pref_change_registrar_.Init(prefs);
51 StringListPrefMember dictionaries_pref; 52 StringListPrefMember dictionaries_pref;
52 dictionaries_pref.Init(prefs::kSpellCheckDictionaries, prefs); 53 dictionaries_pref.Init(spellcheck::prefs::kSpellCheckDictionaries, prefs);
53 std::string first_of_dictionaries; 54 std::string first_of_dictionaries;
54 55
55 #if defined(USE_BROWSER_SPELLCHECKER) 56 #if defined(USE_BROWSER_SPELLCHECKER)
56 // Ensure that the renderer always knows the platform spellchecking language. 57 // Ensure that the renderer always knows the platform spellchecking language.
57 // This language is used for initialization of the text iterator. If the 58 // This language is used for initialization of the text iterator. If the
58 // iterator is not initialized, then the context menu does not show spellcheck 59 // iterator is not initialized, then the context menu does not show spellcheck
59 // suggestions. 60 // suggestions.
60 // 61 //
61 // No migration is necessary, because the spellcheck language preference is 62 // No migration is necessary, because the spellcheck language preference is
62 // not user visible or modifiable in Chrome on Mac. 63 // not user visible or modifiable in Chrome on Mac.
63 dictionaries_pref.SetValue(std::vector<std::string>( 64 dictionaries_pref.SetValue(std::vector<std::string>(
64 1, spellcheck_platform::GetSpellCheckerLanguage())); 65 1, spellcheck_platform::GetSpellCheckerLanguage()));
65 first_of_dictionaries = dictionaries_pref.GetValue().front(); 66 first_of_dictionaries = dictionaries_pref.GetValue().front();
66 #else 67 #else
67 // Migrate preferences from single-language to multi-language schema. 68 // Migrate preferences from single-language to multi-language schema.
68 StringPrefMember single_dictionary_pref; 69 StringPrefMember single_dictionary_pref;
69 single_dictionary_pref.Init(prefs::kSpellCheckDictionary, prefs); 70 single_dictionary_pref.Init(spellcheck::prefs::kSpellCheckDictionary, prefs);
70 std::string single_dictionary = single_dictionary_pref.GetValue(); 71 std::string single_dictionary = single_dictionary_pref.GetValue();
71 72
72 if (!dictionaries_pref.GetValue().empty()) 73 if (!dictionaries_pref.GetValue().empty())
73 first_of_dictionaries = dictionaries_pref.GetValue().front(); 74 first_of_dictionaries = dictionaries_pref.GetValue().front();
74 75
75 if (first_of_dictionaries.empty() && !single_dictionary.empty()) { 76 if (first_of_dictionaries.empty() && !single_dictionary.empty()) {
76 first_of_dictionaries = single_dictionary; 77 first_of_dictionaries = single_dictionary;
77 dictionaries_pref.SetValue( 78 dictionaries_pref.SetValue(
78 std::vector<std::string>(1, first_of_dictionaries)); 79 std::vector<std::string>(1, first_of_dictionaries));
79 } 80 }
80 81
81 single_dictionary_pref.SetValue(""); 82 single_dictionary_pref.SetValue("");
82 #endif // defined(USE_BROWSER_SPELLCHECKER) 83 #endif // defined(USE_BROWSER_SPELLCHECKER)
83 84
84 std::string language_code; 85 std::string language_code;
85 std::string country_code; 86 std::string country_code;
86 spellcheck::GetISOLanguageCountryCodeFromLocale( 87 spellcheck::GetISOLanguageCountryCodeFromLocale(
87 first_of_dictionaries, &language_code, &country_code); 88 first_of_dictionaries, &language_code, &country_code);
88 feedback_sender_.reset(new spellcheck::FeedbackSender( 89 feedback_sender_.reset(new spellcheck::FeedbackSender(
89 content::BrowserContext::GetDefaultStoragePartition(context)-> 90 content::BrowserContext::GetDefaultStoragePartition(context)->
90 GetURLRequestContext(), 91 GetURLRequestContext(),
91 language_code, country_code)); 92 language_code, country_code));
92 93
93 pref_change_registrar_.Add( 94 pref_change_registrar_.Add(
94 prefs::kSpellCheckDictionaries, 95 spellcheck::prefs::kSpellCheckDictionaries,
95 base::Bind(&SpellcheckService::OnSpellCheckDictionariesChanged, 96 base::Bind(&SpellcheckService::OnSpellCheckDictionariesChanged,
96 base::Unretained(this))); 97 base::Unretained(this)));
97 pref_change_registrar_.Add( 98 pref_change_registrar_.Add(
98 prefs::kSpellCheckUseSpellingService, 99 spellcheck::prefs::kSpellCheckUseSpellingService,
99 base::Bind(&SpellcheckService::OnUseSpellingServiceChanged, 100 base::Bind(&SpellcheckService::OnUseSpellingServiceChanged,
100 base::Unretained(this))); 101 base::Unretained(this)));
101 pref_change_registrar_.Add( 102 pref_change_registrar_.Add(
102 prefs::kAcceptLanguages, 103 prefs::kAcceptLanguages,
103 base::Bind(&SpellcheckService::OnAcceptLanguagesChanged, 104 base::Bind(&SpellcheckService::OnAcceptLanguagesChanged,
104 base::Unretained(this))); 105 base::Unretained(this)));
105 pref_change_registrar_.Add( 106 pref_change_registrar_.Add(spellcheck::prefs::kEnableContinuousSpellcheck,
106 prefs::kEnableContinuousSpellcheck, 107 base::Bind(&SpellcheckService::InitForAllRenderers,
107 base::Bind(&SpellcheckService::InitForAllRenderers, 108 base::Unretained(this)));
108 base::Unretained(this)));
109 109
110 custom_dictionary_.reset(new SpellcheckCustomDictionary(context_->GetPath())); 110 custom_dictionary_.reset(new SpellcheckCustomDictionary(context_->GetPath()));
111 custom_dictionary_->AddObserver(this); 111 custom_dictionary_->AddObserver(this);
112 custom_dictionary_->Load(); 112 custom_dictionary_->Load();
113 113
114 registrar_.Add(this, 114 registrar_.Add(this,
115 content::NOTIFICATION_RENDERER_PROCESS_CREATED, 115 content::NOTIFICATION_RENDERER_PROCESS_CREATED,
116 content::NotificationService::AllSources()); 116 content::NotificationService::AllSources());
117 117
118 LoadHunspellDictionaries(); 118 LoadHunspellDictionaries();
119 UpdateFeedbackSenderState(); 119 UpdateFeedbackSenderState();
120 } 120 }
121 121
122 SpellcheckService::~SpellcheckService() { 122 SpellcheckService::~SpellcheckService() {
123 // Remove pref observers 123 // Remove pref observers
124 pref_change_registrar_.RemoveAll(); 124 pref_change_registrar_.RemoveAll();
125 } 125 }
126 126
127 base::WeakPtr<SpellcheckService> SpellcheckService::GetWeakPtr() { 127 base::WeakPtr<SpellcheckService> SpellcheckService::GetWeakPtr() {
128 return weak_ptr_factory_.GetWeakPtr(); 128 return weak_ptr_factory_.GetWeakPtr();
129 } 129 }
130 130
131 #if !defined(OS_MACOSX) 131 #if !defined(OS_MACOSX)
132 // static 132 // static
133 void SpellcheckService::GetDictionaries(base::SupportsUserData* browser_context, 133 void SpellcheckService::GetDictionaries(base::SupportsUserData* browser_context,
134 std::vector<Dictionary>* dictionaries) { 134 std::vector<Dictionary>* dictionaries) {
135 PrefService* prefs = user_prefs::UserPrefs::Get(browser_context); 135 PrefService* prefs = user_prefs::UserPrefs::Get(browser_context);
136 std::set<std::string> spellcheck_dictionaries; 136 std::set<std::string> spellcheck_dictionaries;
137 for (const auto& value : *prefs->GetList(prefs::kSpellCheckDictionaries)) { 137 for (const auto& value :
138 *prefs->GetList(spellcheck::prefs::kSpellCheckDictionaries)) {
138 std::string dictionary; 139 std::string dictionary;
139 if (value->GetAsString(&dictionary)) 140 if (value->GetAsString(&dictionary))
140 spellcheck_dictionaries.insert(dictionary); 141 spellcheck_dictionaries.insert(dictionary);
141 } 142 }
142 143
143 dictionaries->clear(); 144 dictionaries->clear();
144 std::vector<std::string> accept_languages = 145 std::vector<std::string> accept_languages =
145 base::SplitString(prefs->GetString(prefs::kAcceptLanguages), ",", 146 base::SplitString(prefs->GetString(prefs::kAcceptLanguages), ",",
146 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 147 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
147 for (const auto& accept_language : accept_languages) { 148 for (const auto& accept_language : accept_languages) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 bdict_languages.push_back(SpellCheckBDictLanguage()); 191 bdict_languages.push_back(SpellCheckBDictLanguage());
191 bdict_languages.back().language = hunspell_dictionary->GetLanguage(); 192 bdict_languages.back().language = hunspell_dictionary->GetLanguage();
192 bdict_languages.back().file = 193 bdict_languages.back().file =
193 hunspell_dictionary->GetDictionaryFile().IsValid() 194 hunspell_dictionary->GetDictionaryFile().IsValid()
194 ? IPC::GetPlatformFileForTransit( 195 ? IPC::GetPlatformFileForTransit(
195 hunspell_dictionary->GetDictionaryFile().GetPlatformFile(), 196 hunspell_dictionary->GetDictionaryFile().GetPlatformFile(),
196 false) 197 false)
197 : IPC::InvalidPlatformFileForTransit(); 198 : IPC::InvalidPlatformFileForTransit();
198 } 199 }
199 200
200 bool enabled = prefs->GetBoolean(prefs::kEnableContinuousSpellcheck) && 201 bool enabled =
201 !bdict_languages.empty(); 202 prefs->GetBoolean(spellcheck::prefs::kEnableContinuousSpellcheck) &&
203 !bdict_languages.empty();
202 process->Send(new SpellCheckMsg_Init( 204 process->Send(new SpellCheckMsg_Init(
203 bdict_languages, 205 bdict_languages,
204 enabled ? custom_dictionary_->GetWords() : std::set<std::string>())); 206 enabled ? custom_dictionary_->GetWords() : std::set<std::string>()));
205 process->Send(new SpellCheckMsg_EnableSpellCheck(enabled)); 207 process->Send(new SpellCheckMsg_EnableSpellCheck(enabled));
206 } 208 }
207 209
208 SpellCheckHostMetrics* SpellcheckService::GetMetrics() const { 210 SpellCheckHostMetrics* SpellcheckService::GetMetrics() const {
209 return metrics_.get(); 211 return metrics_.get();
210 } 212 }
211 213
212 SpellcheckCustomDictionary* SpellcheckService::GetCustomDictionary() { 214 SpellcheckCustomDictionary* SpellcheckService::GetCustomDictionary() {
213 return custom_dictionary_.get(); 215 return custom_dictionary_.get();
214 } 216 }
215 217
216 void SpellcheckService::LoadHunspellDictionaries() { 218 void SpellcheckService::LoadHunspellDictionaries() {
217 hunspell_dictionaries_.clear(); 219 hunspell_dictionaries_.clear();
218 220
219 PrefService* prefs = user_prefs::UserPrefs::Get(context_); 221 PrefService* prefs = user_prefs::UserPrefs::Get(context_);
220 DCHECK(prefs); 222 DCHECK(prefs);
221 223
222 const base::ListValue* dictionary_values = 224 const base::ListValue* dictionary_values =
223 prefs->GetList(prefs::kSpellCheckDictionaries); 225 prefs->GetList(spellcheck::prefs::kSpellCheckDictionaries);
224 226
225 for (const auto& dictionary_value : *dictionary_values) { 227 for (const auto& dictionary_value : *dictionary_values) {
226 std::string dictionary; 228 std::string dictionary;
227 dictionary_value->GetAsString(&dictionary); 229 dictionary_value->GetAsString(&dictionary);
228 hunspell_dictionaries_.push_back(new SpellcheckHunspellDictionary( 230 hunspell_dictionaries_.push_back(new SpellcheckHunspellDictionary(
229 dictionary, 231 dictionary,
230 content::BrowserContext::GetDefaultStoragePartition(context_)-> 232 content::BrowserContext::GetDefaultStoragePartition(context_)->
231 GetURLRequestContext(), 233 GetURLRequestContext(),
232 this)); 234 this));
233 hunspell_dictionaries_.back()->AddObserver(this); 235 hunspell_dictionaries_.back()->AddObserver(this);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 UpdateFeedbackSenderState(); 328 UpdateFeedbackSenderState();
327 329
328 // If there are no hunspell dictionaries to load, then immediately let the 330 // If there are no hunspell dictionaries to load, then immediately let the
329 // renderers know the new state. 331 // renderers know the new state.
330 if (hunspell_dictionaries_.empty()) 332 if (hunspell_dictionaries_.empty())
331 InitForAllRenderers(); 333 InitForAllRenderers();
332 } 334 }
333 335
334 void SpellcheckService::OnUseSpellingServiceChanged() { 336 void SpellcheckService::OnUseSpellingServiceChanged() {
335 bool enabled = pref_change_registrar_.prefs()->GetBoolean( 337 bool enabled = pref_change_registrar_.prefs()->GetBoolean(
336 prefs::kSpellCheckUseSpellingService); 338 spellcheck::prefs::kSpellCheckUseSpellingService);
337 if (metrics_) 339 if (metrics_)
338 metrics_->RecordSpellingServiceStats(enabled); 340 metrics_->RecordSpellingServiceStats(enabled);
339 UpdateFeedbackSenderState(); 341 UpdateFeedbackSenderState();
340 } 342 }
341 343
342 void SpellcheckService::OnAcceptLanguagesChanged() { 344 void SpellcheckService::OnAcceptLanguagesChanged() {
343 PrefService* prefs = user_prefs::UserPrefs::Get(context_); 345 PrefService* prefs = user_prefs::UserPrefs::Get(context_);
344 std::vector<std::string> accept_languages = 346 std::vector<std::string> accept_languages =
345 base::SplitString(prefs->GetString(prefs::kAcceptLanguages), ",", 347 base::SplitString(prefs->GetString(prefs::kAcceptLanguages), ",",
346 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 348 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
347 std::transform(accept_languages.begin(), accept_languages.end(), 349 std::transform(accept_languages.begin(), accept_languages.end(),
348 accept_languages.begin(), 350 accept_languages.begin(),
349 &spellcheck::GetCorrespondingSpellCheckLanguage); 351 &spellcheck::GetCorrespondingSpellCheckLanguage);
350 352
351 StringListPrefMember dictionaries_pref; 353 StringListPrefMember dictionaries_pref;
352 dictionaries_pref.Init(prefs::kSpellCheckDictionaries, prefs); 354 dictionaries_pref.Init(spellcheck::prefs::kSpellCheckDictionaries, prefs);
353 std::vector<std::string> dictionaries = dictionaries_pref.GetValue(); 355 std::vector<std::string> dictionaries = dictionaries_pref.GetValue();
354 std::vector<std::string> filtered_dictionaries; 356 std::vector<std::string> filtered_dictionaries;
355 357
356 for (const auto& dictionary : dictionaries) { 358 for (const auto& dictionary : dictionaries) {
357 if (std::find(accept_languages.begin(), accept_languages.end(), 359 if (std::find(accept_languages.begin(), accept_languages.end(),
358 dictionary) != accept_languages.end()) { 360 dictionary) != accept_languages.end()) {
359 filtered_dictionaries.push_back(dictionary); 361 filtered_dictionaries.push_back(dictionary);
360 } 362 }
361 } 363 }
362 364
363 dictionaries_pref.SetValue(filtered_dictionaries); 365 dictionaries_pref.SetValue(filtered_dictionaries);
364 } 366 }
365 367
366 void SpellcheckService::UpdateFeedbackSenderState() { 368 void SpellcheckService::UpdateFeedbackSenderState() {
367 std::string feedback_language; 369 std::string feedback_language;
368 if (!hunspell_dictionaries_.empty()) 370 if (!hunspell_dictionaries_.empty())
369 feedback_language = hunspell_dictionaries_.front()->GetLanguage(); 371 feedback_language = hunspell_dictionaries_.front()->GetLanguage();
370 std::string language_code; 372 std::string language_code;
371 std::string country_code; 373 std::string country_code;
372 spellcheck::GetISOLanguageCountryCodeFromLocale( 374 spellcheck::GetISOLanguageCountryCodeFromLocale(
373 feedback_language, &language_code, &country_code); 375 feedback_language, &language_code, &country_code);
374 feedback_sender_->OnLanguageCountryChange(language_code, country_code); 376 feedback_sender_->OnLanguageCountryChange(language_code, country_code);
375 if (SpellingServiceClient::IsAvailable( 377 if (SpellingServiceClient::IsAvailable(
376 context_, SpellingServiceClient::SPELLCHECK)) { 378 context_, SpellingServiceClient::SPELLCHECK)) {
377 feedback_sender_->StartFeedbackCollection(); 379 feedback_sender_->StartFeedbackCollection();
378 } else { 380 } else {
379 feedback_sender_->StopFeedbackCollection(); 381 feedback_sender_->StopFeedbackCollection();
380 } 382 }
381 } 383 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698