diff options
-rw-r--r-- | chrome/browser/history/web_history_service.cc | 128 | ||||
-rw-r--r-- | chrome/browser/history/web_history_service.h | 12 | ||||
-rw-r--r-- | chrome/browser/ui/webui/history_ui.cc | 24 | ||||
-rw-r--r-- | chrome/browser/ui/webui/history_ui.h | 8 |
4 files changed, 144 insertions, 28 deletions
diff --git a/chrome/browser/history/web_history_service.cc b/chrome/browser/history/web_history_service.cc index fc4882e..42d177c 100644 --- a/chrome/browser/history/web_history_service.cc +++ b/chrome/browser/history/web_history_service.cc @@ -4,7 +4,10 @@ #include "chrome/browser/history/web_history_service.h" +#include "base/bind.h" #include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/string_number_conversions.h" #include "base/values.h" #include "chrome/browser/signin/oauth2_token_service.h" #include "chrome/browser/signin/oauth2_token_service_factory.h" @@ -23,9 +26,14 @@ namespace { const char kHistoryOAuthScope[] = "https://www.googleapis.com/auth/chromesync"; -const char kHistoryGetHistoryUrl[] = +const char kHistoryQueryHistoryUrl[] = "https://history.google.com/history/api/lookup?client=chrome"; +const char kHistoryDeleteHistoryUrl[] = + "https://history.google.com/history/api/delete?client=chrome"; + +const char kPostDataMimeType[] = "text/plain"; + // The maximum number of retries for the URLFetcher requests. const size_t kMaxRetries = 1; @@ -36,13 +44,25 @@ class RequestImpl : public WebHistoryService::Request, virtual ~RequestImpl() { } + // Returns the response code received from the server, which will only be + // valid if the request succeeded. + int response_code() { return response_code_; } + + // Returns the contents of the response body received from the server. + const std::string& response_body() { return response_body_; } + private: friend class history::WebHistoryService; + typedef base::Callback<void(Request*, bool)> CompletionCallback; + RequestImpl(Profile* profile, const std::string& url, - const WebHistoryService::QueryWebHistoryCallback& callback) - : profile_(profile), url_(GURL(url)), query_history_callback_(callback) { + const CompletionCallback& callback) + : profile_(profile), + url_(GURL(url)), + response_code_(0), + callback_(callback) { } // Tells the request to do its thang. @@ -58,20 +78,10 @@ class RequestImpl : public WebHistoryService::Request, // content::URLFetcherDelegate interface. virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE { DCHECK_EQ(source, url_fetcher_.get()); - std::string result_body; - int response_code = url_fetcher_->GetResponseCode(); - url_fetcher_->GetResponseAsString(&result_body); + response_code_ = url_fetcher_->GetResponseCode(); + url_fetcher_->GetResponseAsString(&response_body_); url_fetcher_.reset(); - - if (response_code == net::HTTP_OK) { - scoped_ptr<base::Value> value(base::JSONReader::Read(result_body)); - if (value.get() && value->IsType(base::Value::TYPE_DICTIONARY)) { - query_history_callback_.Run(this, - static_cast<DictionaryValue*>(value.get())); - return; - } - } - query_history_callback_.Run(this, NULL); + callback_.Run(this, true); } // OAuth2TokenService::Consumer interface. @@ -92,43 +102,74 @@ class RequestImpl : public WebHistoryService::Request, const GoogleServiceAuthError& error) OVERRIDE { token_request_.reset(); LOG(WARNING) << "Failed to get OAuth token: " << error.ToString(); - query_history_callback_.Run(this, NULL); + callback_.Run(this, false); } // Helper for creating a new URLFetcher for the API request. net::URLFetcher* CreateUrlFetcher(const std::string& access_token) { + net::URLFetcher::RequestType request_type = post_data_.empty() ? + net::URLFetcher::GET : net::URLFetcher::POST; net::URLFetcher* fetcher = net::URLFetcher::Create( - url_, net::URLFetcher::GET, this); + url_, request_type, this); fetcher->SetRequestContext(profile_->GetRequestContext()); fetcher->SetMaxRetriesOn5xx(kMaxRetries); fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES); fetcher->AddExtraRequestHeader("Authorization: Bearer " + access_token); + if (request_type == net::URLFetcher::POST) + fetcher->SetUploadData(kPostDataMimeType, post_data_); return fetcher; } + void set_post_data(const std::string& post_data) { + post_data_ = post_data; + } + Profile* profile_; // The URL of the API endpoint. GURL url_; + // POST data to be sent with the request (may be empty). + std::string post_data_; + // The OAuth2 access token request. scoped_ptr<OAuth2TokenService::Request> token_request_; // Handles the actual API requests after the OAuth token is acquired. scoped_ptr<net::URLFetcher> url_fetcher_; - // The callback to execute when the query is complete, whether successful - // or not. - WebHistoryService::QueryWebHistoryCallback query_history_callback_; + // Holds the response code received from the server. + int response_code_; + + // Holds the response body received from the server. + std::string response_body_; + + // The callback to execute when the query is complete. + CompletionCallback callback_; }; +// Called when a query to web history has completed, successfully or not. +void QueryHistoryCompletionCallback( + const WebHistoryService::QueryWebHistoryCallback& callback, + WebHistoryService::Request* request, + bool success) { + RequestImpl* request_impl = static_cast<RequestImpl*>(request); + if (success && request_impl->response_code() == net::HTTP_OK) { + scoped_ptr<base::Value> value( + base::JSONReader::Read(request_impl->response_body())); + if (value.get() && value->IsType(base::Value::TYPE_DICTIONARY)) + callback.Run(request, static_cast<DictionaryValue*>(value.get())); + } + callback.Run(request, NULL); +} + } // namespace -WebHistoryService::Request::~Request() { +WebHistoryService::Request::Request() { } -WebHistoryService::Request::Request() { +WebHistoryService::Request::~Request() { } WebHistoryService::WebHistoryService(Profile* profile) @@ -142,8 +183,47 @@ scoped_ptr<WebHistoryService::Request> WebHistoryService::QueryHistory( const string16& text_query, const QueryOptions& options, const WebHistoryService::QueryWebHistoryCallback& callback) { + // Wrap the original callback into a generic completion callback. + RequestImpl::CompletionCallback completion_callback = base::Bind( + &QueryHistoryCompletionCallback, callback); + + scoped_ptr<RequestImpl> request( + new RequestImpl(profile_, kHistoryQueryHistoryUrl, completion_callback)); + request->Start(); + return request.PassAs<Request>(); +} + +scoped_ptr<WebHistoryService::Request> WebHistoryService::ExpireHistoryBetween( + const std::set<GURL>& urls, + base::Time begin_time, + base::Time end_time, + const WebHistoryService::ExpireWebHistoryCallback& callback) { + + // Determine the timestamps representing the beginning and end of the day. + std::string min_timestamp(base::Int64ToString( + (begin_time - base::Time::FromJsTime(0)).InMicroseconds())); + std::string max_timestamp(base::Int64ToString( + (end_time - base::Time::FromJsTime(0)).InMicroseconds())); + + DictionaryValue delete_request; + ListValue* deletions = new ListValue; + delete_request.Set("del", deletions); + + for (std::set<GURL>::const_iterator it = urls.begin(); + it != urls.end(); ++it) { + DictionaryValue* deletion = new DictionaryValue; + deletion->SetString("type", "CHROME_HISTORY"); + deletion->SetString("url", it->spec()); + deletion->SetString("min_timestamp_usec", min_timestamp); + deletion->SetString("max_timestamp_usec", max_timestamp); + deletions->Append(deletion); + } + std::string post_data; + base::JSONWriter::Write(&delete_request, &post_data); + scoped_ptr<RequestImpl> request( - new RequestImpl(profile_, kHistoryGetHistoryUrl, callback)); + new RequestImpl(profile_, kHistoryDeleteHistoryUrl, callback)); + request->set_post_data(post_data); request->Start(); return request.PassAs<Request>(); } diff --git a/chrome/browser/history/web_history_service.h b/chrome/browser/history/web_history_service.h index c3321a6..039ab14 100644 --- a/chrome/browser/history/web_history_service.h +++ b/chrome/browser/history/web_history_service.h @@ -30,6 +30,7 @@ class WebHistoryService : public ProfileKeyedService { class Request { public: virtual ~Request(); + protected: Request(); }; @@ -40,6 +41,9 @@ class WebHistoryService : public ProfileKeyedService { typedef base::Callback<void(Request*, const DictionaryValue*)> QueryWebHistoryCallback; + typedef base::Callback<void(Request*, bool success)> + ExpireWebHistoryCallback; + explicit WebHistoryService(Profile* profile); virtual ~WebHistoryService(); @@ -54,6 +58,14 @@ class WebHistoryService : public ProfileKeyedService { const QueryOptions& options, const QueryWebHistoryCallback& callback); + // Deletes all visits to the given set of URLs between |begin_time| and + // |end_time|. + scoped_ptr<Request> ExpireHistoryBetween( + const std::set<GURL>& restrict_urls, + base::Time begin_time, + base::Time end_time, + const ExpireWebHistoryCallback& callback); + private: Profile* profile_; diff --git a/chrome/browser/ui/webui/history_ui.cc b/chrome/browser/ui/webui/history_ui.cc index 75c1e50..88f5624 100644 --- a/chrome/browser/ui/webui/history_ui.cc +++ b/chrome/browser/ui/webui/history_ui.cc @@ -291,10 +291,7 @@ void BrowsingHistoryHandler::HandleRemoveURLsOnOneDay(const ListValue* args) { web_ui()->CallJavascriptFunction("deleteFailed"); return; } - base::Time::Exploded exploded; - base::Time::FromJsTime(visit_time).LocalExplode(&exploded); - exploded.hour = exploded.minute = exploded.second = exploded.millisecond = 0; - base::Time begin_time = base::Time::FromLocalExploded(exploded); + base::Time begin_time = base::Time::FromJsTime(visit_time).LocalMidnight(); base::Time end_time = begin_time + base::TimeDelta::FromDays(1); // Get URLs. @@ -311,6 +308,7 @@ void BrowsingHistoryHandler::HandleRemoveURLsOnOneDay(const ListValue* args) { urls_to_be_deleted_.insert(GURL(string16_value)); } + Profile* profile = Profile::FromWebUI(web_ui()); HistoryService* hs = HistoryServiceFactory::GetForProfile( Profile::FromWebUI(web_ui()), Profile::EXPLICIT_ACCESS); hs->ExpireHistoryBetween( @@ -318,6 +316,17 @@ void BrowsingHistoryHandler::HandleRemoveURLsOnOneDay(const ListValue* args) { base::Bind(&BrowsingHistoryHandler::RemoveComplete, base::Unretained(this)), &delete_task_tracker_); + + history::WebHistoryService* web_history = + WebHistoryServiceFactory::GetForProfile(profile); + if (web_history) { + web_history_delete_request_ = web_history->ExpireHistoryBetween( + urls_to_be_deleted_, + begin_time, + end_time, + base::Bind(&BrowsingHistoryHandler::RemoveWebHistoryComplete, + base::Unretained(this))); + } } void BrowsingHistoryHandler::HandleClearBrowsingData(const ListValue* args) { @@ -477,6 +486,13 @@ void BrowsingHistoryHandler::RemoveComplete() { web_ui()->CallJavascriptFunction("deleteComplete"); } +void BrowsingHistoryHandler::RemoveWebHistoryComplete( + history::WebHistoryService::Request* request, bool success) { + // Notify the page that the deletion request is complete. + base::FundamentalValue success_value(success); + web_ui()->CallJavascriptFunction("webHistoryDeleteComplete", success_value); +} + // Helper function for Observe that determines if there are any differences // between the URLs noticed for deletion and the ones we are expecting. static bool DeletionsDiffer(const history::URLRows& deleted_rows, diff --git a/chrome/browser/ui/webui/history_ui.h b/chrome/browser/ui/webui/history_ui.h index 5ee6cde..6e3acb7 100644 --- a/chrome/browser/ui/webui/history_ui.h +++ b/chrome/browser/ui/webui/history_ui.h @@ -77,6 +77,10 @@ class BrowsingHistoryHandler : public content::WebUIMessageHandler, // Callback from the history system when visits were deleted. void RemoveComplete(); + // Callback from history server when visits were deleted. + void RemoveWebHistoryComplete(history::WebHistoryService::Request* request, + bool success); + bool ExtractIntegerValueAtIndex( const base::ListValue* value, int index, int* out_int); @@ -95,6 +99,10 @@ class BrowsingHistoryHandler : public content::WebUIMessageHandler, // Deleting the request will cancel it. scoped_ptr<history::WebHistoryService::Request> web_history_request_; + // The currently-executing delete request for synced history. + // Deleting the request will cancel it. + scoped_ptr<history::WebHistoryService::Request> web_history_delete_request_; + // Tracker for delete requests to the history service. CancelableTaskTracker delete_task_tracker_; |