web_history_service.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/utf_string_conversions.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/signin/oauth2_token_service.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/signin/oauth2_token_service_factory.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/gaia_urls.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "googleurl/src/gurl.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/load_flags.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/url_util.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_status_code.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_fetcher.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace history { 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kHistoryOAuthScope[] = 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "https://www.googleapis.com/auth/chromesync"; 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kHistoryQueryHistoryUrl[] = 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "https://history.google.com/history/api/lookup?client=chrome"; 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kHistoryDeleteHistoryUrl[] = 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "https://history.google.com/history/api/delete?client=chrome"; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kPostDataMimeType[] = "text/plain"; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The maximum number of retries for the URLFetcher requests. 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kMaxRetries = 1; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class RequestImpl : public WebHistoryService::Request, 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private OAuth2TokenService::Consumer, 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private net::URLFetcherDelegate { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~RequestImpl() { 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns the response code received from the server, which will only be 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // valid if the request succeeded. 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int response_code() { return response_code_; } 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns the contents of the response body received from the server. 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& response_body() { return response_body_; } 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) friend class history::WebHistoryService; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef base::Callback<void(Request*, bool)> CompletionCallback; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RequestImpl(Profile* profile, 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& url, 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CompletionCallback& callback) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : profile_(profile), 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_(GURL(url)), 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_code_(0), 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_(callback) { 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Tells the request to do its thang. 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Start() { 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OAuth2TokenService::ScopeSet oauth_scopes; 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) oauth_scopes.insert(kHistoryOAuthScope); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OAuth2TokenService* token_service = 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OAuth2TokenServiceFactory::GetForProfile(profile_); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) token_request_ = token_service->StartRequest(oauth_scopes, this); 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // content::URLFetcherDelegate interface. 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(source, url_fetcher_.get()); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_code_ = url_fetcher_->GetResponseCode(); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_fetcher_->GetResponseAsString(&response_body_); 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_fetcher_.reset(); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_.Run(this, true); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // OAuth2TokenService::Consumer interface. 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnGetTokenSuccess( 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const OAuth2TokenService::Request* request, 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& access_token, 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Time& expiration_time) OVERRIDE { 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) token_request_.reset(); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!access_token.empty()); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Got an access token -- start the actual API request. 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_fetcher_.reset(CreateUrlFetcher(access_token)); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_fetcher_->Start(); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnGetTokenFailure( 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const OAuth2TokenService::Request* request, 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GoogleServiceAuthError& error) OVERRIDE { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) token_request_.reset(); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Failed to get OAuth token: " << error.ToString(); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_.Run(this, false); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Helper for creating a new URLFetcher for the API request. 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::URLFetcher* CreateUrlFetcher(const std::string& access_token) { 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::URLFetcher::RequestType request_type = post_data_.empty() ? 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::URLFetcher::GET : net::URLFetcher::POST; 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::URLFetcher* fetcher = net::URLFetcher::Create( 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_, request_type, this); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->SetRequestContext(profile_->GetRequestContext()); 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->SetMaxRetriesOn5xx(kMaxRetries); 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::LOAD_DO_NOT_SAVE_COOKIES); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->AddExtraRequestHeader("Authorization: Bearer " + access_token); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->AddExtraRequestHeader("X-Developer-Key: " + 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_id()); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (request_type == net::URLFetcher::POST) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->SetUploadData(kPostDataMimeType, post_data_); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return fetcher; 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void set_post_data(const std::string& post_data) { 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) post_data_ = post_data; 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile_; 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The URL of the API endpoint. 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url_; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // POST data to be sent with the request (may be empty). 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string post_data_; 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The OAuth2 access token request. 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<OAuth2TokenService::Request> token_request_; 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Handles the actual API requests after the OAuth token is acquired. 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<net::URLFetcher> url_fetcher_; 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Holds the response code received from the server. 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int response_code_; 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Holds the response body received from the server. 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string response_body_; 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The callback to execute when the query is complete. 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CompletionCallback callback_; 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called when a query to web history has completed, successfully or not. 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QueryHistoryCompletionCallback( 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const WebHistoryService::QueryWebHistoryCallback& callback, 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebHistoryService::Request* request, 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success) { 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RequestImpl* request_impl = static_cast<RequestImpl*>(request); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (success && request_impl->response_code() == net::HTTP_OK) { 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::Value> value( 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::JSONReader::Read(request_impl->response_body())); 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (value.get() && value->IsType(base::Value::TYPE_DICTIONARY)) { 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.Run(request, static_cast<DictionaryValue*>(value.get())); 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.Run(request, NULL); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Converts a time into a string for use as a parameter in a request to the 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// history server. 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string ServerTimeString(base::Time time) { 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::Int64ToString((time - base::Time::UnixEpoch()).InMicroseconds()); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns a URL for querying the history server for a query specified by 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |options|. 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string GetQueryUrl(const string16& text_query, 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const QueryOptions& options) { 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url = GURL(kHistoryQueryHistoryUrl); 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url = net::AppendQueryParameter(url, "titles", "1"); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Take |begin_time|, |end_time|, and |max_count| from the original query 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // options, and convert them to the equivalent URL parameters. 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time end_time = 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::min(base::Time::FromInternalValue(options.EffectiveEndTime()), 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now()); 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url = net::AppendQueryParameter(url, "max", ServerTimeString(end_time)); 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!options.begin_time.is_null()) { 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url = net::AppendQueryParameter( 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url, "min", ServerTimeString(options.begin_time)); 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (options.max_count) { 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url = net::AppendQueryParameter( 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url, "num", base::IntToString(options.max_count)); 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!text_query.empty()) 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url = net::AppendQueryParameter(url, "q", UTF16ToUTF8(text_query)); 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return url.spec(); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Creates a DictionaryValue to hold the parameters for a deletion. 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Ownership is passed to the caller. 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |url| may be empty, indicating a time-range deletion. 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DictionaryValue* CreateDeletion( 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& min_time, 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& max_time, 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& url) { 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DictionaryValue* deletion = new DictionaryValue; 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deletion->SetString("type", "CHROME_HISTORY"); 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (url.is_valid()) 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deletion->SetString("url", url.spec()); 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deletion->SetString("min_timestamp_usec", min_time); 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deletion->SetString("max_timestamp_usec", max_time); 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return deletion; 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebHistoryService::Request::Request() { 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebHistoryService::Request::~Request() { 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebHistoryService::WebHistoryService(Profile* profile) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : profile_(profile) { 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebHistoryService::~WebHistoryService() { 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<WebHistoryService::Request> WebHistoryService::QueryHistory( 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const string16& text_query, 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const QueryOptions& options, 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const WebHistoryService::QueryWebHistoryCallback& callback) { 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Wrap the original callback into a generic completion callback. 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RequestImpl::CompletionCallback completion_callback = base::Bind( 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &QueryHistoryCompletionCallback, callback); 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string url = GetQueryUrl(text_query, options); 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<RequestImpl> request( 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new RequestImpl(profile_, url, completion_callback)); 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request->Start(); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return request.PassAs<Request>(); 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<WebHistoryService::Request> WebHistoryService::ExpireHistory( 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ExpireHistoryArgs>& expire_list, 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ExpireWebHistoryCallback& callback) { 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DictionaryValue delete_request; 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<ListValue> deletions(new ListValue); 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time now = base::Time::Now(); 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<ExpireHistoryArgs>::const_iterator it = expire_list.begin(); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != expire_list.end(); ++it) { 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Convert the times to server timestamps. 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string min_timestamp = ServerTimeString(it->begin_time); 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(dubroy): Use sane time (crbug.com/146090) here when it's available. 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time end_time = it->end_time; 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (end_time.is_null() || end_time > now) 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) end_time = now; 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string max_timestamp = ServerTimeString(end_time); 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::set<GURL>::const_iterator url_iterator = it->urls.begin(); 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_iterator != it->urls.end(); ++url_iterator) { 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deletions->Append( 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDeletion(min_timestamp, max_timestamp, *url_iterator)); 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If no URLs were specified, delete everything in the time range. 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->urls.empty()) 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deletions->Append(CreateDeletion(min_timestamp, max_timestamp, GURL())); 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_request.Set("del", deletions.release()); 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string post_data; 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::JSONWriter::Write(&delete_request, &post_data); 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<RequestImpl> request( 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new RequestImpl(profile_, kHistoryDeleteHistoryUrl, callback)); 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request->set_post_data(post_data); 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request->Start(); 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return request.PassAs<Request>(); 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<WebHistoryService::Request> WebHistoryService::ExpireHistoryBetween( 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::set<GURL>& restrict_urls, 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time begin_time, 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time end_time, 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ExpireWebHistoryCallback& callback) { 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<ExpireHistoryArgs> expire_list(1); 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expire_list.back().urls = restrict_urls; 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expire_list.back().begin_time = begin_time; 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expire_list.back().end_time = end_time; 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ExpireHistory(expire_list, callback); 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace history 306