summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/history/web_history_service.cc128
-rw-r--r--chrome/browser/history/web_history_service.h12
-rw-r--r--chrome/browser/ui/webui/history_ui.cc24
-rw-r--r--chrome/browser/ui/webui/history_ui.h8
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_;