12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/web_history_service.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_reader.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_writer.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/metrics/histogram.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/stl_util.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h" 17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/profile_oauth2_token_service.h" 18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_manager.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/gaia_urls.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h" 21424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "google_apis/gaia/oauth2_token_service.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/load_flags.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/url_util.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_status_code.h" 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/http/http_util.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_fetcher.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h" 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace history { 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kHistoryOAuthScope[] = 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "https://www.googleapis.com/auth/chromesync"; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kHistoryQueryHistoryUrl[] = 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "https://history.google.com/history/api/lookup?client=chrome"; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kHistoryDeleteHistoryUrl[] = 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "https://history.google.com/history/api/delete?client=chrome"; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kPostDataMimeType[] = "text/plain"; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The maximum number of retries for the URLFetcher requests. 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kMaxRetries = 1; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class RequestImpl : public WebHistoryService::Request, 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private OAuth2TokenService::Consumer, 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private net::URLFetcherDelegate { 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~RequestImpl() { 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns the response code received from the server, which will only be 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // valid if the request succeeded. 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int response_code() { return response_code_; } 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns the contents of the response body received from the server. 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& response_body() { return response_body_; } 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual bool is_pending() OVERRIDE { return is_pending_; } 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) friend class history::WebHistoryService; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef base::Callback<void(Request*, bool)> CompletionCallback; 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RequestImpl(Profile* profile, 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const GURL& url, 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CompletionCallback& callback) 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : OAuth2TokenService::Consumer("web_history"), 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) profile_(profile), 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_(url), 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_code_(0), 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) auth_retry_count_(0), 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback_(callback), 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_pending_(false) { 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Tells the request to do its thang. 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Start() { 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OAuth2TokenService::ScopeSet oauth_scopes; 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) oauth_scopes.insert(kHistoryOAuthScope); 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProfileOAuth2TokenService* token_service = 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SigninManagerBase* signin_manager = 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SigninManagerFactory::GetForProfile(profile_); 9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) token_request_ = token_service->StartRequest( 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) signin_manager->GetAuthenticatedAccountId(), oauth_scopes, this); 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_pending_ = true; 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // content::URLFetcherDelegate interface. 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE { 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(source, url_fetcher_.get()); 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_code_ = url_fetcher_->GetResponseCode(); 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_ENUMERATION("WebHistory.OAuthTokenResponseCode", 101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) net::HttpUtil::MapStatusCodeForHistogram(response_code_), 102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) net::HttpUtil::GetStatusCodesForHistogram()); 103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If the response code indicates that the token might not be valid, 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // invalidate the token and try again. 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (response_code_ == net::HTTP_UNAUTHORIZED && ++auth_retry_count_ <= 1) { 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OAuth2TokenService::ScopeSet oauth_scopes; 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) oauth_scopes.insert(kHistoryOAuthScope); 10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ProfileOAuth2TokenService* token_service = 11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SigninManagerBase* signin_manager = 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SigninManagerFactory::GetForProfile(profile_); 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) token_service->InvalidateToken( 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) signin_manager->GetAuthenticatedAccountId(), 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) oauth_scopes, 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) access_token_); 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) access_token_.clear(); 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Start(); 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_fetcher_->GetResponseAsString(&response_body_); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_fetcher_.reset(); 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_pending_ = false; 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_.Run(this, true); 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // It is valid for the callback to delete |this|, so do not access any 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // members below here. 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // OAuth2TokenService::Consumer interface. 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnGetTokenSuccess( 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const OAuth2TokenService::Request* request, 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& access_token, 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Time& expiration_time) OVERRIDE { 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) token_request_.reset(); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!access_token.empty()); 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) access_token_ = access_token; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("WebHistory.OAuthTokenCompletion", true); 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Got an access token -- start the actual API request. 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_fetcher_.reset(CreateUrlFetcher(access_token)); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_fetcher_->Start(); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnGetTokenFailure( 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const OAuth2TokenService::Request* request, 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GoogleServiceAuthError& error) OVERRIDE { 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) token_request_.reset(); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_pending_ = false; 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("WebHistory.OAuthTokenCompletion", false); 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_.Run(this, false); 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // It is valid for the callback to delete |this|, so do not access any 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // members below here. 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Helper for creating a new URLFetcher for the API request. 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::URLFetcher* CreateUrlFetcher(const std::string& access_token) { 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::URLFetcher::RequestType request_type = post_data_.empty() ? 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::URLFetcher::GET : net::URLFetcher::POST; 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::URLFetcher* fetcher = net::URLFetcher::Create( 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_, request_type, this); 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->SetRequestContext(profile_->GetRequestContext()); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->SetMaxRetriesOn5xx(kMaxRetries); 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::LOAD_DO_NOT_SAVE_COOKIES); 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->AddExtraRequestHeader("Authorization: Bearer " + access_token); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->AddExtraRequestHeader("X-Developer-Key: " + 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_id()); 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (request_type == net::URLFetcher::POST) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->SetUploadData(kPostDataMimeType, post_data_); 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return fetcher; 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void set_post_data(const std::string& post_data) { 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) post_data_ = post_data; 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile_; 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The URL of the API endpoint. 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url_; 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // POST data to be sent with the request (may be empty). 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string post_data_; 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The OAuth2 access token request. 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<OAuth2TokenService::Request> token_request_; 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The current OAuth2 access token. 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string access_token_; 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Handles the actual API requests after the OAuth token is acquired. 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<net::URLFetcher> url_fetcher_; 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Holds the response code received from the server. 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int response_code_; 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Holds the response body received from the server. 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string response_body_; 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The number of times this request has already been retried due to 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // authorization problems. 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int auth_retry_count_; 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The callback to execute when the query is complete. 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CompletionCallback callback_; 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // True if the request was started and has not yet completed, otherwise false. 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool is_pending_; 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Extracts a JSON-encoded HTTP response into a DictionaryValue. 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// If |request|'s HTTP response code indicates failure, or if the response 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// body is not JSON, a null pointer is returned. 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<base::DictionaryValue> ReadResponse(RequestImpl* request) { 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> result; 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (request->response_code() == net::HTTP_OK) { 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Value* value = base::JSONReader::Read(request->response_body()); 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (value && value->IsType(base::Value::TYPE_DICTIONARY)) 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.reset(static_cast<base::DictionaryValue*>(value)); 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DLOG(WARNING) << "Non-JSON response received from history server."; 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result.Pass(); 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Converts a time into a string for use as a parameter in a request to the 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// history server. 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string ServerTimeString(base::Time time) { 233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (time < base::Time::UnixEpoch()) { 234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return base::Int64ToString(0); 235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return base::Int64ToString( 237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (time - base::Time::UnixEpoch()).InMicroseconds()); 238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns a URL for querying the history server for a query specified by 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// |options|. |version_info|, if not empty, should be a token that was received 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// from the server in response to a write operation. It is used to help ensure 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// read consistency after a write. 245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)GURL GetQueryUrl(const base::string16& text_query, 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const QueryOptions& options, 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& version_info) { 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url = GURL(kHistoryQueryHistoryUrl); 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url = net::AppendQueryParameter(url, "titles", "1"); 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Take |begin_time|, |end_time|, and |max_count| from the original query 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // options, and convert them to the equivalent URL parameters. 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time end_time = 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::min(base::Time::FromInternalValue(options.EffectiveEndTime()), 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now()); 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url = net::AppendQueryParameter(url, "max", ServerTimeString(end_time)); 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!options.begin_time.is_null()) { 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url = net::AppendQueryParameter( 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url, "min", ServerTimeString(options.begin_time)); 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (options.max_count) { 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url = net::AppendQueryParameter( 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url, "num", base::IntToString(options.max_count)); 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!text_query.empty()) 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url = net::AppendQueryParameter(url, "q", base::UTF16ToUTF8(text_query)); 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!version_info.empty()) 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url = net::AppendQueryParameter(url, "kvi", version_info); 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return url; 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Creates a DictionaryValue to hold the parameters for a deletion. 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Ownership is passed to the caller. 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |url| may be empty, indicating a time-range deletion. 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::DictionaryValue* CreateDeletion( 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& min_time, 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& max_time, 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& url) { 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue* deletion = new base::DictionaryValue; 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deletion->SetString("type", "CHROME_HISTORY"); 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (url.is_valid()) 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deletion->SetString("url", url.spec()); 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deletion->SetString("min_timestamp_usec", min_time); 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deletion->SetString("max_timestamp_usec", max_time); 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return deletion; 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebHistoryService::Request::Request() { 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebHistoryService::Request::~Request() { 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebHistoryService::WebHistoryService(Profile* profile) 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : profile_(profile), 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_(this) { 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebHistoryService::~WebHistoryService() { 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) STLDeleteElements(&pending_expire_requests_); 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<WebHistoryService::Request> WebHistoryService::QueryHistory( 312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& text_query, 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const QueryOptions& options, 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const WebHistoryService::QueryWebHistoryCallback& callback) { 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Wrap the original callback into a generic completion callback. 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RequestImpl::CompletionCallback completion_callback = base::Bind( 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &WebHistoryService::QueryHistoryCompletionCallback, callback); 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL url = GetQueryUrl(text_query, options, server_version_info_); 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<RequestImpl> request( 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new RequestImpl(profile_, url, completion_callback)); 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request->Start(); 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return request.PassAs<Request>(); 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebHistoryService::ExpireHistory( 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ExpireHistoryArgs>& expire_list, 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ExpireWebHistoryCallback& callback) { 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::DictionaryValue delete_request; 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> deletions(new base::ListValue); 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time now = base::Time::Now(); 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<ExpireHistoryArgs>::const_iterator it = expire_list.begin(); 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != expire_list.end(); ++it) { 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Convert the times to server timestamps. 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string min_timestamp = ServerTimeString(it->begin_time); 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(dubroy): Use sane time (crbug.com/146090) here when it's available. 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time end_time = it->end_time; 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (end_time.is_null() || end_time > now) 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) end_time = now; 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string max_timestamp = ServerTimeString(end_time); 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::set<GURL>::const_iterator url_iterator = it->urls.begin(); 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_iterator != it->urls.end(); ++url_iterator) { 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deletions->Append( 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeletion(min_timestamp, max_timestamp, *url_iterator)); 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If no URLs were specified, delete everything in the time range. 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->urls.empty()) 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deletions->Append(CreateDeletion(min_timestamp, max_timestamp, GURL())); 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_request.Set("del", deletions.release()); 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string post_data; 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::JSONWriter::Write(&delete_request, &post_data); 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL url(kHistoryDeleteHistoryUrl); 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Append the version info token, if it is available, to help ensure 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // consistency with any previous deletions. 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!server_version_info_.empty()) 361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url = net::AppendQueryParameter(url, "kvi", server_version_info_); 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Wrap the original callback into a generic completion callback. 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RequestImpl::CompletionCallback completion_callback = 365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&WebHistoryService::ExpireHistoryCompletionCallback, 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback); 368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<RequestImpl> request( 370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new RequestImpl(profile_, url, completion_callback)); 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request->set_post_data(post_data); 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request->Start(); 373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pending_expire_requests_.insert(request.release()); 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebHistoryService::ExpireHistoryBetween( 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::set<GURL>& restrict_urls, 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time begin_time, 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time end_time, 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ExpireWebHistoryCallback& callback) { 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<ExpireHistoryArgs> expire_list(1); 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expire_list.back().urls = restrict_urls; 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expire_list.back().begin_time = begin_time; 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expire_list.back().end_time = end_time; 385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ExpireHistory(expire_list, callback); 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebHistoryService::QueryHistoryCompletionCallback( 390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const WebHistoryService::QueryWebHistoryCallback& callback, 391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebHistoryService::Request* request, 392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool success) { 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> response_value; 394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (success) 395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) response_value = ReadResponse(static_cast<RequestImpl*>(request)); 396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback.Run(request, response_value.get()); 397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebHistoryService::ExpireHistoryCompletionCallback( 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const WebHistoryService::ExpireWebHistoryCallback& callback, 401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WebHistoryService::Request* request, 402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool success) { 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> response_value; 404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (success) { 405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) response_value = ReadResponse(static_cast<RequestImpl*>(request)); 406b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (response_value) 407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) response_value->GetString("version_info", &server_version_info_); 408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) callback.Run(response_value.get() && success); 410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Clean up from pending requests. 411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pending_expire_requests_.erase(request); 412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delete request; 413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace history 416