| OLD | NEW |
| 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/history/web_history_service.h" | 5 #include "chrome/browser/history/web_history_service.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
| 9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 | 33 |
| 34 const char kHistoryOAuthScope[] = | 34 const char kHistoryOAuthScope[] = |
| 35 "https://www.googleapis.com/auth/chromesync"; | 35 "https://www.googleapis.com/auth/chromesync"; |
| 36 | 36 |
| 37 const char kHistoryQueryHistoryUrl[] = | 37 const char kHistoryQueryHistoryUrl[] = |
| 38 "https://history.google.com/history/api/lookup?client=chrome"; | 38 "https://history.google.com/history/api/lookup?client=chrome"; |
| 39 | 39 |
| 40 const char kHistoryDeleteHistoryUrl[] = | 40 const char kHistoryDeleteHistoryUrl[] = |
| 41 "https://history.google.com/history/api/delete?client=chrome"; | 41 "https://history.google.com/history/api/delete?client=chrome"; |
| 42 | 42 |
| 43 const char kHistoryAudioHistoryUrl[] = |
| 44 "https://history.google.com/history/api/lookup?client=audio"; |
| 45 |
| 46 const char kHistoryAudioHistoryChangeUrl[] = |
| 47 "https://history.google.com/history/api/change"; |
| 48 |
| 43 const char kPostDataMimeType[] = "text/plain"; | 49 const char kPostDataMimeType[] = "text/plain"; |
| 44 | 50 |
| 45 // The maximum number of retries for the URLFetcher requests. | 51 // The maximum number of retries for the URLFetcher requests. |
| 46 const size_t kMaxRetries = 1; | 52 const size_t kMaxRetries = 1; |
| 47 | 53 |
| 48 class RequestImpl : public WebHistoryService::Request, | 54 class RequestImpl : public WebHistoryService::Request, |
| 49 private OAuth2TokenService::Consumer, | 55 private OAuth2TokenService::Consumer, |
| 50 private net::URLFetcherDelegate { | 56 private net::URLFetcherDelegate { |
| 51 public: | 57 public: |
| 52 ~RequestImpl() override {} | 58 ~RequestImpl() override {} |
| 53 | 59 |
| 54 // Returns the response code received from the server, which will only be | 60 // Returns the response code received from the server, which will only be |
| 55 // valid if the request succeeded. | 61 // valid if the request succeeded. |
| 56 int response_code() { return response_code_; } | 62 int response_code() override { return response_code_; } |
| 57 | 63 |
| 58 // Returns the contents of the response body received from the server. | 64 // Returns the contents of the response body received from the server. |
| 59 const std::string& response_body() { return response_body_; } | 65 const std::string& response_body() override { return response_body_; } |
| 60 | 66 |
| 61 bool is_pending() override { return is_pending_; } | 67 bool is_pending() override { return is_pending_; } |
| 62 | 68 |
| 63 private: | 69 private: |
| 64 friend class history::WebHistoryService; | 70 friend class history::WebHistoryService; |
| 65 | 71 |
| 66 typedef base::Callback<void(Request*, bool)> CompletionCallback; | |
| 67 | |
| 68 RequestImpl(Profile* profile, | 72 RequestImpl(Profile* profile, |
| 69 const GURL& url, | 73 const GURL& url, |
| 70 const CompletionCallback& callback) | 74 const WebHistoryService::CompletionCallback& callback) |
| 71 : OAuth2TokenService::Consumer("web_history"), | 75 : OAuth2TokenService::Consumer("web_history"), |
| 72 profile_(profile), | 76 profile_(profile), |
| 73 url_(url), | 77 url_(url), |
| 74 response_code_(0), | 78 response_code_(0), |
| 75 auth_retry_count_(0), | 79 auth_retry_count_(0), |
| 76 callback_(callback), | 80 callback_(callback), |
| 77 is_pending_(false) { | 81 is_pending_(false) { |
| 78 } | 82 } |
| 79 | 83 |
| 80 // Tells the request to do its thang. | 84 // Tells the request to do its thang. |
| 81 void Start() { | 85 void Start() override { |
| 82 OAuth2TokenService::ScopeSet oauth_scopes; | 86 OAuth2TokenService::ScopeSet oauth_scopes; |
| 83 oauth_scopes.insert(kHistoryOAuthScope); | 87 oauth_scopes.insert(kHistoryOAuthScope); |
| 84 | 88 |
| 85 ProfileOAuth2TokenService* token_service = | 89 ProfileOAuth2TokenService* token_service = |
| 86 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); | 90 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); |
| 87 SigninManagerBase* signin_manager = | 91 SigninManagerBase* signin_manager = |
| 88 SigninManagerFactory::GetForProfile(profile_); | 92 SigninManagerFactory::GetForProfile(profile_); |
| 89 token_request_ = token_service->StartRequest( | 93 token_request_ = token_service->StartRequest( |
| 90 signin_manager->GetAuthenticatedAccountId(), oauth_scopes, this); | 94 signin_manager->GetAuthenticatedAccountId(), oauth_scopes, this); |
| 91 is_pending_ = true; | 95 is_pending_ = true; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 168 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
| 165 net::LOAD_DO_NOT_SAVE_COOKIES); | 169 net::LOAD_DO_NOT_SAVE_COOKIES); |
| 166 fetcher->AddExtraRequestHeader("Authorization: Bearer " + access_token); | 170 fetcher->AddExtraRequestHeader("Authorization: Bearer " + access_token); |
| 167 fetcher->AddExtraRequestHeader("X-Developer-Key: " + | 171 fetcher->AddExtraRequestHeader("X-Developer-Key: " + |
| 168 GaiaUrls::GetInstance()->oauth2_chrome_client_id()); | 172 GaiaUrls::GetInstance()->oauth2_chrome_client_id()); |
| 169 if (request_type == net::URLFetcher::POST) | 173 if (request_type == net::URLFetcher::POST) |
| 170 fetcher->SetUploadData(kPostDataMimeType, post_data_); | 174 fetcher->SetUploadData(kPostDataMimeType, post_data_); |
| 171 return fetcher; | 175 return fetcher; |
| 172 } | 176 } |
| 173 | 177 |
| 174 void set_post_data(const std::string& post_data) { | 178 void set_post_data(const std::string& post_data) override { |
| 175 post_data_ = post_data; | 179 post_data_ = post_data; |
| 176 } | 180 } |
| 177 | 181 |
| 178 Profile* profile_; | 182 Profile* profile_; |
| 179 | 183 |
| 180 // The URL of the API endpoint. | 184 // The URL of the API endpoint. |
| 181 GURL url_; | 185 GURL url_; |
| 182 | 186 |
| 183 // POST data to be sent with the request (may be empty). | 187 // POST data to be sent with the request (may be empty). |
| 184 std::string post_data_; | 188 std::string post_data_; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 196 int response_code_; | 200 int response_code_; |
| 197 | 201 |
| 198 // Holds the response body received from the server. | 202 // Holds the response body received from the server. |
| 199 std::string response_body_; | 203 std::string response_body_; |
| 200 | 204 |
| 201 // The number of times this request has already been retried due to | 205 // The number of times this request has already been retried due to |
| 202 // authorization problems. | 206 // authorization problems. |
| 203 int auth_retry_count_; | 207 int auth_retry_count_; |
| 204 | 208 |
| 205 // The callback to execute when the query is complete. | 209 // The callback to execute when the query is complete. |
| 206 CompletionCallback callback_; | 210 WebHistoryService::CompletionCallback callback_; |
| 207 | 211 |
| 208 // True if the request was started and has not yet completed, otherwise false. | 212 // True if the request was started and has not yet completed, otherwise false. |
| 209 bool is_pending_; | 213 bool is_pending_; |
| 210 }; | 214 }; |
| 211 | 215 |
| 212 // Extracts a JSON-encoded HTTP response into a DictionaryValue. | |
| 213 // If |request|'s HTTP response code indicates failure, or if the response | |
| 214 // body is not JSON, a null pointer is returned. | |
| 215 scoped_ptr<base::DictionaryValue> ReadResponse(RequestImpl* request) { | |
| 216 scoped_ptr<base::DictionaryValue> result; | |
| 217 if (request->response_code() == net::HTTP_OK) { | |
| 218 base::Value* value = base::JSONReader::Read(request->response_body()); | |
| 219 if (value && value->IsType(base::Value::TYPE_DICTIONARY)) | |
| 220 result.reset(static_cast<base::DictionaryValue*>(value)); | |
| 221 else | |
| 222 DLOG(WARNING) << "Non-JSON response received from history server."; | |
| 223 } | |
| 224 return result.Pass(); | |
| 225 } | |
| 226 | |
| 227 // Converts a time into a string for use as a parameter in a request to the | 216 // Converts a time into a string for use as a parameter in a request to the |
| 228 // history server. | 217 // history server. |
| 229 std::string ServerTimeString(base::Time time) { | 218 std::string ServerTimeString(base::Time time) { |
| 230 if (time < base::Time::UnixEpoch()) { | 219 if (time < base::Time::UnixEpoch()) { |
| 231 return base::Int64ToString(0); | 220 return base::Int64ToString(0); |
| 232 } else { | 221 } else { |
| 233 return base::Int64ToString( | 222 return base::Int64ToString( |
| 234 (time - base::Time::UnixEpoch()).InMicroseconds()); | 223 (time - base::Time::UnixEpoch()).InMicroseconds()); |
| 235 } | 224 } |
| 236 } | 225 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 WebHistoryService::Request::~Request() { | 285 WebHistoryService::Request::~Request() { |
| 297 } | 286 } |
| 298 | 287 |
| 299 WebHistoryService::WebHistoryService(Profile* profile) | 288 WebHistoryService::WebHistoryService(Profile* profile) |
| 300 : profile_(profile), | 289 : profile_(profile), |
| 301 weak_ptr_factory_(this) { | 290 weak_ptr_factory_(this) { |
| 302 } | 291 } |
| 303 | 292 |
| 304 WebHistoryService::~WebHistoryService() { | 293 WebHistoryService::~WebHistoryService() { |
| 305 STLDeleteElements(&pending_expire_requests_); | 294 STLDeleteElements(&pending_expire_requests_); |
| 295 STLDeleteElements(&pending_audio_history_requests_); |
| 296 } |
| 297 |
| 298 WebHistoryService::Request* WebHistoryService::CreateRequest( |
| 299 const GURL& url, |
| 300 const CompletionCallback& callback) { |
| 301 return new RequestImpl(profile_, url, callback); |
| 302 } |
| 303 |
| 304 // static |
| 305 scoped_ptr<base::DictionaryValue> WebHistoryService::ReadResponse( |
| 306 WebHistoryService::Request* request) { |
| 307 scoped_ptr<base::DictionaryValue> result; |
| 308 if (request->response_code() == net::HTTP_OK) { |
| 309 base::Value* value = base::JSONReader::Read(request->response_body()); |
| 310 if (value && value->IsType(base::Value::TYPE_DICTIONARY)) |
| 311 result.reset(static_cast<base::DictionaryValue*>(value)); |
| 312 else |
| 313 DLOG(WARNING) << "Non-JSON response received from history server."; |
| 314 } |
| 315 return result.Pass(); |
| 306 } | 316 } |
| 307 | 317 |
| 308 scoped_ptr<WebHistoryService::Request> WebHistoryService::QueryHistory( | 318 scoped_ptr<WebHistoryService::Request> WebHistoryService::QueryHistory( |
| 309 const base::string16& text_query, | 319 const base::string16& text_query, |
| 310 const QueryOptions& options, | 320 const QueryOptions& options, |
| 311 const WebHistoryService::QueryWebHistoryCallback& callback) { | 321 const WebHistoryService::QueryWebHistoryCallback& callback) { |
| 312 // Wrap the original callback into a generic completion callback. | 322 // Wrap the original callback into a generic completion callback. |
| 313 RequestImpl::CompletionCallback completion_callback = base::Bind( | 323 CompletionCallback completion_callback = base::Bind( |
| 314 &WebHistoryService::QueryHistoryCompletionCallback, callback); | 324 &WebHistoryService::QueryHistoryCompletionCallback, callback); |
| 315 | 325 |
| 316 GURL url = GetQueryUrl(text_query, options, server_version_info_); | 326 GURL url = GetQueryUrl(text_query, options, server_version_info_); |
| 317 scoped_ptr<RequestImpl> request( | 327 scoped_ptr<Request> request(CreateRequest(url, completion_callback)); |
| 318 new RequestImpl(profile_, url, completion_callback)); | |
| 319 request->Start(); | 328 request->Start(); |
| 320 return request.Pass(); | 329 return request.Pass(); |
| 321 } | 330 } |
| 322 | 331 |
| 323 void WebHistoryService::ExpireHistory( | 332 void WebHistoryService::ExpireHistory( |
| 324 const std::vector<ExpireHistoryArgs>& expire_list, | 333 const std::vector<ExpireHistoryArgs>& expire_list, |
| 325 const ExpireWebHistoryCallback& callback) { | 334 const ExpireWebHistoryCallback& callback) { |
| 326 base::DictionaryValue delete_request; | 335 base::DictionaryValue delete_request; |
| 327 scoped_ptr<base::ListValue> deletions(new base::ListValue); | 336 scoped_ptr<base::ListValue> deletions(new base::ListValue); |
| 328 base::Time now = base::Time::Now(); | 337 base::Time now = base::Time::Now(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 351 base::JSONWriter::Write(&delete_request, &post_data); | 360 base::JSONWriter::Write(&delete_request, &post_data); |
| 352 | 361 |
| 353 GURL url(kHistoryDeleteHistoryUrl); | 362 GURL url(kHistoryDeleteHistoryUrl); |
| 354 | 363 |
| 355 // Append the version info token, if it is available, to help ensure | 364 // Append the version info token, if it is available, to help ensure |
| 356 // consistency with any previous deletions. | 365 // consistency with any previous deletions. |
| 357 if (!server_version_info_.empty()) | 366 if (!server_version_info_.empty()) |
| 358 url = net::AppendQueryParameter(url, "kvi", server_version_info_); | 367 url = net::AppendQueryParameter(url, "kvi", server_version_info_); |
| 359 | 368 |
| 360 // Wrap the original callback into a generic completion callback. | 369 // Wrap the original callback into a generic completion callback. |
| 361 RequestImpl::CompletionCallback completion_callback = | 370 CompletionCallback completion_callback = |
| 362 base::Bind(&WebHistoryService::ExpireHistoryCompletionCallback, | 371 base::Bind(&WebHistoryService::ExpireHistoryCompletionCallback, |
| 363 weak_ptr_factory_.GetWeakPtr(), | 372 weak_ptr_factory_.GetWeakPtr(), |
| 364 callback); | 373 callback); |
| 365 | 374 |
| 366 scoped_ptr<RequestImpl> request( | 375 scoped_ptr<Request> request(CreateRequest(url, completion_callback)); |
| 367 new RequestImpl(profile_, url, completion_callback)); | |
| 368 request->set_post_data(post_data); | 376 request->set_post_data(post_data); |
| 369 request->Start(); | 377 request->Start(); |
| 370 pending_expire_requests_.insert(request.release()); | 378 pending_expire_requests_.insert(request.release()); |
| 371 } | 379 } |
| 372 | 380 |
| 373 void WebHistoryService::ExpireHistoryBetween( | 381 void WebHistoryService::ExpireHistoryBetween( |
| 374 const std::set<GURL>& restrict_urls, | 382 const std::set<GURL>& restrict_urls, |
| 375 base::Time begin_time, | 383 base::Time begin_time, |
| 376 base::Time end_time, | 384 base::Time end_time, |
| 377 const ExpireWebHistoryCallback& callback) { | 385 const ExpireWebHistoryCallback& callback) { |
| 378 std::vector<ExpireHistoryArgs> expire_list(1); | 386 std::vector<ExpireHistoryArgs> expire_list(1); |
| 379 expire_list.back().urls = restrict_urls; | 387 expire_list.back().urls = restrict_urls; |
| 380 expire_list.back().begin_time = begin_time; | 388 expire_list.back().begin_time = begin_time; |
| 381 expire_list.back().end_time = end_time; | 389 expire_list.back().end_time = end_time; |
| 382 ExpireHistory(expire_list, callback); | 390 ExpireHistory(expire_list, callback); |
| 383 } | 391 } |
| 384 | 392 |
| 393 void WebHistoryService::GetAudioHistoryEnabled( |
| 394 const AudioWebHistoryCallback& callback) { |
| 395 // Wrap the original callback into a generic completion callback. |
| 396 CompletionCallback completion_callback = |
| 397 base::Bind(&WebHistoryService::AudioHistoryCompletionCallback, |
| 398 weak_ptr_factory_.GetWeakPtr(), |
| 399 callback); |
| 400 |
| 401 GURL url(kHistoryAudioHistoryUrl); |
| 402 scoped_ptr<Request> request(CreateRequest(url, completion_callback)); |
| 403 request->Start(); |
| 404 pending_audio_history_requests_.insert(request.release()); |
| 405 } |
| 406 |
| 407 void WebHistoryService::SetAudioHistoryEnabled( |
| 408 bool new_enabled_value, |
| 409 const AudioWebHistoryCallback& callback) { |
| 410 // Wrap the original callback into a generic completion callback. |
| 411 CompletionCallback completion_callback = |
| 412 base::Bind(&WebHistoryService::AudioHistoryCompletionCallback, |
| 413 weak_ptr_factory_.GetWeakPtr(), |
| 414 callback); |
| 415 |
| 416 GURL url(kHistoryAudioHistoryChangeUrl); |
| 417 scoped_ptr<Request> request(CreateRequest(url, completion_callback)); |
| 418 |
| 419 base::DictionaryValue enable_audio_history; |
| 420 enable_audio_history.SetBoolean("enable_history_recording", |
| 421 new_enabled_value); |
| 422 enable_audio_history.SetString("client", "audio"); |
| 423 std::string post_data; |
| 424 base::JSONWriter::Write(&enable_audio_history, &post_data); |
| 425 request->set_post_data(post_data); |
| 426 |
| 427 request->Start(); |
| 428 pending_audio_history_requests_.insert(request.release()); |
| 429 } |
| 430 |
| 385 // static | 431 // static |
| 386 void WebHistoryService::QueryHistoryCompletionCallback( | 432 void WebHistoryService::QueryHistoryCompletionCallback( |
| 387 const WebHistoryService::QueryWebHistoryCallback& callback, | 433 const WebHistoryService::QueryWebHistoryCallback& callback, |
| 388 WebHistoryService::Request* request, | 434 WebHistoryService::Request* request, |
| 389 bool success) { | 435 bool success) { |
| 390 scoped_ptr<base::DictionaryValue> response_value; | 436 scoped_ptr<base::DictionaryValue> response_value; |
| 391 if (success) | 437 if (success) |
| 392 response_value = ReadResponse(static_cast<RequestImpl*>(request)); | 438 response_value = ReadResponse(request); |
| 393 callback.Run(request, response_value.get()); | 439 callback.Run(request, response_value.get()); |
| 394 } | 440 } |
| 395 | 441 |
| 396 void WebHistoryService::ExpireHistoryCompletionCallback( | 442 void WebHistoryService::ExpireHistoryCompletionCallback( |
| 397 const WebHistoryService::ExpireWebHistoryCallback& callback, | 443 const WebHistoryService::ExpireWebHistoryCallback& callback, |
| 398 WebHistoryService::Request* request, | 444 WebHistoryService::Request* request, |
| 399 bool success) { | 445 bool success) { |
| 400 scoped_ptr<base::DictionaryValue> response_value; | 446 scoped_ptr<base::DictionaryValue> response_value; |
| 401 if (success) { | 447 if (success) { |
| 402 response_value = ReadResponse(static_cast<RequestImpl*>(request)); | 448 response_value = ReadResponse(request); |
| 403 if (response_value) | 449 if (response_value) |
| 404 response_value->GetString("version_info", &server_version_info_); | 450 response_value->GetString("version_info", &server_version_info_); |
| 405 } | 451 } |
| 406 callback.Run(response_value.get() && success); | 452 callback.Run(response_value.get() && success); |
| 407 // Clean up from pending requests. | 453 // Clean up from pending requests. |
| 408 pending_expire_requests_.erase(request); | 454 pending_expire_requests_.erase(request); |
| 409 delete request; | 455 delete request; |
| 410 } | 456 } |
| 411 | 457 |
| 458 void WebHistoryService::AudioHistoryCompletionCallback( |
| 459 const WebHistoryService::AudioWebHistoryCallback& callback, |
| 460 WebHistoryService::Request* request, |
| 461 bool success) { |
| 462 scoped_ptr<base::DictionaryValue> response_value; |
| 463 bool enabled_value = false; |
| 464 if (success) { |
| 465 response_value = ReadResponse(request); |
| 466 if (response_value) |
| 467 response_value->GetBoolean("history_recording_enabled", &enabled_value); |
| 468 } |
| 469 callback.Run(success, enabled_value); |
| 470 pending_audio_history_requests_.erase(request); |
| 471 delete request; |
| 472 } |
| 473 |
| 412 } // namespace history | 474 } // namespace history |
| OLD | NEW |