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

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

Issue 1665023002: Cheer up spell-checking code (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: More descriptive variable name Created 4 years, 10 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) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 // The |FeedbackSender| object stores the user feedback to spellcheck 5 // The |FeedbackSender| object stores the user feedback to spellcheck
6 // suggestions in a |Feedback| object. 6 // suggestions in a |Feedback| object.
7 // 7 //
8 // When spelling service returns spellcheck results, these results first arrive 8 // When spelling service returns spellcheck results, these results first arrive
9 // in |FeedbackSender| to assign hash identifiers for each 9 // in |FeedbackSender| to assign hash identifiers for each
10 // misspelling-suggestion pair. If the spelling service identifies the same 10 // misspelling-suggestion pair. If the spelling service identifies the same
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 start + result.length, 86 start + result.length,
87 text, 87 text,
88 chrome::spellcheck_common::kContextWordCount); 88 chrome::spellcheck_common::kContextWordCount);
89 return Misspelling(context, 89 return Misspelling(context,
90 start, 90 start,
91 result.length, 91 result.length,
92 std::vector<base::string16>(1, result.replacement), 92 std::vector<base::string16>(1, result.replacement),
93 result.hash); 93 result.hash);
94 } 94 }
95 95
96 // Builds suggestion info from |suggestions|. The caller owns the result. 96 // Builds suggestion info from |suggestions|.
97 base::ListValue* BuildSuggestionInfo( 97 scoped_ptr<base::ListValue> BuildSuggestionInfo(
98 const std::vector<Misspelling>& suggestions, 98 const std::vector<Misspelling>& misspellings,
99 bool is_first_feedback_batch) { 99 bool is_first_feedback_batch) {
100 base::ListValue* list = new base::ListValue; 100 scoped_ptr<base::ListValue> list(new base::ListValue);
101 for (std::vector<Misspelling>::const_iterator suggestion_it = 101 for (const auto& raw_misspelling : misspellings) {
102 suggestions.begin(); 102 scoped_ptr<base::DictionaryValue> misspelling(
103 suggestion_it != suggestions.end(); 103 SerializeMisspelling(raw_misspelling));
104 ++suggestion_it) { 104 misspelling->SetBoolean("isFirstInSession", is_first_feedback_batch);
105 base::DictionaryValue* suggestion = SerializeMisspelling(*suggestion_it); 105 misspelling->SetBoolean("isAutoCorrection", false);
106 suggestion->SetBoolean("isFirstInSession", is_first_feedback_batch); 106 list->Append(misspelling.release());
107 suggestion->SetBoolean("isAutoCorrection", false);
108 list->Append(suggestion);
109 } 107 }
110 return list; 108 return list;
111 } 109 }
112 110
113 // Builds feedback parameters from |suggestion_info|, |language|, and |country|. 111 // Builds feedback parameters from |suggestion_info|, |language|, and |country|.
114 // Takes ownership of |suggestion_list|. The caller owns the result. 112 // Takes ownership of |suggestion_list|.
115 base::DictionaryValue* BuildParams(base::ListValue* suggestion_info, 113 scoped_ptr<base::DictionaryValue> BuildParams(
116 const std::string& language, 114 scoped_ptr<base::ListValue> suggestion_info,
117 const std::string& country) { 115 const std::string& language,
118 base::DictionaryValue* params = new base::DictionaryValue; 116 const std::string& country) {
119 params->Set("suggestionInfo", suggestion_info); 117 scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue);
118 params->Set("suggestionInfo", suggestion_info.release());
120 params->SetString("key", google_apis::GetAPIKey()); 119 params->SetString("key", google_apis::GetAPIKey());
121 params->SetString("language", language); 120 params->SetString("language", language);
122 params->SetString("originCountry", country); 121 params->SetString("originCountry", country);
123 params->SetString("clientName", "Chrome"); 122 params->SetString("clientName", "Chrome");
124 return params; 123 return params;
125 } 124 }
126 125
127 // Builds feedback data from |params|. Takes ownership of |params|. The caller 126 // Builds feedback data from |params|. Takes ownership of |params|.
128 // owns the result. 127 scoped_ptr<base::Value> BuildFeedbackValue(
129 base::Value* BuildFeedbackValue(base::DictionaryValue* params, 128 scoped_ptr<base::DictionaryValue> params,
130 const std::string& api_version) { 129 const std::string& api_version) {
131 base::DictionaryValue* result = new base::DictionaryValue; 130 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue);
132 result->Set("params", params); 131 result->Set("params", params.release());
133 result->SetString("method", "spelling.feedback"); 132 result->SetString("method", "spelling.feedback");
134 result->SetString("apiVersion", api_version); 133 result->SetString("apiVersion", api_version);
135 return result; 134 return std::move(result);
136 } 135 }
137 136
138 // Returns true if the misspelling location is within text bounds. 137 // Returns true if the misspelling location is within text bounds.
139 bool IsInBounds(int misspelling_location, 138 bool IsInBounds(int misspelling_location,
140 int misspelling_length, 139 int misspelling_length,
141 size_t text_length) { 140 size_t text_length) {
142 return misspelling_location >= 0 && misspelling_length > 0 && 141 return misspelling_location >= 0 && misspelling_length > 0 &&
143 static_cast<size_t>(misspelling_location) < text_length && 142 static_cast<size_t>(misspelling_location) < text_length &&
144 static_cast<size_t>(misspelling_location + misspelling_length) <= 143 static_cast<size_t>(misspelling_location + misspelling_length) <=
145 text_length; 144 text_length;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 void FeedbackSender::AddedToDictionary(uint32_t hash) { 198 void FeedbackSender::AddedToDictionary(uint32_t hash) {
200 Misspelling* misspelling = feedback_.GetMisspelling(hash); 199 Misspelling* misspelling = feedback_.GetMisspelling(hash);
201 // GetMisspelling() returns null for flushed feedback. Feedback is flushed 200 // GetMisspelling() returns null for flushed feedback. Feedback is flushed
202 // when the session expires every |kSessionHours| hours. 201 // when the session expires every |kSessionHours| hours.
203 if (!misspelling) 202 if (!misspelling)
204 return; 203 return;
205 misspelling->action.set_type(SpellcheckAction::TYPE_ADD_TO_DICT); 204 misspelling->action.set_type(SpellcheckAction::TYPE_ADD_TO_DICT);
206 misspelling->timestamp = base::Time::Now(); 205 misspelling->timestamp = base::Time::Now();
207 const std::set<uint32_t>& hashes = 206 const std::set<uint32_t>& hashes =
208 feedback_.FindMisspellings(GetMisspelledString(*misspelling)); 207 feedback_.FindMisspellings(GetMisspelledString(*misspelling));
209 for (std::set<uint32_t>::const_iterator hash_it = hashes.begin(); 208 for (uint32_t hash : hashes) {
210 hash_it != hashes.end(); ++hash_it) { 209 Misspelling* duplicate_misspelling = feedback_.GetMisspelling(hash);
211 Misspelling* duplicate_misspelling = feedback_.GetMisspelling(*hash_it);
212 if (!duplicate_misspelling || duplicate_misspelling->action.IsFinal()) 210 if (!duplicate_misspelling || duplicate_misspelling->action.IsFinal())
213 continue; 211 continue;
214 duplicate_misspelling->action.set_type(SpellcheckAction::TYPE_ADD_TO_DICT); 212 duplicate_misspelling->action.set_type(SpellcheckAction::TYPE_ADD_TO_DICT);
215 duplicate_misspelling->timestamp = misspelling->timestamp; 213 duplicate_misspelling->timestamp = misspelling->timestamp;
216 } 214 }
217 } 215 }
218 216
219 void FeedbackSender::RecordInDictionary(uint32_t hash) { 217 void FeedbackSender::RecordInDictionary(uint32_t hash) {
220 Misspelling* misspelling = feedback_.GetMisspelling(hash); 218 Misspelling* misspelling = feedback_.GetMisspelling(hash);
221 // GetMisspelling() returns null for flushed feedback. Feedback is flushed 219 // GetMisspelling() returns null for flushed feedback. Feedback is flushed
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 return; 274 return;
277 275
278 // Generate a map of marker offsets to marker hashes. This map helps to 276 // Generate a map of marker offsets to marker hashes. This map helps to
279 // efficiently lookup feedback data based on the position of the misspelling 277 // efficiently lookup feedback data based on the position of the misspelling
280 // in text. 278 // in text.
281 typedef std::map<size_t, uint32_t> MarkerMap; 279 typedef std::map<size_t, uint32_t> MarkerMap;
282 MarkerMap marker_map; 280 MarkerMap marker_map;
283 for (size_t i = 0; i < markers.size(); ++i) 281 for (size_t i = 0; i < markers.size(); ++i)
284 marker_map[markers[i].offset] = markers[i].hash; 282 marker_map[markers[i].offset] = markers[i].hash;
285 283
286 for (std::vector<SpellCheckResult>::iterator result_it = results->begin(); 284 for (auto& result : *results) {
287 result_it != results->end(); 285 if (!IsInBounds(result.location, result.length, text.length()))
288 ++result_it) {
289 if (!IsInBounds(result_it->location, result_it->length, text.length()))
290 continue; 286 continue;
291 MarkerMap::const_iterator marker_it = marker_map.find(result_it->location); 287 MarkerMap::const_iterator marker_it = marker_map.find(result.location);
292 if (marker_it != marker_map.end() && 288 if (marker_it != marker_map.end() &&
293 feedback_.HasMisspelling(marker_it->second)) { 289 feedback_.HasMisspelling(marker_it->second)) {
294 // If the renderer already has a marker for this spellcheck result, then 290 // If the renderer already has a marker for this spellcheck result, then
295 // set the hash of the spellcheck result to be the same as the marker. 291 // set the hash of the spellcheck result to be the same as the marker.
296 result_it->hash = marker_it->second; 292 result.hash = marker_it->second;
297 } else { 293 } else {
298 // If the renderer does not yet have a marker for this spellcheck result, 294 // If the renderer does not yet have a marker for this spellcheck result,
299 // then generate a new hash for the spellcheck result. 295 // then generate a new hash for the spellcheck result.
300 result_it->hash = BuildHash(session_start_, ++misspelling_counter_); 296 result.hash = BuildHash(session_start_, ++misspelling_counter_);
301 } 297 }
302 // Save the feedback data for the spellcheck result. 298 // Save the feedback data for the spellcheck result.
303 feedback_.AddMisspelling(renderer_process_id, 299 feedback_.AddMisspelling(renderer_process_id, BuildFeedback(result, text));
304 BuildFeedback(*result_it, text));
305 } 300 }
306 } 301 }
307 302
308 void FeedbackSender::OnLanguageCountryChange(const std::string& language, 303 void FeedbackSender::OnLanguageCountryChange(const std::string& language,
309 const std::string& country) { 304 const std::string& country) {
310 FlushFeedback(); 305 FlushFeedback();
311 language_ = language; 306 language_ = language;
312 country_ = country; 307 country_ = country;
313 } 308 }
314 309
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 it.Advance()) { 363 it.Advance()) {
369 alive_renderers.insert(it.GetCurrentValue()->GetID()); 364 alive_renderers.insert(it.GetCurrentValue()->GetID());
370 it.GetCurrentValue()->Send(new SpellCheckMsg_RequestDocumentMarkers()); 365 it.GetCurrentValue()->Send(new SpellCheckMsg_RequestDocumentMarkers());
371 } 366 }
372 367
373 // Asynchronously send out the feedback for all the renderers that are no 368 // Asynchronously send out the feedback for all the renderers that are no
374 // longer alive. 369 // longer alive.
375 std::vector<int> known_renderers = feedback_.GetRendersWithMisspellings(); 370 std::vector<int> known_renderers = feedback_.GetRendersWithMisspellings();
376 std::sort(known_renderers.begin(), known_renderers.end()); 371 std::sort(known_renderers.begin(), known_renderers.end());
377 std::vector<int> dead_renderers = 372 std::vector<int> dead_renderers =
378 base::STLSetDifference<std::vector<int> >(known_renderers, 373 base::STLSetDifference<std::vector<int>>(known_renderers,
379 alive_renderers); 374 alive_renderers);
380 for (std::vector<int>::const_iterator it = dead_renderers.begin(); 375 for (int renderer_process_id : dead_renderers) {
381 it != dead_renderers.end();
382 ++it) {
383 base::ThreadTaskRunnerHandle::Get()->PostTask( 376 base::ThreadTaskRunnerHandle::Get()->PostTask(
384 FROM_HERE, base::Bind(&FeedbackSender::OnReceiveDocumentMarkers, 377 FROM_HERE,
385 AsWeakPtr(), *it, std::vector<uint32_t>())); 378 base::Bind(&FeedbackSender::OnReceiveDocumentMarkers, AsWeakPtr(),
379 renderer_process_id, std::vector<uint32_t>()));
386 } 380 }
387 } 381 }
388 382
389 void FeedbackSender::FlushFeedback() { 383 void FeedbackSender::FlushFeedback() {
390 if (feedback_.Empty()) 384 if (feedback_.Empty())
391 return; 385 return;
392 feedback_.FinalizeAllMisspellings(); 386 feedback_.FinalizeAllMisspellings();
393 SendFeedback(feedback_.GetAllMisspellings(), 387 SendFeedback(feedback_.GetAllMisspellings(),
394 renderers_sent_feedback_.empty()); 388 renderers_sent_feedback_.empty());
395 feedback_.Clear(); 389 feedback_.Clear();
(...skipping 17 matching lines...) Expand all
413 net::URLFetcher* sender = 407 net::URLFetcher* sender =
414 net::URLFetcher::Create(kUrlFetcherId, feedback_service_url_, 408 net::URLFetcher::Create(kUrlFetcherId, feedback_service_url_,
415 net::URLFetcher::POST, this).release(); 409 net::URLFetcher::POST, this).release();
416 data_use_measurement::DataUseUserData::AttachToFetcher( 410 data_use_measurement::DataUseUserData::AttachToFetcher(
417 sender, data_use_measurement::DataUseUserData::SPELL_CHECKER); 411 sender, data_use_measurement::DataUseUserData::SPELL_CHECKER);
418 sender->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 412 sender->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
419 net::LOAD_DO_NOT_SAVE_COOKIES); 413 net::LOAD_DO_NOT_SAVE_COOKIES);
420 sender->SetUploadData("application/json", feedback); 414 sender->SetUploadData("application/json", feedback);
421 senders_.push_back(sender); 415 senders_.push_back(sender);
422 416
423 // Request context is NULL in testing. 417 // Request context is nullptr in testing.
424 if (request_context_.get()) { 418 if (request_context_.get()) {
425 sender->SetRequestContext(request_context_.get()); 419 sender->SetRequestContext(request_context_.get());
426 sender->Start(); 420 sender->Start();
427 } 421 }
428 } 422 }
429 423
430 } // namespace spellcheck 424 } // namespace spellcheck
OLDNEW
« no previous file with comments | « chrome/browser/spellchecker/feedback.cc ('k') | chrome/browser/spellchecker/feedback_sender_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698