Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 113 params->Set("suggestionInfo", suggestion_info); | 113 params->Set("suggestionInfo", suggestion_info); |
| 114 params->SetString("key", google_apis::GetAPIKey()); | 114 params->SetString("key", google_apis::GetAPIKey()); |
| 115 params->SetString("language", language); | 115 params->SetString("language", language); |
| 116 params->SetString("originCountry", country); | 116 params->SetString("originCountry", country); |
| 117 params->SetString("clientName", "Chrome"); | 117 params->SetString("clientName", "Chrome"); |
| 118 return params; | 118 return params; |
| 119 } | 119 } |
| 120 | 120 |
| 121 // Builds feedback data from |params|. Takes ownership of |params|. The caller | 121 // Builds feedback data from |params|. Takes ownership of |params|. The caller |
| 122 // owns the result. | 122 // owns the result. |
| 123 base::Value* BuildFeedbackValue(base::DictionaryValue* params) { | 123 base::Value* BuildFeedbackValue(base::DictionaryValue* params, |
| 124 const std::string& api_version) { | |
| 124 base::DictionaryValue* result = new base::DictionaryValue; | 125 base::DictionaryValue* result = new base::DictionaryValue; |
| 125 result->Set("params", params); | 126 result->Set("params", params); |
| 126 result->SetString("method", "spelling.feedback"); | 127 result->SetString("method", "spelling.feedback"); |
| 127 result->SetString("apiVersion", "v2"); | 128 result->SetString("apiVersion", api_version); |
| 128 return result; | 129 return result; |
| 129 } | 130 } |
| 130 | 131 |
| 131 // Returns true if the misspelling location is within text bounds. | 132 // Returns true if the misspelling location is within text bounds. |
| 132 bool IsInBounds(int misspelling_location, | 133 bool IsInBounds(int misspelling_location, |
| 133 int misspelling_length, | 134 int misspelling_length, |
| 134 size_t text_length) { | 135 size_t text_length) { |
| 135 return misspelling_location >= 0 && misspelling_length > 0 && | 136 return misspelling_location >= 0 && misspelling_length > 0 && |
| 136 static_cast<size_t>(misspelling_location) < text_length && | 137 static_cast<size_t>(misspelling_location) < text_length && |
| 137 static_cast<size_t>(misspelling_location + misspelling_length) <= | 138 static_cast<size_t>(misspelling_location + misspelling_length) <= |
| 138 text_length; | 139 text_length; |
| 139 } | 140 } |
| 140 | 141 |
| 142 // Returns the feedback API version. | |
| 143 std::string GetApiVersion() { | |
| 144 // This guard is temporary. | |
| 145 // TODO(rouslan): Remove the guard. http://crbug.com/247726 | |
| 146 if (base::FieldTrialList::FindFullName(kFeedbackFieldTrialName) == | |
| 147 kFeedbackFieldTrialEnabledGroupName && | |
| 148 CommandLine::ForCurrentProcess()->HasSwitch( | |
| 149 switches::kEnableSpellingServiceFeedback)) { | |
|
groby-ooo-7-16
2013/11/21 02:48:41
This confuses me, since we have a "FeedbackEnabled
please use gerrit instead
2013/11/22 22:06:31
The flag is to switch from "v2" to "v2-internal" A
please use gerrit instead
2013/11/22 22:14:22
--enable-spelling-feedback-field-trial.
| |
| 150 return "v2-internal"; | |
| 151 } | |
| 152 return "v2"; | |
| 153 } | |
| 154 | |
| 141 } // namespace | 155 } // namespace |
| 142 | 156 |
| 143 FeedbackSender::FeedbackSender(net::URLRequestContextGetter* request_context, | 157 FeedbackSender::FeedbackSender(net::URLRequestContextGetter* request_context, |
| 144 const std::string& language, | 158 const std::string& language, |
| 145 const std::string& country) | 159 const std::string& country) |
| 146 : request_context_(request_context), | 160 : request_context_(request_context), |
| 161 api_version_(GetApiVersion()), | |
| 147 language_(language), | 162 language_(language), |
| 148 country_(country), | 163 country_(country), |
| 149 misspelling_counter_(0), | 164 misspelling_counter_(0), |
| 150 session_start_(base::Time::Now()), | 165 session_start_(base::Time::Now()), |
| 151 feedback_service_url_(kFeedbackServiceURL) { | 166 feedback_service_url_(kFeedbackServiceURL) { |
| 152 // This guard is temporary. | |
| 153 // TODO(rouslan): Remove the guard. http://crbug.com/247726 | |
| 154 if (!CommandLine::ForCurrentProcess()->HasSwitch( | |
| 155 switches::kEnableSpellingServiceFeedback) || | |
| 156 base::FieldTrialList::FindFullName(kFeedbackFieldTrialName) != | |
| 157 kFeedbackFieldTrialEnabledGroupName) { | |
| 158 return; | |
| 159 } | |
| 160 | |
| 161 // The command-line switch is for testing and temporary. | 167 // The command-line switch is for testing and temporary. |
| 162 // TODO(rouslan): Remove the command-line switch when testing is complete. | 168 // TODO(rouslan): Remove the command-line switch when testing is complete. |
| 163 // http://crbug.com/247726 | 169 // http://crbug.com/247726 |
| 164 if (CommandLine::ForCurrentProcess()->HasSwitch( | 170 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 165 switches::kSpellingServiceFeedbackUrl)) { | 171 switches::kSpellingServiceFeedbackUrl)) { |
| 166 feedback_service_url_ = | 172 feedback_service_url_ = |
| 167 GURL(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 173 GURL(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 168 switches::kSpellingServiceFeedbackUrl)); | 174 switches::kSpellingServiceFeedbackUrl)); |
| 169 } | 175 } |
| 170 | |
| 171 int interval_seconds = chrome::spellcheck_common::kFeedbackIntervalSeconds; | |
| 172 // This command-line switch is for testing and temporary. | |
| 173 // TODO(rouslan): Remove the command-line switch when testing is complete. | |
| 174 // http://crbug.com/247726 | |
| 175 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
| 176 switches::kSpellingServiceFeedbackIntervalSeconds)) { | |
| 177 base::StringToInt(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
| 178 switches::kSpellingServiceFeedbackIntervalSeconds), | |
| 179 &interval_seconds); | |
| 180 if (interval_seconds < kMinIntervalSeconds) | |
| 181 interval_seconds = kMinIntervalSeconds; | |
| 182 } | |
| 183 | |
| 184 timer_.Start(FROM_HERE, | |
| 185 base::TimeDelta::FromSeconds(interval_seconds), | |
| 186 this, | |
| 187 &FeedbackSender::RequestDocumentMarkers); | |
| 188 } | 176 } |
| 189 | 177 |
| 190 FeedbackSender::~FeedbackSender() { | 178 FeedbackSender::~FeedbackSender() { |
| 191 } | 179 } |
| 192 | 180 |
| 193 void FeedbackSender::SelectedSuggestion(uint32 hash, int suggestion_index) { | 181 void FeedbackSender::SelectedSuggestion(uint32 hash, int suggestion_index) { |
| 194 Misspelling* misspelling = feedback_.GetMisspelling(hash); | 182 Misspelling* misspelling = feedback_.GetMisspelling(hash); |
| 195 // GetMisspelling() returns null for flushed feedback. Feedback is flushed | 183 // GetMisspelling() returns null for flushed feedback. Feedback is flushed |
| 196 // when the session expires every |kSessionHours| hours. | 184 // when the session expires every |kSessionHours| hours. |
| 197 if (!misspelling) | 185 if (!misspelling) |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 311 } | 299 } |
| 312 } | 300 } |
| 313 | 301 |
| 314 void FeedbackSender::OnLanguageCountryChange(const std::string& language, | 302 void FeedbackSender::OnLanguageCountryChange(const std::string& language, |
| 315 const std::string& country) { | 303 const std::string& country) { |
| 316 FlushFeedback(); | 304 FlushFeedback(); |
| 317 language_ = language; | 305 language_ = language; |
| 318 country_ = country; | 306 country_ = country; |
| 319 } | 307 } |
| 320 | 308 |
| 309 void FeedbackSender::StopFeedbackCollection() { | |
| 310 FlushFeedback(); | |
| 311 timer_.Stop(); | |
| 312 } | |
| 313 | |
| 314 void FeedbackSender::StartFeedbackCollection() { | |
| 315 int interval_seconds = chrome::spellcheck_common::kFeedbackIntervalSeconds; | |
| 316 // This command-line switch is for testing and temporary. | |
| 317 // TODO(rouslan): Remove the command-line switch when testing is complete. | |
| 318 // http://crbug.com/247726 | |
| 319 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
| 320 switches::kSpellingServiceFeedbackIntervalSeconds)) { | |
| 321 base::StringToInt(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
| 322 switches::kSpellingServiceFeedbackIntervalSeconds), | |
|
groby-ooo-7-16
2013/11/21 02:48:41
You might want to clamp to kMaxIntervalSeconds, to
please use gerrit instead
2013/11/22 22:06:31
Done.
| |
| 323 &interval_seconds); | |
| 324 if (interval_seconds < kMinIntervalSeconds) | |
| 325 interval_seconds = kMinIntervalSeconds; | |
| 326 } | |
| 327 timer_.Start(FROM_HERE, | |
|
groby-ooo-7-16
2013/11/21 02:48:41
I suppose timer automatically cancels pending task
please use gerrit instead
2013/11/22 22:06:31
Correct. Added a comment in feedback_sender.h.
| |
| 328 base::TimeDelta::FromSeconds(interval_seconds), | |
| 329 this, | |
| 330 &FeedbackSender::RequestDocumentMarkers); | |
| 331 } | |
| 332 | |
| 321 void FeedbackSender::OnURLFetchComplete(const net::URLFetcher* source) { | 333 void FeedbackSender::OnURLFetchComplete(const net::URLFetcher* source) { |
| 322 for (ScopedVector<net::URLFetcher>::iterator sender_it = senders_.begin(); | 334 for (ScopedVector<net::URLFetcher>::iterator sender_it = senders_.begin(); |
| 323 sender_it != senders_.end(); | 335 sender_it != senders_.end(); |
| 324 ++sender_it) { | 336 ++sender_it) { |
| 325 if (*sender_it == source) { | 337 if (*sender_it == source) { |
| 326 senders_.erase(sender_it); | 338 senders_.erase(sender_it); |
| 327 return; | 339 return; |
| 328 } | 340 } |
| 329 } | 341 } |
| 330 delete source; | 342 delete source; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 renderers_sent_feedback_.clear(); | 382 renderers_sent_feedback_.clear(); |
| 371 session_start_ = base::Time::Now(); | 383 session_start_ = base::Time::Now(); |
| 372 timer_.Reset(); | 384 timer_.Reset(); |
| 373 } | 385 } |
| 374 | 386 |
| 375 void FeedbackSender::SendFeedback(const std::vector<Misspelling>& feedback_data, | 387 void FeedbackSender::SendFeedback(const std::vector<Misspelling>& feedback_data, |
| 376 bool is_first_feedback_batch) { | 388 bool is_first_feedback_batch) { |
| 377 scoped_ptr<base::Value> feedback_value(BuildFeedbackValue( | 389 scoped_ptr<base::Value> feedback_value(BuildFeedbackValue( |
| 378 BuildParams(BuildSuggestionInfo(feedback_data, is_first_feedback_batch), | 390 BuildParams(BuildSuggestionInfo(feedback_data, is_first_feedback_batch), |
| 379 language_, | 391 language_, |
| 380 country_))); | 392 country_), |
| 393 api_version_)); | |
| 381 std::string feedback; | 394 std::string feedback; |
| 382 base::JSONWriter::Write(feedback_value.get(), &feedback); | 395 base::JSONWriter::Write(feedback_value.get(), &feedback); |
| 383 | 396 |
| 384 // The tests use this identifier to mock the URL fetcher. | 397 // The tests use this identifier to mock the URL fetcher. |
| 385 static const int kUrlFetcherId = 0; | 398 static const int kUrlFetcherId = 0; |
| 386 net::URLFetcher* sender = net::URLFetcher::Create( | 399 net::URLFetcher* sender = net::URLFetcher::Create( |
| 387 kUrlFetcherId, feedback_service_url_, net::URLFetcher::POST, this); | 400 kUrlFetcherId, feedback_service_url_, net::URLFetcher::POST, this); |
| 388 sender->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 401 sender->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
| 389 net::LOAD_DO_NOT_SAVE_COOKIES); | 402 net::LOAD_DO_NOT_SAVE_COOKIES); |
| 390 sender->SetUploadData("application/json", feedback); | 403 sender->SetUploadData("application/json", feedback); |
| 391 senders_.push_back(sender); | 404 senders_.push_back(sender); |
| 392 | 405 |
| 393 // Request context is NULL in testing. | 406 // Request context is NULL in testing. |
| 394 if (request_context_.get()) { | 407 if (request_context_.get()) { |
| 395 sender->SetRequestContext(request_context_.get()); | 408 sender->SetRequestContext(request_context_.get()); |
| 396 sender->Start(); | 409 sender->Start(); |
| 397 } | 410 } |
| 398 } | 411 } |
| 399 | 412 |
| 400 } // namespace spellcheck | 413 } // namespace spellcheck |
| OLD | NEW |