blob: 58ffbb0583994e709dd524a6ece9151e6502f8bc [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/google_apis/drive_api_requests.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/json/json_writer.h"
#include "base/values.h"
#include "chrome/browser/google_apis/drive_api_parser.h"
#include "chrome/browser/google_apis/request_util.h"
#include "chrome/browser/google_apis/time_util.h"
namespace google_apis {
namespace {
const char kContentTypeApplicationJson[] = "application/json";
const char kDirectoryMimeType[] = "application/vnd.google-apps.folder";
const char kParentLinkKind[] = "drive#fileLink";
// Parses the JSON value to a resource typed |T| and runs |callback| on the UI
// thread once parsing is done.
template<typename T>
void ParseJsonAndRun(
const base::Callback<void(GDataErrorCode, scoped_ptr<T>)>& callback,
GDataErrorCode error,
scoped_ptr<base::Value> value) {
DCHECK(!callback.is_null());
scoped_ptr<T> resource;
if (value) {
resource = T::CreateFrom(*value);
if (!resource) {
// Failed to parse the JSON value, although the JSON value is available,
// so let the callback know the parsing error.
error = GDATA_PARSE_ERROR;
}
}
callback.Run(error, resource.Pass());
}
// Parses the JSON value to FileResource instance and runs |callback| on the
// UI thread once parsing is done.
// This is customized version of ParseJsonAndRun defined above to adapt the
// remaining response type.
void ParseFileResourceWithUploadRangeAndRun(
const drive::UploadRangeCallback& callback,
const UploadRangeResponse& response,
scoped_ptr<base::Value> value) {
DCHECK(!callback.is_null());
scoped_ptr<FileResource> file_resource;
if (value) {
file_resource = FileResource::CreateFrom(*value);
if (!file_resource) {
callback.Run(
UploadRangeResponse(GDATA_PARSE_ERROR,
response.start_position_received,
response.end_position_received),
scoped_ptr<FileResource>());
return;
}
}
callback.Run(response, file_resource.Pass());
}
} // namespace
//============================== GetAboutRequest =============================
GetAboutRequest::GetAboutRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const GetAboutResourceCallback& callback)
: GetDataRequest(sender,
base::Bind(&ParseJsonAndRun<AboutResource>, callback)),
url_generator_(url_generator) {
DCHECK(!callback.is_null());
}
GetAboutRequest::~GetAboutRequest() {}
GURL GetAboutRequest::GetURL() const {
return url_generator_.GetAboutUrl();
}
//============================== GetApplistRequest ===========================
GetApplistRequest::GetApplistRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const GetDataCallback& callback)
: GetDataRequest(sender, callback),
url_generator_(url_generator) {
DCHECK(!callback.is_null());
}
GetApplistRequest::~GetApplistRequest() {}
GURL GetApplistRequest::GetURL() const {
return url_generator_.GetApplistUrl();
}
//============================ GetChangelistRequest ==========================
GetChangelistRequest::GetChangelistRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
bool include_deleted,
int64 start_changestamp,
int max_results,
const GetDataCallback& callback)
: GetDataRequest(sender, callback),
url_generator_(url_generator),
include_deleted_(include_deleted),
start_changestamp_(start_changestamp),
max_results_(max_results) {
DCHECK(!callback.is_null());
}
GetChangelistRequest::~GetChangelistRequest() {}
GURL GetChangelistRequest::GetURL() const {
return url_generator_.GetChangelistUrl(
include_deleted_, start_changestamp_, max_results_);
}
//============================= GetFilelistRequest ===========================
GetFilelistRequest::GetFilelistRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const std::string& search_string,
int max_results,
const GetDataCallback& callback)
: GetDataRequest(sender, callback),
url_generator_(url_generator),
search_string_(search_string),
max_results_(max_results) {
DCHECK(!callback.is_null());
}
GetFilelistRequest::~GetFilelistRequest() {}
GURL GetFilelistRequest::GetURL() const {
return url_generator_.GetFilelistUrl(search_string_, max_results_);
}
//=============================== GetFileRequest =============================
GetFileRequest::GetFileRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const std::string& file_id,
const FileResourceCallback& callback)
: GetDataRequest(sender,
base::Bind(&ParseJsonAndRun<FileResource>, callback)),
url_generator_(url_generator),
file_id_(file_id) {
DCHECK(!callback.is_null());
}
GetFileRequest::~GetFileRequest() {}
GURL GetFileRequest::GetURL() const {
return url_generator_.GetFileUrl(file_id_);
}
namespace drive {
//======================= ContinueGetFileListRequest =========================
ContinueGetFileListRequest::ContinueGetFileListRequest(
RequestSender* sender,
const GURL& url,
const GetDataCallback& callback)
: GetDataRequest(sender, callback),
url_(url) {
DCHECK(!callback.is_null());
}
ContinueGetFileListRequest::~ContinueGetFileListRequest() {}
GURL ContinueGetFileListRequest::GetURL() const {
return url_;
}
//========================== CreateDirectoryRequest ==========================
CreateDirectoryRequest::CreateDirectoryRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const std::string& parent_resource_id,
const std::string& directory_title,
const FileResourceCallback& callback)
: GetDataRequest(sender,
base::Bind(&ParseJsonAndRun<FileResource>, callback)),
url_generator_(url_generator),
parent_resource_id_(parent_resource_id),
directory_title_(directory_title) {
DCHECK(!callback.is_null());
DCHECK(!parent_resource_id_.empty());
DCHECK(!directory_title_.empty());
}
CreateDirectoryRequest::~CreateDirectoryRequest() {}
GURL CreateDirectoryRequest::GetURL() const {
return url_generator_.GetFilesUrl();
}
net::URLFetcher::RequestType CreateDirectoryRequest::GetRequestType() const {
return net::URLFetcher::POST;
}
bool CreateDirectoryRequest::GetContentData(std::string* upload_content_type,
std::string* upload_content) {
*upload_content_type = kContentTypeApplicationJson;
base::DictionaryValue root;
root.SetString("title", directory_title_);
{
base::DictionaryValue* parent_value = new base::DictionaryValue;
parent_value->SetString("id", parent_resource_id_);
base::ListValue* parent_list_value = new base::ListValue;
parent_list_value->Append(parent_value);
root.Set("parents", parent_list_value);
}
root.SetString("mimeType", kDirectoryMimeType);
base::JSONWriter::Write(&root, upload_content);
DVLOG(1) << "CreateDirectory data: " << *upload_content_type << ", ["
<< *upload_content << "]";
return true;
}
//=========================== RenameResourceRequest ==========================
RenameResourceRequest::RenameResourceRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const std::string& resource_id,
const std::string& new_title,
const EntryActionCallback& callback)
: EntryActionRequest(sender, callback),
url_generator_(url_generator),
resource_id_(resource_id),
new_title_(new_title) {
DCHECK(!callback.is_null());
}
RenameResourceRequest::~RenameResourceRequest() {}
net::URLFetcher::RequestType RenameResourceRequest::GetRequestType() const {
return net::URLFetcher::PATCH;
}
std::vector<std::string>
RenameResourceRequest::GetExtraRequestHeaders() const {
std::vector<std::string> headers;
headers.push_back(util::kIfMatchAllHeader);
return headers;
}
GURL RenameResourceRequest::GetURL() const {
return url_generator_.GetFileUrl(resource_id_);
}
bool RenameResourceRequest::GetContentData(std::string* upload_content_type,
std::string* upload_content) {
*upload_content_type = kContentTypeApplicationJson;
base::DictionaryValue root;
root.SetString("title", new_title_);
base::JSONWriter::Write(&root, upload_content);
DVLOG(1) << "RenameResource data: " << *upload_content_type << ", ["
<< *upload_content << "]";
return true;
}
//=========================== TouchResourceRequest ===========================
TouchResourceRequest::TouchResourceRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const std::string& resource_id,
const base::Time& modified_date,
const base::Time& last_viewed_by_me_date,
const FileResourceCallback& callback)
: GetDataRequest(sender,
base::Bind(&ParseJsonAndRun<FileResource>, callback)),
url_generator_(url_generator),
resource_id_(resource_id),
modified_date_(modified_date),
last_viewed_by_me_date_(last_viewed_by_me_date) {
DCHECK(!modified_date.is_null());
DCHECK(!last_viewed_by_me_date.is_null());
DCHECK(!callback.is_null());
}
TouchResourceRequest::~TouchResourceRequest() {}
net::URLFetcher::RequestType TouchResourceRequest::GetRequestType() const {
return net::URLFetcher::PATCH;
}
std::vector<std::string>
TouchResourceRequest::GetExtraRequestHeaders() const {
std::vector<std::string> headers;
headers.push_back(util::kIfMatchAllHeader);
return headers;
}
GURL TouchResourceRequest::GetURL() const {
return url_generator_.GetFileTouchUrl(resource_id_);
}
bool TouchResourceRequest::GetContentData(std::string* upload_content_type,
std::string* upload_content) {
*upload_content_type = kContentTypeApplicationJson;
base::DictionaryValue root;
root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));
root.SetString("lastViewedByMeDate",
util::FormatTimeAsString(last_viewed_by_me_date_));
base::JSONWriter::Write(&root, upload_content);
DVLOG(1) << "TouchResource data: " << *upload_content_type << ", ["
<< *upload_content << "]";
return true;
}
//=========================== CopyResourceRequest ============================
CopyResourceRequest::CopyResourceRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const std::string& resource_id,
const std::string& parent_resource_id,
const std::string& new_title,
const FileResourceCallback& callback)
: GetDataRequest(sender,
base::Bind(&ParseJsonAndRun<FileResource>, callback)),
url_generator_(url_generator),
resource_id_(resource_id),
parent_resource_id_(parent_resource_id),
new_title_(new_title) {
DCHECK(!callback.is_null());
}
CopyResourceRequest::~CopyResourceRequest() {
}
net::URLFetcher::RequestType CopyResourceRequest::GetRequestType() const {
return net::URLFetcher::POST;
}
GURL CopyResourceRequest::GetURL() const {
return url_generator_.GetFileCopyUrl(resource_id_);
}
bool CopyResourceRequest::GetContentData(std::string* upload_content_type,
std::string* upload_content) {
*upload_content_type = kContentTypeApplicationJson;
base::DictionaryValue root;
root.SetString("title", new_title_);
if (!parent_resource_id_.empty()) {
// Set the parent resource (destination directory) of the new resource.
base::ListValue* parents = new base::ListValue;
root.Set("parents", parents);
base::DictionaryValue* parent_value = new base::DictionaryValue;
parents->Append(parent_value);
parent_value->SetString("id", parent_resource_id_);
}
base::JSONWriter::Write(&root, upload_content);
DVLOG(1) << "CopyResource data: " << *upload_content_type << ", ["
<< *upload_content << "]";
return true;
}
//=========================== TrashResourceRequest ===========================
TrashResourceRequest::TrashResourceRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const std::string& resource_id,
const EntryActionCallback& callback)
: EntryActionRequest(sender, callback),
url_generator_(url_generator),
resource_id_(resource_id) {
DCHECK(!callback.is_null());
}
TrashResourceRequest::~TrashResourceRequest() {}
GURL TrashResourceRequest::GetURL() const {
return url_generator_.GetFileTrashUrl(resource_id_);
}
net::URLFetcher::RequestType TrashResourceRequest::GetRequestType() const {
return net::URLFetcher::POST;
}
//========================== InsertResourceRequest ===========================
InsertResourceRequest::InsertResourceRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const std::string& parent_resource_id,
const std::string& resource_id,
const EntryActionCallback& callback)
: EntryActionRequest(sender, callback),
url_generator_(url_generator),
parent_resource_id_(parent_resource_id),
resource_id_(resource_id) {
DCHECK(!callback.is_null());
}
InsertResourceRequest::~InsertResourceRequest() {}
GURL InsertResourceRequest::GetURL() const {
return url_generator_.GetChildrenUrl(parent_resource_id_);
}
net::URLFetcher::RequestType InsertResourceRequest::GetRequestType() const {
return net::URLFetcher::POST;
}
bool InsertResourceRequest::GetContentData(std::string* upload_content_type,
std::string* upload_content) {
*upload_content_type = kContentTypeApplicationJson;
base::DictionaryValue root;
root.SetString("id", resource_id_);
base::JSONWriter::Write(&root, upload_content);
DVLOG(1) << "InsertResource data: " << *upload_content_type << ", ["
<< *upload_content << "]";
return true;
}
//========================== DeleteResourceRequest ===========================
DeleteResourceRequest::DeleteResourceRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const std::string& parent_resource_id,
const std::string& resource_id,
const EntryActionCallback& callback)
: EntryActionRequest(sender, callback),
url_generator_(url_generator),
parent_resource_id_(parent_resource_id),
resource_id_(resource_id) {
DCHECK(!callback.is_null());
}
DeleteResourceRequest::~DeleteResourceRequest() {}
GURL DeleteResourceRequest::GetURL() const {
return url_generator_.GetChildrenUrlForRemoval(
parent_resource_id_, resource_id_);
}
net::URLFetcher::RequestType DeleteResourceRequest::GetRequestType() const {
return net::URLFetcher::DELETE_REQUEST;
}
//======================= InitiateUploadNewFileRequest =======================
InitiateUploadNewFileRequest::InitiateUploadNewFileRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const std::string& content_type,
int64 content_length,
const std::string& parent_resource_id,
const std::string& title,
const InitiateUploadCallback& callback)
: InitiateUploadRequestBase(sender,
callback,
content_type,
content_length),
url_generator_(url_generator),
parent_resource_id_(parent_resource_id),
title_(title) {
}
InitiateUploadNewFileRequest::~InitiateUploadNewFileRequest() {}
GURL InitiateUploadNewFileRequest::GetURL() const {
return url_generator_.GetInitiateUploadNewFileUrl();
}
net::URLFetcher::RequestType
InitiateUploadNewFileRequest::GetRequestType() const {
return net::URLFetcher::POST;
}
bool InitiateUploadNewFileRequest::GetContentData(
std::string* upload_content_type,
std::string* upload_content) {
*upload_content_type = kContentTypeApplicationJson;
base::DictionaryValue root;
root.SetString("title", title_);
// Fill parent link.
{
scoped_ptr<base::DictionaryValue> parent(new base::DictionaryValue);
parent->SetString("kind", kParentLinkKind);
parent->SetString("id", parent_resource_id_);
scoped_ptr<base::ListValue> parents(new base::ListValue);
parents->Append(parent.release());
root.Set("parents", parents.release());
}
base::JSONWriter::Write(&root, upload_content);
DVLOG(1) << "InitiateUploadNewFile data: " << *upload_content_type << ", ["
<< *upload_content << "]";
return true;
}
//===================== InitiateUploadExistingFileRequest ====================
InitiateUploadExistingFileRequest::InitiateUploadExistingFileRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const std::string& content_type,
int64 content_length,
const std::string& resource_id,
const std::string& etag,
const InitiateUploadCallback& callback)
: InitiateUploadRequestBase(sender,
callback,
content_type,
content_length),
url_generator_(url_generator),
resource_id_(resource_id),
etag_(etag) {
}
InitiateUploadExistingFileRequest::~InitiateUploadExistingFileRequest() {}
GURL InitiateUploadExistingFileRequest::GetURL() const {
return url_generator_.GetInitiateUploadExistingFileUrl(resource_id_);
}
net::URLFetcher::RequestType
InitiateUploadExistingFileRequest::GetRequestType() const {
return net::URLFetcher::PUT;
}
std::vector<std::string>
InitiateUploadExistingFileRequest::GetExtraRequestHeaders() const {
std::vector<std::string> headers(
InitiateUploadRequestBase::GetExtraRequestHeaders());
headers.push_back(util::GenerateIfMatchHeader(etag_));
return headers;
}
//============================ ResumeUploadRequest ===========================
ResumeUploadRequest::ResumeUploadRequest(
RequestSender* sender,
const GURL& upload_location,
int64 start_position,
int64 end_position,
int64 content_length,
const std::string& content_type,
const base::FilePath& local_file_path,
const UploadRangeCallback& callback,
const ProgressCallback& progress_callback)
: ResumeUploadRequestBase(sender,
upload_location,
start_position,
end_position,
content_length,
content_type,
local_file_path),
callback_(callback),
progress_callback_(progress_callback) {
DCHECK(!callback_.is_null());
}
ResumeUploadRequest::~ResumeUploadRequest() {}
void ResumeUploadRequest::OnRangeRequestComplete(
const UploadRangeResponse& response,
scoped_ptr<base::Value> value) {
DCHECK(CalledOnValidThread());
ParseFileResourceWithUploadRangeAndRun(callback_, response, value.Pass());
}
void ResumeUploadRequest::OnURLFetchUploadProgress(
const net::URLFetcher* source, int64 current, int64 total) {
if (!progress_callback_.is_null())
progress_callback_.Run(current, total);
}
//========================== GetUploadStatusRequest ==========================
GetUploadStatusRequest::GetUploadStatusRequest(
RequestSender* sender,
const GURL& upload_url,
int64 content_length,
const UploadRangeCallback& callback)
: GetUploadStatusRequestBase(sender,
upload_url,
content_length),
callback_(callback) {
DCHECK(!callback.is_null());
}
GetUploadStatusRequest::~GetUploadStatusRequest() {}
void GetUploadStatusRequest::OnRangeRequestComplete(
const UploadRangeResponse& response,
scoped_ptr<base::Value> value) {
DCHECK(CalledOnValidThread());
ParseFileResourceWithUploadRangeAndRun(callback_, response, value.Pass());
}
//========================== DownloadFileRequest ==========================
DownloadFileRequest::DownloadFileRequest(
RequestSender* sender,
const DriveApiUrlGenerator& url_generator,
const std::string& resource_id,
const base::FilePath& output_file_path,
const DownloadActionCallback& download_action_callback,
const GetContentCallback& get_content_callback,
const ProgressCallback& progress_callback)
: DownloadFileRequestBase(
sender,
download_action_callback,
get_content_callback,
progress_callback,
url_generator.GenerateDownloadFileUrl(resource_id),
output_file_path) {
}
DownloadFileRequest::~DownloadFileRequest() {
}
} // namespace drive
} // namespace google_apis