drive: Add metadata parameters to InitiateUpload* methods

It is allowed to send metadata and file contents at the same time with Drive API.

BUG=260539
TEST=unit_tests

Review URL: https://codereview.chromium.org/139153006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245466 0039d316-1c4b-4281-b951-d872f2087c98
parent 9bd35ea5
...@@ -113,6 +113,15 @@ void ParseFileResourceWithUploadRangeAndRun( ...@@ -113,6 +113,15 @@ void ParseFileResourceWithUploadRangeAndRun(
callback.Run(response, file_resource.Pass()); callback.Run(response, file_resource.Pass());
} }
// Creates a Parents value which can be used as a part of request body.
scoped_ptr<base::DictionaryValue> CreateParentValue(
const std::string& file_id) {
scoped_ptr<base::DictionaryValue> parent(new base::DictionaryValue);
parent->SetString("kind", kParentLinkKind);
parent->SetString("id", file_id);
return parent.Pass();
}
} // namespace } // namespace
namespace drive { namespace drive {
...@@ -602,7 +611,7 @@ InitiateUploadNewFileRequest::InitiateUploadNewFileRequest( ...@@ -602,7 +611,7 @@ InitiateUploadNewFileRequest::InitiateUploadNewFileRequest(
InitiateUploadNewFileRequest::~InitiateUploadNewFileRequest() {} InitiateUploadNewFileRequest::~InitiateUploadNewFileRequest() {}
GURL InitiateUploadNewFileRequest::GetURL() const { GURL InitiateUploadNewFileRequest::GetURL() const {
return url_generator_.GetInitiateUploadNewFileUrl(); return url_generator_.GetInitiateUploadNewFileUrl(!modified_date_.is_null());
} }
net::URLFetcher::RequestType net::URLFetcher::RequestType
...@@ -619,15 +628,16 @@ bool InitiateUploadNewFileRequest::GetContentData( ...@@ -619,15 +628,16 @@ bool InitiateUploadNewFileRequest::GetContentData(
root.SetString("title", title_); root.SetString("title", title_);
// Fill parent link. // Fill parent link.
{ scoped_ptr<base::ListValue> parents(new base::ListValue);
scoped_ptr<base::DictionaryValue> parent(new base::DictionaryValue); parents->Append(CreateParentValue(parent_resource_id_).release());
parent->SetString("kind", kParentLinkKind); root.Set("parents", parents.release());
parent->SetString("id", parent_resource_id_);
scoped_ptr<base::ListValue> parents(new base::ListValue); if (!modified_date_.is_null())
parents->Append(parent.release()); root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));
root.Set("parents", parents.release()); if (!last_viewed_by_me_date_.is_null()) {
root.SetString("lastViewedByMeDate",
util::FormatTimeAsString(last_viewed_by_me_date_));
} }
base::JSONWriter::Write(&root, upload_content); base::JSONWriter::Write(&root, upload_content);
...@@ -659,7 +669,8 @@ InitiateUploadExistingFileRequest::InitiateUploadExistingFileRequest( ...@@ -659,7 +669,8 @@ InitiateUploadExistingFileRequest::InitiateUploadExistingFileRequest(
InitiateUploadExistingFileRequest::~InitiateUploadExistingFileRequest() {} InitiateUploadExistingFileRequest::~InitiateUploadExistingFileRequest() {}
GURL InitiateUploadExistingFileRequest::GetURL() const { GURL InitiateUploadExistingFileRequest::GetURL() const {
return url_generator_.GetInitiateUploadExistingFileUrl(resource_id_); return url_generator_.GetInitiateUploadExistingFileUrl(
resource_id_, !modified_date_.is_null());
} }
net::URLFetcher::RequestType net::URLFetcher::RequestType
...@@ -675,6 +686,37 @@ InitiateUploadExistingFileRequest::GetExtraRequestHeaders() const { ...@@ -675,6 +686,37 @@ InitiateUploadExistingFileRequest::GetExtraRequestHeaders() const {
return headers; return headers;
} }
bool InitiateUploadExistingFileRequest::GetContentData(
std::string* upload_content_type,
std::string* upload_content) {
base::DictionaryValue root;
if (!parent_resource_id_.empty()) {
scoped_ptr<base::ListValue> parents(new base::ListValue);
parents->Append(CreateParentValue(parent_resource_id_).release());
root.Set("parents", parents.release());
}
if (!title_.empty())
root.SetString("title", title_);
if (!modified_date_.is_null())
root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));
if (!last_viewed_by_me_date_.is_null()) {
root.SetString("lastViewedByMeDate",
util::FormatTimeAsString(last_viewed_by_me_date_));
}
if (root.empty())
return false;
*upload_content_type = kContentTypeApplicationJson;
base::JSONWriter::Write(&root, upload_content);
DVLOG(1) << "InitiateUploadExistingFile data: " << *upload_content_type
<< ", [" << *upload_content << "]";
return true;
}
//============================ ResumeUploadRequest =========================== //============================ ResumeUploadRequest ===========================
ResumeUploadRequest::ResumeUploadRequest( ResumeUploadRequest::ResumeUploadRequest(
......
...@@ -624,6 +624,18 @@ class InitiateUploadNewFileRequest : public InitiateUploadRequestBase { ...@@ -624,6 +624,18 @@ class InitiateUploadNewFileRequest : public InitiateUploadRequestBase {
const InitiateUploadCallback& callback); const InitiateUploadCallback& callback);
virtual ~InitiateUploadNewFileRequest(); virtual ~InitiateUploadNewFileRequest();
// Optional parameters.
const base::Time& modified_date() const { return modified_date_; }
void set_modified_date(const base::Time& modified_date) {
modified_date_ = modified_date;
}
const base::Time& last_viewed_by_me_date() const {
return last_viewed_by_me_date_;
}
void set_last_viewed_by_me_date(const base::Time& last_viewed_by_me_date) {
last_viewed_by_me_date_ = last_viewed_by_me_date;
}
protected: protected:
// UrlFetchRequestBase overrides. // UrlFetchRequestBase overrides.
virtual GURL GetURL() const OVERRIDE; virtual GURL GetURL() const OVERRIDE;
...@@ -636,6 +648,9 @@ class InitiateUploadNewFileRequest : public InitiateUploadRequestBase { ...@@ -636,6 +648,9 @@ class InitiateUploadNewFileRequest : public InitiateUploadRequestBase {
const std::string parent_resource_id_; const std::string parent_resource_id_;
const std::string title_; const std::string title_;
base::Time modified_date_;
base::Time last_viewed_by_me_date_;
DISALLOW_COPY_AND_ASSIGN(InitiateUploadNewFileRequest); DISALLOW_COPY_AND_ASSIGN(InitiateUploadNewFileRequest);
}; };
...@@ -659,17 +674,43 @@ class InitiateUploadExistingFileRequest : public InitiateUploadRequestBase { ...@@ -659,17 +674,43 @@ class InitiateUploadExistingFileRequest : public InitiateUploadRequestBase {
const InitiateUploadCallback& callback); const InitiateUploadCallback& callback);
virtual ~InitiateUploadExistingFileRequest(); virtual ~InitiateUploadExistingFileRequest();
// Optional parameters.
const std::string& parent_resource_id() const { return parent_resource_id_; }
void set_parent_resource_id(const std::string& parent_resource_id) {
parent_resource_id_ = parent_resource_id;
}
const std::string& title() const { return title_; }
void set_title(const std::string& title) { title_ = title; }
const base::Time& modified_date() const { return modified_date_; }
void set_modified_date(const base::Time& modified_date) {
modified_date_ = modified_date;
}
const base::Time& last_viewed_by_me_date() const {
return last_viewed_by_me_date_;
}
void set_last_viewed_by_me_date(const base::Time& last_viewed_by_me_date) {
last_viewed_by_me_date_ = last_viewed_by_me_date;
}
protected: protected:
// UrlFetchRequestBase overrides. // UrlFetchRequestBase overrides.
virtual GURL GetURL() const OVERRIDE; virtual GURL GetURL() const OVERRIDE;
virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE; virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE;
virtual std::vector<std::string> GetExtraRequestHeaders() const OVERRIDE; virtual std::vector<std::string> GetExtraRequestHeaders() const OVERRIDE;
virtual bool GetContentData(std::string* upload_content_type,
std::string* upload_content) OVERRIDE;
private: private:
const DriveApiUrlGenerator url_generator_; const DriveApiUrlGenerator url_generator_;
const std::string resource_id_; const std::string resource_id_;
const std::string etag_; const std::string etag_;
std::string parent_resource_id_;
std::string title_;
base::Time modified_date_;
base::Time last_viewed_by_me_date_;
DISALLOW_COPY_AND_ASSIGN(InitiateUploadExistingFileRequest); DISALLOW_COPY_AND_ASSIGN(InitiateUploadExistingFileRequest);
}; };
......
...@@ -1257,6 +1257,60 @@ TEST_F(DriveApiRequestsTest, UploadNewLargeFileRequest) { ...@@ -1257,6 +1257,60 @@ TEST_F(DriveApiRequestsTest, UploadNewLargeFileRequest) {
} }
} }
TEST_F(DriveApiRequestsTest, UploadNewFileWithMetadataRequest) {
const base::Time::Exploded kModifiedDate = {2012, 7, 0, 19, 15, 59, 13, 123};
const base::Time::Exploded kLastViewedByMeDate =
{2013, 7, 0, 19, 15, 59, 13, 123};
// Set an expected url for uploading.
expected_upload_path_ = kTestUploadNewFilePath;
const char kTestContentType[] = "text/plain";
const std::string kTestContent(100, 'a');
GDataErrorCode error = GDATA_OTHER_ERROR;
GURL upload_url;
// Initiate uploading a new file to the directory with "parent_resource_id".
{
base::RunLoop run_loop;
drive::InitiateUploadNewFileRequest* request =
new drive::InitiateUploadNewFileRequest(
request_sender_.get(),
*url_generator_,
kTestContentType,
kTestContent.size(),
"parent_resource_id", // The resource id of the parent directory.
"new file title", // The title of the file being uploaded.
test_util::CreateQuitCallback(
&run_loop,
test_util::CreateCopyResultCallback(&error, &upload_url)));
request->set_modified_date(base::Time::FromUTCExploded(kModifiedDate));
request->set_last_viewed_by_me_date(
base::Time::FromUTCExploded(kLastViewedByMeDate));
request_sender_->StartRequestWithRetry(request);
run_loop.Run();
}
EXPECT_EQ(HTTP_SUCCESS, error);
EXPECT_EQ(kTestUploadNewFilePath, upload_url.path());
EXPECT_EQ(kTestContentType, http_request_.headers["X-Upload-Content-Type"]);
EXPECT_EQ(base::Int64ToString(kTestContent.size()),
http_request_.headers["X-Upload-Content-Length"]);
EXPECT_EQ(net::test_server::METHOD_POST, http_request_.method);
EXPECT_EQ("/upload/drive/v2/files?uploadType=resumable&setModifiedDate=true",
http_request_.relative_url);
EXPECT_EQ("application/json", http_request_.headers["Content-Type"]);
EXPECT_TRUE(http_request_.has_content);
EXPECT_EQ("{\"lastViewedByMeDate\":\"2013-07-19T15:59:13.123Z\","
"\"modifiedDate\":\"2012-07-19T15:59:13.123Z\","
"\"parents\":[{\"id\":\"parent_resource_id\","
"\"kind\":\"drive#fileLink\"}],"
"\"title\":\"new file title\"}",
http_request_.content);
}
TEST_F(DriveApiRequestsTest, UploadExistingFileRequest) { TEST_F(DriveApiRequestsTest, UploadExistingFileRequest) {
// Set an expected url for uploading. // Set an expected url for uploading.
expected_upload_path_ = kTestUploadExistingFilePath; expected_upload_path_ = kTestUploadExistingFilePath;
...@@ -1573,6 +1627,65 @@ TEST_F(DriveApiRequestsTest, ...@@ -1573,6 +1627,65 @@ TEST_F(DriveApiRequestsTest,
EXPECT_FALSE(new_entry.get()); EXPECT_FALSE(new_entry.get());
} }
TEST_F(DriveApiRequestsTest, UploadExistingFileWithMetadataRequest) {
const base::Time::Exploded kModifiedDate = {2012, 7, 0, 19, 15, 59, 13, 123};
const base::Time::Exploded kLastViewedByMeDate =
{2013, 7, 0, 19, 15, 59, 13, 123};
// Set an expected url for uploading.
expected_upload_path_ = kTestUploadExistingFilePath;
const char kTestContentType[] = "text/plain";
const std::string kTestContent(100, 'a');
GDataErrorCode error = GDATA_OTHER_ERROR;
GURL upload_url;
// Initiate uploading a new file to the directory with "parent_resource_id".
{
base::RunLoop run_loop;
drive::InitiateUploadExistingFileRequest* request =
new drive::InitiateUploadExistingFileRequest(
request_sender_.get(),
*url_generator_,
kTestContentType,
kTestContent.size(),
"resource_id", // The resource id of the file to be overwritten.
kTestETag,
test_util::CreateQuitCallback(
&run_loop,
test_util::CreateCopyResultCallback(&error, &upload_url)));
request->set_parent_resource_id("new_parent_resource_id");
request->set_title("new file title");
request->set_modified_date(base::Time::FromUTCExploded(kModifiedDate));
request->set_last_viewed_by_me_date(
base::Time::FromUTCExploded(kLastViewedByMeDate));
request_sender_->StartRequestWithRetry(request);
run_loop.Run();
}
EXPECT_EQ(HTTP_SUCCESS, error);
EXPECT_EQ(kTestUploadExistingFilePath, upload_url.path());
EXPECT_EQ(kTestContentType, http_request_.headers["X-Upload-Content-Type"]);
EXPECT_EQ(base::Int64ToString(kTestContent.size()),
http_request_.headers["X-Upload-Content-Length"]);
EXPECT_EQ(kTestETag, http_request_.headers["If-Match"]);
EXPECT_EQ(net::test_server::METHOD_PUT, http_request_.method);
EXPECT_EQ("/upload/drive/v2/files/resource_id?"
"uploadType=resumable&setModifiedDate=true",
http_request_.relative_url);
EXPECT_EQ("application/json", http_request_.headers["Content-Type"]);
EXPECT_TRUE(http_request_.has_content);
EXPECT_EQ("{\"lastViewedByMeDate\":\"2013-07-19T15:59:13.123Z\","
"\"modifiedDate\":\"2012-07-19T15:59:13.123Z\","
"\"parents\":[{\"id\":\"new_parent_resource_id\","
"\"kind\":\"drive#fileLink\"}],"
"\"title\":\"new file title\"}",
http_request_.content);
}
TEST_F(DriveApiRequestsTest, DownloadFileRequest) { TEST_F(DriveApiRequestsTest, DownloadFileRequest) {
const base::FilePath kDownloadedFilePath = const base::FilePath kDownloadedFilePath =
temp_dir_.path().AppendASCII("cache_file"); temp_dir_.path().AppendASCII("cache_file");
......
...@@ -170,17 +170,31 @@ GURL DriveApiUrlGenerator::GetChildrenDeleteUrl( ...@@ -170,17 +170,31 @@ GURL DriveApiUrlGenerator::GetChildrenDeleteUrl(
net::EscapePath(child_id).c_str())); net::EscapePath(child_id).c_str()));
} }
GURL DriveApiUrlGenerator::GetInitiateUploadNewFileUrl() const { GURL DriveApiUrlGenerator::GetInitiateUploadNewFileUrl(
return AddResumableUploadParam( bool set_modified_date) const {
GURL url = AddResumableUploadParam(
base_url_.Resolve(kDriveV2InitiateUploadNewFileUrl)); base_url_.Resolve(kDriveV2InitiateUploadNewFileUrl));
// setModifiedDate is "false" by default.
if (set_modified_date)
url = net::AppendOrReplaceQueryParameter(url, "setModifiedDate", "true");
return url;
} }
GURL DriveApiUrlGenerator::GetInitiateUploadExistingFileUrl( GURL DriveApiUrlGenerator::GetInitiateUploadExistingFileUrl(
const std::string& resource_id) const { const std::string& resource_id,
const GURL& url = base_url_.Resolve( bool set_modified_date) const {
GURL url = base_url_.Resolve(
kDriveV2InitiateUploadExistingFileUrlPrefix + kDriveV2InitiateUploadExistingFileUrlPrefix +
net::EscapePath(resource_id)); net::EscapePath(resource_id));
return AddResumableUploadParam(url); url = AddResumableUploadParam(url);
// setModifiedDate is "false" by default.
if (set_modified_date)
url = net::AppendOrReplaceQueryParameter(url, "setModifiedDate", "true");
return url;
} }
GURL DriveApiUrlGenerator::GenerateDownloadFileUrl( GURL DriveApiUrlGenerator::GenerateDownloadFileUrl(
......
...@@ -75,11 +75,12 @@ class DriveApiUrlGenerator { ...@@ -75,11 +75,12 @@ class DriveApiUrlGenerator {
const std::string& folder_id) const; const std::string& folder_id) const;
// Returns a URL to initiate uploading a new file. // Returns a URL to initiate uploading a new file.
GURL GetInitiateUploadNewFileUrl() const; GURL GetInitiateUploadNewFileUrl(bool set_modified_date) const;
// Returns a URL to initiate uploading an existing file specified by // Returns a URL to initiate uploading an existing file specified by
// |resource_id|. // |resource_id|.
GURL GetInitiateUploadExistingFileUrl(const std::string& resource_id) const; GURL GetInitiateUploadExistingFileUrl(const std::string& resource_id,
bool set_modified_date) const;
// Generates a URL for downloading a file. // Generates a URL for downloading a file.
GURL GenerateDownloadFileUrl(const std::string& resource_id) const; GURL GenerateDownloadFileUrl(const std::string& resource_id) const;
......
...@@ -345,45 +345,69 @@ TEST_F(DriveApiUrlGeneratorTest, GetChildrenDeleteUrl) { ...@@ -345,45 +345,69 @@ TEST_F(DriveApiUrlGeneratorTest, GetChildrenDeleteUrl) {
} }
TEST_F(DriveApiUrlGeneratorTest, GetInitiateUploadNewFileUrl) { TEST_F(DriveApiUrlGeneratorTest, GetInitiateUploadNewFileUrl) {
const bool kSetModifiedDate = true;
EXPECT_EQ( EXPECT_EQ(
"https://www.googleapis.com/upload/drive/v2/files?uploadType=resumable", "https://www.googleapis.com/upload/drive/v2/files?uploadType=resumable",
url_generator_.GetInitiateUploadNewFileUrl().spec()); url_generator_.GetInitiateUploadNewFileUrl(!kSetModifiedDate).spec());
EXPECT_EQ( EXPECT_EQ(
"http://127.0.0.1:12345/upload/drive/v2/files?uploadType=resumable", "http://127.0.0.1:12345/upload/drive/v2/files?uploadType=resumable",
test_url_generator_.GetInitiateUploadNewFileUrl().spec()); test_url_generator_.GetInitiateUploadNewFileUrl(
!kSetModifiedDate).spec());
EXPECT_EQ(
"http://127.0.0.1:12345/upload/drive/v2/files?uploadType=resumable&"
"setModifiedDate=true",
test_url_generator_.GetInitiateUploadNewFileUrl(
kSetModifiedDate).spec());
} }
TEST_F(DriveApiUrlGeneratorTest, GetInitiateUploadExistingFileUrl) { TEST_F(DriveApiUrlGeneratorTest, GetInitiateUploadExistingFileUrl) {
const bool kSetModifiedDate = true;
// |resource_id| should be embedded into the url. // |resource_id| should be embedded into the url.
EXPECT_EQ( EXPECT_EQ(
"https://www.googleapis.com/upload/drive/v2/files/0ADK06pfg" "https://www.googleapis.com/upload/drive/v2/files/0ADK06pfg"
"?uploadType=resumable", "?uploadType=resumable",
url_generator_.GetInitiateUploadExistingFileUrl("0ADK06pfg").spec()); url_generator_.GetInitiateUploadExistingFileUrl(
"0ADK06pfg", !kSetModifiedDate).spec());
EXPECT_EQ( EXPECT_EQ(
"https://www.googleapis.com/upload/drive/v2/files/0Bz0bd074" "https://www.googleapis.com/upload/drive/v2/files/0Bz0bd074"
"?uploadType=resumable", "?uploadType=resumable",
url_generator_.GetInitiateUploadExistingFileUrl("0Bz0bd074").spec()); url_generator_.GetInitiateUploadExistingFileUrl(
"0Bz0bd074", !kSetModifiedDate).spec());
EXPECT_EQ( EXPECT_EQ(
"https://www.googleapis.com/upload/drive/v2/files/file%3Afile_id" "https://www.googleapis.com/upload/drive/v2/files/file%3Afile_id"
"?uploadType=resumable", "?uploadType=resumable",
url_generator_.GetInitiateUploadExistingFileUrl("file:file_id").spec()); url_generator_.GetInitiateUploadExistingFileUrl(
"file:file_id", !kSetModifiedDate).spec());
EXPECT_EQ(
"https://www.googleapis.com/upload/drive/v2/files/file%3Afile_id"
"?uploadType=resumable&setModifiedDate=true",
url_generator_.GetInitiateUploadExistingFileUrl(
"file:file_id", kSetModifiedDate).spec());
EXPECT_EQ( EXPECT_EQ(
"http://127.0.0.1:12345/upload/drive/v2/files/0ADK06pfg" "http://127.0.0.1:12345/upload/drive/v2/files/0ADK06pfg"
"?uploadType=resumable", "?uploadType=resumable",
test_url_generator_.GetInitiateUploadExistingFileUrl( test_url_generator_.GetInitiateUploadExistingFileUrl(
"0ADK06pfg").spec()); "0ADK06pfg", !kSetModifiedDate).spec());
EXPECT_EQ( EXPECT_EQ(
"http://127.0.0.1:12345/upload/drive/v2/files/0Bz0bd074" "http://127.0.0.1:12345/upload/drive/v2/files/0Bz0bd074"
"?uploadType=resumable", "?uploadType=resumable",
test_url_generator_.GetInitiateUploadExistingFileUrl( test_url_generator_.GetInitiateUploadExistingFileUrl(
"0Bz0bd074").spec()); "0Bz0bd074", !kSetModifiedDate).spec());
EXPECT_EQ( EXPECT_EQ(
"http://127.0.0.1:12345/upload/drive/v2/files/file%3Afile_id" "http://127.0.0.1:12345/upload/drive/v2/files/file%3Afile_id"
"?uploadType=resumable", "?uploadType=resumable",
test_url_generator_.GetInitiateUploadExistingFileUrl( test_url_generator_.GetInitiateUploadExistingFileUrl(
"file:file_id").spec()); "file:file_id", !kSetModifiedDate).spec());
EXPECT_EQ(
"http://127.0.0.1:12345/upload/drive/v2/files/file%3Afile_id"
"?uploadType=resumable&setModifiedDate=true",
test_url_generator_.GetInitiateUploadExistingFileUrl(
"file:file_id", kSetModifiedDate).spec());
} }
TEST_F(DriveApiUrlGeneratorTest, GenerateDownloadFileUrl) { TEST_F(DriveApiUrlGeneratorTest, GenerateDownloadFileUrl) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment