OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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 |
11 // misspelling as already displayed to the user, then |FeedbackSender| reuses | 11 // misspelling as already displayed to the user, then |FeedbackSender| reuses |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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); |
groby-ooo-7-16
2016/02/09 20:20:26
Does this need to be std::move? The move ctor _sho
Kevin Bailey
2016/02/09 22:26:39
../../chrome/browser/spellchecker/feedback_sender.
| |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 : dead_renderers) { |
groby-ooo-7-16
2016/02/09 20:20:26
nit: renderer_process_id (I wish we had a type for
Kevin Bailey
2016/02/09 22:26:39
Done.
| |
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, base::Bind(&FeedbackSender::OnReceiveDocumentMarkers, |
385 AsWeakPtr(), *it, std::vector<uint32_t>())); | 378 AsWeakPtr(), renderer, std::vector<uint32_t>())); |
386 } | 379 } |
387 } | 380 } |
388 | 381 |
389 void FeedbackSender::FlushFeedback() { | 382 void FeedbackSender::FlushFeedback() { |
390 if (feedback_.Empty()) | 383 if (feedback_.Empty()) |
391 return; | 384 return; |
392 feedback_.FinalizeAllMisspellings(); | 385 feedback_.FinalizeAllMisspellings(); |
393 SendFeedback(feedback_.GetAllMisspellings(), | 386 SendFeedback(feedback_.GetAllMisspellings(), |
394 renderers_sent_feedback_.empty()); | 387 renderers_sent_feedback_.empty()); |
395 feedback_.Clear(); | 388 feedback_.Clear(); |
(...skipping 17 matching lines...) Expand all Loading... | |
413 net::URLFetcher* sender = | 406 net::URLFetcher* sender = |
414 net::URLFetcher::Create(kUrlFetcherId, feedback_service_url_, | 407 net::URLFetcher::Create(kUrlFetcherId, feedback_service_url_, |
415 net::URLFetcher::POST, this).release(); | 408 net::URLFetcher::POST, this).release(); |
416 data_use_measurement::DataUseUserData::AttachToFetcher( | 409 data_use_measurement::DataUseUserData::AttachToFetcher( |
417 sender, data_use_measurement::DataUseUserData::SPELL_CHECKER); | 410 sender, data_use_measurement::DataUseUserData::SPELL_CHECKER); |
418 sender->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 411 sender->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
419 net::LOAD_DO_NOT_SAVE_COOKIES); | 412 net::LOAD_DO_NOT_SAVE_COOKIES); |
420 sender->SetUploadData("application/json", feedback); | 413 sender->SetUploadData("application/json", feedback); |
421 senders_.push_back(sender); | 414 senders_.push_back(sender); |
422 | 415 |
423 // Request context is NULL in testing. | 416 // Request context is nullptr in testing. |
424 if (request_context_.get()) { | 417 if (request_context_.get()) { |
425 sender->SetRequestContext(request_context_.get()); | 418 sender->SetRequestContext(request_context_.get()); |
426 sender->Start(); | 419 sender->Start(); |
427 } | 420 } |
428 } | 421 } |
429 | 422 |
430 } // namespace spellcheck | 423 } // namespace spellcheck |
OLD | NEW |