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

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: 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 25 matching lines...) Expand all
36 #include "base/hash.h" 36 #include "base/hash.h"
37 #include "base/json/json_writer.h" 37 #include "base/json/json_writer.h"
38 #include "base/location.h" 38 #include "base/location.h"
39 #include "base/metrics/field_trial.h" 39 #include "base/metrics/field_trial.h"
40 #include "base/single_thread_task_runner.h" 40 #include "base/single_thread_task_runner.h"
41 #include "base/stl_util.h" 41 #include "base/stl_util.h"
42 #include "base/strings/string_number_conversions.h" 42 #include "base/strings/string_number_conversions.h"
43 #include "base/strings/stringprintf.h" 43 #include "base/strings/stringprintf.h"
44 #include "base/thread_task_runner_handle.h" 44 #include "base/thread_task_runner_handle.h"
45 #include "base/values.h" 45 #include "base/values.h"
46 #include "chrome/browser/spellchecker/set_difference_container.h"
46 #include "chrome/browser/spellchecker/word_trimmer.h" 47 #include "chrome/browser/spellchecker/word_trimmer.h"
47 #include "chrome/common/chrome_switches.h" 48 #include "chrome/common/chrome_switches.h"
48 #include "chrome/common/spellcheck_common.h" 49 #include "chrome/common/spellcheck_common.h"
49 #include "chrome/common/spellcheck_marker.h" 50 #include "chrome/common/spellcheck_marker.h"
50 #include "chrome/common/spellcheck_messages.h" 51 #include "chrome/common/spellcheck_messages.h"
51 #include "components/data_use_measurement/core/data_use_user_data.h" 52 #include "components/data_use_measurement/core/data_use_user_data.h"
52 #include "content/public/browser/render_process_host.h" 53 #include "content/public/browser/render_process_host.h"
53 #include "google_apis/google_api_keys.h" 54 #include "google_apis/google_api_keys.h"
54 #include "net/base/load_flags.h" 55 #include "net/base/load_flags.h"
55 #include "net/url_request/url_fetcher.h" 56 #include "net/url_request/url_fetcher.h"
56 #include "net/url_request/url_request_context_getter.h" 57 #include "net/url_request/url_request_context_getter.h"
57 58
58 namespace spellcheck { 59 namespace spellcheck {
59 60
60 namespace { 61 namespace {
61 62
62 const size_t kMaxFeedbackSizeBytes = 10 * 1024 * 1024; // 10 MB 63 const size_t kMaxFeedbackSizeBytes = 10 * 1024 * 1024; // 10 MB
63 64
64 // The default URL where feedback data is sent. 65 // The default URL where feedback data is sent.
65 const char kFeedbackServiceURL[] = "https://www.googleapis.com/rpc"; 66 const char kFeedbackServiceURL[] = "https://www.googleapis.com/rpc";
66 67
67 // The minimum number of seconds between sending batches of feedback. 68 // The minimum number of seconds between sending batches of feedback.
68 const int kMinIntervalSeconds = 5; 69 const int kMinIntervalSeconds = 5;
69 70
70 // Returns a hash of |session_start|, the current timestamp, and 71 // Returns a hash of |session_start|, the current timestamp, and
71 // |suggestion_index|. 72 // |suggestion_index|.
72 uint32_t BuildHash(const base::Time& session_start, size_t suggestion_index) { 73 uint32_t BuildHash(const base::Time& session_start, size_t suggestion_index) {
73 return base::Hash( 74 return base::Hash(base::StringPrintf(
74 base::StringPrintf("%" PRId64 "%" PRId64 "%" PRIuS, 75 "%" PRId64 "%" PRId64 "%" PRIuS, session_start.ToInternalValue(),
75 session_start.ToInternalValue(), 76 base::Time::Now().ToInternalValue(), suggestion_index));
76 base::Time::Now().ToInternalValue(),
77 suggestion_index));
78 } 77 }
79 78
80 // Returns a pending feedback data structure for the spellcheck |result| and 79 // Returns a pending feedback data structure for the spellcheck |result| and
81 // |text|. 80 // |text|.
82 Misspelling BuildFeedback(const SpellCheckResult& result, 81 Misspelling BuildFeedback(const SpellCheckResult& result,
83 const base::string16& text) { 82 const base::string16& text) {
84 size_t start = result.location; 83 size_t start = result.location;
85 base::string16 context = TrimWords(&start, 84 base::string16 context =
86 start + result.length, 85 TrimWords(&start, start + result.length, text,
87 text, 86 chrome::spellcheck_common::kContextWordCount);
88 chrome::spellcheck_common::kContextWordCount); 87 return Misspelling(context, start, result.length,
89 return Misspelling(context,
90 start,
91 result.length,
92 std::vector<base::string16>(1, result.replacement), 88 std::vector<base::string16>(1, result.replacement),
93 result.hash); 89 result.hash);
94 } 90 }
95 91
96 // Builds suggestion info from |suggestions|. The caller owns the result. 92 // Builds suggestion info from |suggestions|. The caller owns the result.
97 base::ListValue* BuildSuggestionInfo( 93 scoped_ptr<base::ListValue> BuildSuggestionInfo(
98 const std::vector<Misspelling>& suggestions, 94 const std::vector<Misspelling>& suggestions, bool is_first_feedback_batch) {
99 bool is_first_feedback_batch) { 95 scoped_ptr<base::ListValue> list(new base::ListValue);
100 base::ListValue* list = new base::ListValue;
101 for (std::vector<Misspelling>::const_iterator suggestion_it = 96 for (std::vector<Misspelling>::const_iterator suggestion_it =
please use gerrit instead 2016/02/03 23:59:10 Let's switch to "for (const auto& suggestion : sug
Kevin Bailey 2016/02/04 16:34:11 This was probably the most dangerous change, from
102 suggestions.begin(); 97 suggestions.begin();
103 suggestion_it != suggestions.end(); 98 suggestion_it != suggestions.end(); ++suggestion_it) {
104 ++suggestion_it) { 99 scoped_ptr<base::DictionaryValue> suggestion(
105 base::DictionaryValue* suggestion = SerializeMisspelling(*suggestion_it); 100 SerializeMisspelling(*suggestion_it));
106 suggestion->SetBoolean("isFirstInSession", is_first_feedback_batch); 101 suggestion->SetBoolean("isFirstInSession", is_first_feedback_batch);
107 suggestion->SetBoolean("isAutoCorrection", false); 102 suggestion->SetBoolean("isAutoCorrection", false);
108 list->Append(suggestion); 103 list->Append(suggestion.release());
109 } 104 }
110 return list; 105 return list;
111 } 106 }
112 107
113 // Builds feedback parameters from |suggestion_info|, |language|, and |country|. 108 // Builds feedback parameters from |suggestion_info|, |language|, and |country|.
114 // Takes ownership of |suggestion_list|. The caller owns the result. 109 // Takes ownership of |suggestion_list|. The caller owns the result.
115 base::DictionaryValue* BuildParams(base::ListValue* suggestion_info, 110 scoped_ptr<base::DictionaryValue> BuildParams(
116 const std::string& language, 111 scoped_ptr<base::ListValue> suggestion_info,
117 const std::string& country) { 112 const std::string& language,
118 base::DictionaryValue* params = new base::DictionaryValue; 113 const std::string& country) {
119 params->Set("suggestionInfo", suggestion_info); 114 scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue);
115 params->Set("suggestionInfo", suggestion_info.release());
120 params->SetString("key", google_apis::GetAPIKey()); 116 params->SetString("key", google_apis::GetAPIKey());
121 params->SetString("language", language); 117 params->SetString("language", language);
122 params->SetString("originCountry", country); 118 params->SetString("originCountry", country);
123 params->SetString("clientName", "Chrome"); 119 params->SetString("clientName", "Chrome");
124 return params; 120 return params;
125 } 121 }
126 122
127 // Builds feedback data from |params|. Takes ownership of |params|. The caller 123 // Builds feedback data from |params|. Takes ownership of |params|. The caller
128 // owns the result. 124 // owns the result.
129 base::Value* BuildFeedbackValue(base::DictionaryValue* params, 125 scoped_ptr<base::Value> BuildFeedbackValue(
130 const std::string& api_version) { 126 scoped_ptr<base::DictionaryValue> params,
131 base::DictionaryValue* result = new base::DictionaryValue; 127 const std::string& api_version) {
132 result->Set("params", params); 128 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue);
129 result->Set("params", params.release());
133 result->SetString("method", "spelling.feedback"); 130 result->SetString("method", "spelling.feedback");
134 result->SetString("apiVersion", api_version); 131 result->SetString("apiVersion", api_version);
135 return result; 132 return scoped_ptr<base::Value>(result.release());
please use gerrit instead 2016/02/03 23:59:10 Usually "return result;" gets the job done. If the
Kevin Bailey 2016/02/04 16:34:11 Ya, I was disappointed that it didn't automaticall
136 } 133 }
137 134
138 // Returns true if the misspelling location is within text bounds. 135 // Returns true if the misspelling location is within text bounds.
139 bool IsInBounds(int misspelling_location, 136 bool IsInBounds(int misspelling_location, int misspelling_length,
140 int misspelling_length,
141 size_t text_length) { 137 size_t text_length) {
142 return misspelling_location >= 0 && misspelling_length > 0 && 138 return misspelling_location >= 0 && misspelling_length > 0 &&
143 static_cast<size_t>(misspelling_location) < text_length && 139 static_cast<size_t>(misspelling_location) < text_length &&
144 static_cast<size_t>(misspelling_location + misspelling_length) <= 140 static_cast<size_t>(misspelling_location + misspelling_length) <=
145 text_length; 141 text_length;
146 } 142 }
147 143
148 // Returns the feedback API version. 144 // Returns the feedback API version.
149 std::string GetApiVersion() { 145 std::string GetApiVersion() {
150 // This guard is temporary. 146 // This guard is temporary.
(...skipping 24 matching lines...) Expand all
175 // TODO(rouslan): Remove the command-line switch when testing is complete. 171 // TODO(rouslan): Remove the command-line switch when testing is complete.
176 // http://crbug.com/247726 172 // http://crbug.com/247726
177 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 173 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
178 switches::kSpellingServiceFeedbackUrl)) { 174 switches::kSpellingServiceFeedbackUrl)) {
179 feedback_service_url_ = 175 feedback_service_url_ =
180 GURL(base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 176 GURL(base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
181 switches::kSpellingServiceFeedbackUrl)); 177 switches::kSpellingServiceFeedbackUrl));
182 } 178 }
183 } 179 }
184 180
185 FeedbackSender::~FeedbackSender() { 181 FeedbackSender::~FeedbackSender() {}
186 }
187 182
188 void FeedbackSender::SelectedSuggestion(uint32_t hash, int suggestion_index) { 183 void FeedbackSender::SelectedSuggestion(uint32_t hash, int suggestion_index) {
189 Misspelling* misspelling = feedback_.GetMisspelling(hash); 184 Misspelling* misspelling = feedback_.GetMisspelling(hash);
190 // GetMisspelling() returns null for flushed feedback. Feedback is flushed 185 // GetMisspelling() returns null for flushed feedback. Feedback is flushed
191 // when the session expires every |kSessionHours| hours. 186 // when the session expires every |kSessionHours| hours.
192 if (!misspelling) 187 if (!misspelling) return;
please use gerrit instead 2016/02/03 23:59:10 Which clang-format are you using? I'm surprised it
Kevin Bailey 2016/02/04 16:34:11 I'm glad you asked. depot_tools was at the end of
193 return;
194 misspelling->action.set_type(SpellcheckAction::TYPE_SELECT); 188 misspelling->action.set_type(SpellcheckAction::TYPE_SELECT);
195 misspelling->action.set_index(suggestion_index); 189 misspelling->action.set_index(suggestion_index);
196 misspelling->timestamp = base::Time::Now(); 190 misspelling->timestamp = base::Time::Now();
197 } 191 }
198 192
199 void FeedbackSender::AddedToDictionary(uint32_t hash) { 193 void FeedbackSender::AddedToDictionary(uint32_t hash) {
200 Misspelling* misspelling = feedback_.GetMisspelling(hash); 194 Misspelling* misspelling = feedback_.GetMisspelling(hash);
201 // GetMisspelling() returns null for flushed feedback. Feedback is flushed 195 // GetMisspelling() returns null for flushed feedback. Feedback is flushed
202 // when the session expires every |kSessionHours| hours. 196 // when the session expires every |kSessionHours| hours.
203 if (!misspelling) 197 if (!misspelling) return;
204 return;
205 misspelling->action.set_type(SpellcheckAction::TYPE_ADD_TO_DICT); 198 misspelling->action.set_type(SpellcheckAction::TYPE_ADD_TO_DICT);
206 misspelling->timestamp = base::Time::Now(); 199 misspelling->timestamp = base::Time::Now();
207 const std::set<uint32_t>& hashes = 200 const std::set<uint32_t>& hashes =
208 feedback_.FindMisspellings(GetMisspelledString(*misspelling)); 201 feedback_.FindMisspellings(GetMisspelledString(*misspelling));
209 for (std::set<uint32_t>::const_iterator hash_it = hashes.begin(); 202 for (std::set<uint32_t>::const_iterator hash_it = hashes.begin();
210 hash_it != hashes.end(); ++hash_it) { 203 hash_it != hashes.end(); ++hash_it) {
211 Misspelling* duplicate_misspelling = feedback_.GetMisspelling(*hash_it); 204 Misspelling* duplicate_misspelling = feedback_.GetMisspelling(*hash_it);
212 if (!duplicate_misspelling || duplicate_misspelling->action.IsFinal()) 205 if (!duplicate_misspelling || duplicate_misspelling->action.IsFinal())
213 continue; 206 continue;
214 duplicate_misspelling->action.set_type(SpellcheckAction::TYPE_ADD_TO_DICT); 207 duplicate_misspelling->action.set_type(SpellcheckAction::TYPE_ADD_TO_DICT);
215 duplicate_misspelling->timestamp = misspelling->timestamp; 208 duplicate_misspelling->timestamp = misspelling->timestamp;
216 } 209 }
217 } 210 }
218 211
219 void FeedbackSender::RecordInDictionary(uint32_t hash) { 212 void FeedbackSender::RecordInDictionary(uint32_t hash) {
220 Misspelling* misspelling = feedback_.GetMisspelling(hash); 213 Misspelling* misspelling = feedback_.GetMisspelling(hash);
221 // GetMisspelling() returns null for flushed feedback. Feedback is flushed 214 // GetMisspelling() returns null for flushed feedback. Feedback is flushed
222 // when the session expires every |kSessionHours| hours. 215 // when the session expires every |kSessionHours| hours.
223 if (!misspelling) 216 if (!misspelling) return;
224 return;
225 misspelling->action.set_type(SpellcheckAction::TYPE_IN_DICTIONARY); 217 misspelling->action.set_type(SpellcheckAction::TYPE_IN_DICTIONARY);
226 } 218 }
227 219
228 void FeedbackSender::IgnoredSuggestions(uint32_t hash) { 220 void FeedbackSender::IgnoredSuggestions(uint32_t hash) {
229 Misspelling* misspelling = feedback_.GetMisspelling(hash); 221 Misspelling* misspelling = feedback_.GetMisspelling(hash);
230 // GetMisspelling() returns null for flushed feedback. Feedback is flushed 222 // GetMisspelling() returns null for flushed feedback. Feedback is flushed
231 // when the session expires every |kSessionHours| hours. 223 // when the session expires every |kSessionHours| hours.
232 if (!misspelling) 224 if (!misspelling) return;
233 return;
234 misspelling->action.set_type(SpellcheckAction::TYPE_PENDING_IGNORE); 225 misspelling->action.set_type(SpellcheckAction::TYPE_PENDING_IGNORE);
235 misspelling->timestamp = base::Time::Now(); 226 misspelling->timestamp = base::Time::Now();
236 } 227 }
237 228
238 void FeedbackSender::ManuallyCorrected(uint32_t hash, 229 void FeedbackSender::ManuallyCorrected(uint32_t hash,
239 const base::string16& correction) { 230 const base::string16& correction) {
240 Misspelling* misspelling = feedback_.GetMisspelling(hash); 231 Misspelling* misspelling = feedback_.GetMisspelling(hash);
241 // GetMisspelling() returns null for flushed feedback. Feedback is flushed 232 // GetMisspelling() returns null for flushed feedback. Feedback is flushed
242 // when the session expires every |kSessionHours| hours. 233 // when the session expires every |kSessionHours| hours.
243 if (!misspelling) 234 if (!misspelling) return;
244 return;
245 misspelling->action.set_type(SpellcheckAction::TYPE_MANUALLY_CORRECTED); 235 misspelling->action.set_type(SpellcheckAction::TYPE_MANUALLY_CORRECTED);
246 misspelling->action.set_value(correction); 236 misspelling->action.set_value(correction);
247 misspelling->timestamp = base::Time::Now(); 237 misspelling->timestamp = base::Time::Now();
248 } 238 }
249 239
250 void FeedbackSender::OnReceiveDocumentMarkers( 240 void FeedbackSender::OnReceiveDocumentMarkers(
251 int renderer_process_id, 241 int renderer_process_id, const std::vector<uint32_t>& markers) {
252 const std::vector<uint32_t>& markers) {
253 if ((base::Time::Now() - session_start_).InHours() >= 242 if ((base::Time::Now() - session_start_).InHours() >=
254 chrome::spellcheck_common::kSessionHours) { 243 chrome::spellcheck_common::kSessionHours) {
255 FlushFeedback(); 244 FlushFeedback();
256 return; 245 return;
257 } 246 }
258 247
259 if (!feedback_.RendererHasMisspellings(renderer_process_id)) 248 if (!feedback_.RendererHasMisspellings(renderer_process_id)) return;
260 return;
261 249
262 feedback_.FinalizeRemovedMisspellings(renderer_process_id, markers); 250 feedback_.FinalizeRemovedMisspellings(renderer_process_id, markers);
263 SendFeedback(feedback_.GetMisspellingsInRenderer(renderer_process_id), 251 SendFeedback(feedback_.GetMisspellingsInRenderer(renderer_process_id),
264 !renderers_sent_feedback_.count(renderer_process_id)); 252 !renderers_sent_feedback_.count(renderer_process_id));
265 renderers_sent_feedback_.insert(renderer_process_id); 253 renderers_sent_feedback_.insert(renderer_process_id);
266 feedback_.EraseFinalizedMisspellings(renderer_process_id); 254 feedback_.EraseFinalizedMisspellings(renderer_process_id);
267 } 255 }
268 256
269 void FeedbackSender::OnSpellcheckResults( 257 void FeedbackSender::OnSpellcheckResults(
270 int renderer_process_id, 258 int renderer_process_id, const base::string16& text,
271 const base::string16& text,
272 const std::vector<SpellCheckMarker>& markers, 259 const std::vector<SpellCheckMarker>& markers,
273 std::vector<SpellCheckResult>* results) { 260 std::vector<SpellCheckResult>* results) {
274 // Don't collect feedback if not going to send it. 261 // Don't collect feedback if not going to send it.
275 if (!timer_.IsRunning()) 262 if (!timer_.IsRunning()) return;
276 return;
277 263
278 // Generate a map of marker offsets to marker hashes. This map helps to 264 // 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 265 // efficiently lookup feedback data based on the position of the misspelling
280 // in text. 266 // in text.
281 typedef std::map<size_t, uint32_t> MarkerMap; 267 typedef std::map<size_t, uint32_t> MarkerMap;
282 MarkerMap marker_map; 268 MarkerMap marker_map;
283 for (size_t i = 0; i < markers.size(); ++i) 269 for (size_t i = 0; i < markers.size(); ++i)
284 marker_map[markers[i].offset] = markers[i].hash; 270 marker_map[markers[i].offset] = markers[i].hash;
285 271
286 for (std::vector<SpellCheckResult>::iterator result_it = results->begin(); 272 for (std::vector<SpellCheckResult>::iterator result_it = results->begin();
287 result_it != results->end(); 273 result_it != results->end(); ++result_it) {
288 ++result_it) {
289 if (!IsInBounds(result_it->location, result_it->length, text.length())) 274 if (!IsInBounds(result_it->location, result_it->length, text.length()))
290 continue; 275 continue;
291 MarkerMap::const_iterator marker_it = marker_map.find(result_it->location); 276 MarkerMap::const_iterator marker_it = marker_map.find(result_it->location);
292 if (marker_it != marker_map.end() && 277 if (marker_it != marker_map.end() &&
293 feedback_.HasMisspelling(marker_it->second)) { 278 feedback_.HasMisspelling(marker_it->second)) {
294 // If the renderer already has a marker for this spellcheck result, then 279 // 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. 280 // set the hash of the spellcheck result to be the same as the marker.
296 result_it->hash = marker_it->second; 281 result_it->hash = marker_it->second;
297 } else { 282 } else {
298 // If the renderer does not yet have a marker for this spellcheck result, 283 // If the renderer does not yet have a marker for this spellcheck result,
299 // then generate a new hash for the spellcheck result. 284 // then generate a new hash for the spellcheck result.
300 result_it->hash = BuildHash(session_start_, ++misspelling_counter_); 285 result_it->hash = BuildHash(session_start_, ++misspelling_counter_);
301 } 286 }
302 // Save the feedback data for the spellcheck result. 287 // Save the feedback data for the spellcheck result.
303 feedback_.AddMisspelling(renderer_process_id, 288 feedback_.AddMisspelling(renderer_process_id,
304 BuildFeedback(*result_it, text)); 289 BuildFeedback(*result_it, text));
305 } 290 }
306 } 291 }
307 292
308 void FeedbackSender::OnLanguageCountryChange(const std::string& language, 293 void FeedbackSender::OnLanguageCountryChange(const std::string& language,
309 const std::string& country) { 294 const std::string& country) {
310 FlushFeedback(); 295 FlushFeedback();
311 language_ = language; 296 language_ = language;
312 country_ = country; 297 country_ = country;
313 } 298 }
314 299
315 void FeedbackSender::StartFeedbackCollection() { 300 void FeedbackSender::StartFeedbackCollection() {
316 if (timer_.IsRunning()) 301 if (timer_.IsRunning()) return;
317 return;
318 302
319 int interval_seconds = chrome::spellcheck_common::kFeedbackIntervalSeconds; 303 int interval_seconds = chrome::spellcheck_common::kFeedbackIntervalSeconds;
320 // This command-line switch is for testing and temporary. 304 // This command-line switch is for testing and temporary.
321 // TODO(rouslan): Remove the command-line switch when testing is complete. 305 // TODO(rouslan): Remove the command-line switch when testing is complete.
322 // http://crbug.com/247726 306 // http://crbug.com/247726
323 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 307 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
324 switches::kSpellingServiceFeedbackIntervalSeconds)) { 308 switches::kSpellingServiceFeedbackIntervalSeconds)) {
325 base::StringToInt( 309 base::StringToInt(
326 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 310 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
327 switches::kSpellingServiceFeedbackIntervalSeconds), 311 switches::kSpellingServiceFeedbackIntervalSeconds),
328 &interval_seconds); 312 &interval_seconds);
329 if (interval_seconds < kMinIntervalSeconds) 313 if (interval_seconds < kMinIntervalSeconds)
330 interval_seconds = kMinIntervalSeconds; 314 interval_seconds = kMinIntervalSeconds;
331 static const int kSessionSeconds = 315 static const int kSessionSeconds =
332 chrome::spellcheck_common::kSessionHours * 60 * 60; 316 chrome::spellcheck_common::kSessionHours * 60 * 60;
333 if (interval_seconds > kSessionSeconds) 317 if (interval_seconds > kSessionSeconds) interval_seconds = kSessionSeconds;
334 interval_seconds = kSessionSeconds;
335 } 318 }
336 timer_.Start(FROM_HERE, 319 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(interval_seconds), this,
337 base::TimeDelta::FromSeconds(interval_seconds),
338 this,
339 &FeedbackSender::RequestDocumentMarkers); 320 &FeedbackSender::RequestDocumentMarkers);
340 } 321 }
341 322
342 void FeedbackSender::StopFeedbackCollection() { 323 void FeedbackSender::StopFeedbackCollection() {
343 if (!timer_.IsRunning()) 324 if (!timer_.IsRunning()) return;
344 return;
345 325
346 FlushFeedback(); 326 FlushFeedback();
347 timer_.Stop(); 327 timer_.Stop();
348 } 328 }
349 329
350 void FeedbackSender::OnURLFetchComplete(const net::URLFetcher* source) { 330 void FeedbackSender::OnURLFetchComplete(const net::URLFetcher* source) {
351 for (ScopedVector<net::URLFetcher>::iterator sender_it = senders_.begin(); 331 for (ScopedVector<net::URLFetcher>::iterator sender_it = senders_.begin();
352 sender_it != senders_.end(); 332 sender_it != senders_.end(); ++sender_it) {
353 ++sender_it) {
354 if (*sender_it == source) { 333 if (*sender_it == source) {
355 senders_.erase(sender_it); 334 senders_.erase(sender_it);
356 return; 335 return;
357 } 336 }
358 } 337 }
359 delete source; 338 delete source;
360 } 339 }
361 340
362 void FeedbackSender::RequestDocumentMarkers() { 341 void FeedbackSender::RequestDocumentMarkers() {
363 // Request document markers from all the renderers that are still alive. 342 // Request document markers from all the renderers that are still alive.
364 std::set<int> alive_renderers; 343 std::set<int> alive_renderers;
365 for (content::RenderProcessHost::iterator it( 344 for (content::RenderProcessHost::iterator it(
366 content::RenderProcessHost::AllHostsIterator()); 345 content::RenderProcessHost::AllHostsIterator());
367 !it.IsAtEnd(); 346 !it.IsAtEnd(); it.Advance()) {
368 it.Advance()) {
369 alive_renderers.insert(it.GetCurrentValue()->GetID()); 347 alive_renderers.insert(it.GetCurrentValue()->GetID());
370 it.GetCurrentValue()->Send(new SpellCheckMsg_RequestDocumentMarkers()); 348 it.GetCurrentValue()->Send(new SpellCheckMsg_RequestDocumentMarkers());
371 } 349 }
372 350
373 // Asynchronously send out the feedback for all the renderers that are no 351 // Asynchronously send out the feedback for all the renderers that are no
374 // longer alive. 352 // longer alive.
375 std::vector<int> known_renderers = feedback_.GetRendersWithMisspellings(); 353 std::vector<int> known_renderers = feedback_.GetRendersWithMisspellings();
376 std::sort(known_renderers.begin(), known_renderers.end()); 354 std::sort(known_renderers.begin(), known_renderers.end());
377 std::vector<int> dead_renderers = 355 spellcheck::set_difference_container<std::vector<int>, std::set<int> >
please use gerrit instead 2016/02/03 23:59:10 The ">>" is OK in C++11 now. No need to insert a s
Kevin Bailey 2016/02/04 16:34:11 Ok, I thought it was "allowed", not "mandated".
378 base::STLSetDifference<std::vector<int> >(known_renderers, 356 renderers(known_renderers, alive_renderers);
please use gerrit instead 2016/02/03 23:59:10 s/renderers/dead_renderers/
Kevin Bailey 2016/02/04 16:34:11 Done.
379 alive_renderers); 357 for (auto renderer : renderers) {
please use gerrit instead 2016/02/03 23:59:10 for (const auto& renderer : dead_renderers) { ...
Kevin Bailey 2016/02/04 16:34:11 If you wish, but it's just an int, and auto is not
380 for (std::vector<int>::const_iterator it = dead_renderers.begin();
381 it != dead_renderers.end();
382 ++it) {
383 base::ThreadTaskRunnerHandle::Get()->PostTask( 358 base::ThreadTaskRunnerHandle::Get()->PostTask(
384 FROM_HERE, base::Bind(&FeedbackSender::OnReceiveDocumentMarkers, 359 FROM_HERE, base::Bind(&FeedbackSender::OnReceiveDocumentMarkers,
385 AsWeakPtr(), *it, std::vector<uint32_t>())); 360 AsWeakPtr(), renderer, std::vector<uint32_t>()));
386 } 361 }
387 } 362 }
388 363
389 void FeedbackSender::FlushFeedback() { 364 void FeedbackSender::FlushFeedback() {
390 if (feedback_.Empty()) 365 if (feedback_.Empty()) return;
391 return;
392 feedback_.FinalizeAllMisspellings(); 366 feedback_.FinalizeAllMisspellings();
393 SendFeedback(feedback_.GetAllMisspellings(), 367 SendFeedback(feedback_.GetAllMisspellings(),
394 renderers_sent_feedback_.empty()); 368 renderers_sent_feedback_.empty());
395 feedback_.Clear(); 369 feedback_.Clear();
396 renderers_sent_feedback_.clear(); 370 renderers_sent_feedback_.clear();
397 session_start_ = base::Time::Now(); 371 session_start_ = base::Time::Now();
398 timer_.Reset(); 372 timer_.Reset();
399 } 373 }
400 374
401 void FeedbackSender::SendFeedback(const std::vector<Misspelling>& feedback_data, 375 void FeedbackSender::SendFeedback(const std::vector<Misspelling>& feedback_data,
402 bool is_first_feedback_batch) { 376 bool is_first_feedback_batch) {
403 scoped_ptr<base::Value> feedback_value(BuildFeedbackValue( 377 scoped_ptr<base::Value> feedback_value(BuildFeedbackValue(
404 BuildParams(BuildSuggestionInfo(feedback_data, is_first_feedback_batch), 378 BuildParams(BuildSuggestionInfo(feedback_data, is_first_feedback_batch),
405 language_, 379 language_, country_),
406 country_),
407 api_version_)); 380 api_version_));
408 std::string feedback; 381 std::string feedback;
409 base::JSONWriter::Write(*feedback_value, &feedback); 382 base::JSONWriter::Write(*feedback_value, &feedback);
410 383
411 // The tests use this identifier to mock the URL fetcher. 384 // The tests use this identifier to mock the URL fetcher.
412 static const int kUrlFetcherId = 0; 385 static const int kUrlFetcherId = 0;
413 net::URLFetcher* sender = 386 net::URLFetcher* sender =
414 net::URLFetcher::Create(kUrlFetcherId, feedback_service_url_, 387 net::URLFetcher::Create(kUrlFetcherId, feedback_service_url_,
415 net::URLFetcher::POST, this).release(); 388 net::URLFetcher::POST, this)
389 .release();
416 data_use_measurement::DataUseUserData::AttachToFetcher( 390 data_use_measurement::DataUseUserData::AttachToFetcher(
417 sender, data_use_measurement::DataUseUserData::SPELL_CHECKER); 391 sender, data_use_measurement::DataUseUserData::SPELL_CHECKER);
418 sender->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 392 sender->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
419 net::LOAD_DO_NOT_SAVE_COOKIES); 393 net::LOAD_DO_NOT_SAVE_COOKIES);
420 sender->SetUploadData("application/json", feedback); 394 sender->SetUploadData("application/json", feedback);
421 senders_.push_back(sender); 395 senders_.push_back(sender);
422 396
423 // Request context is NULL in testing. 397 // Request context is nullptr in testing.
424 if (request_context_.get()) { 398 if (request_context_.get()) {
425 sender->SetRequestContext(request_context_.get()); 399 sender->SetRequestContext(request_context_.get());
426 sender->Start(); 400 sender->Start();
427 } 401 }
428 } 402 }
429 403
430 } // namespace spellcheck 404 } // namespace spellcheck
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698