diff options
author | hidehiko@chromium.org <hidehiko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-01 03:56:24 +0000 |
---|---|---|
committer | hidehiko@chromium.org <hidehiko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-01 03:56:24 +0000 |
commit | bcc2c6dcda4c70cf546cec0b25228fa571b4924c (patch) | |
tree | 782d4a7d55a30afd437ac34f704363782e8ef15a /chrome/browser/google_apis | |
parent | cc7dec210cd2a325e65eaab44e4569846de72862 (diff) | |
download | chromium_src-bcc2c6dcda4c70cf546cec0b25228fa571b4924c.zip chromium_src-bcc2c6dcda4c70cf546cec0b25228fa571b4924c.tar.gz chromium_src-bcc2c6dcda4c70cf546cec0b25228fa571b4924c.tar.bz2 |
Implement InitiateUploadNewFile on Drive API v2.
This is a part of implementing an upload function on Drive API v2.
BUG=148632
TEST=Ran unit_tests
Review URL: https://chromiumcodereview.appspot.com/12315101
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@185452 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/google_apis')
-rw-r--r-- | chrome/browser/google_apis/drive_api_operations.cc | 62 | ||||
-rw-r--r-- | chrome/browser/google_apis/drive_api_operations.h | 36 | ||||
-rw-r--r-- | chrome/browser/google_apis/drive_api_operations_unittest.cc | 104 | ||||
-rw-r--r-- | chrome/browser/google_apis/drive_api_service.cc | 13 | ||||
-rw-r--r-- | chrome/browser/google_apis/gdata_wapi_operations_unittest.cc | 23 | ||||
-rw-r--r-- | chrome/browser/google_apis/test_util.cc | 9 | ||||
-rw-r--r-- | chrome/browser/google_apis/test_util.h | 7 |
7 files changed, 227 insertions, 27 deletions
diff --git a/chrome/browser/google_apis/drive_api_operations.cc b/chrome/browser/google_apis/drive_api_operations.cc index f9c75db..2d6a7ee 100644 --- a/chrome/browser/google_apis/drive_api_operations.cc +++ b/chrome/browser/google_apis/drive_api_operations.cc @@ -18,6 +18,7 @@ namespace { const char kContentTypeApplicationJson[] = "application/json"; const char kDirectoryMimeType[] = "application/vnd.google-apps.folder"; +const char kParentLinkKind[] = "drive#fileLink"; // Parses the JSON value to AboutResource and runs |callback| on the UI // thread once parsing is done. @@ -333,5 +334,66 @@ net::URLFetcher::RequestType DeleteResourceOperation::GetRequestType() const { return net::URLFetcher::DELETE_REQUEST; } +//======================= InitiateUploadNewFileOperation ======================= + +InitiateUploadNewFileOperation::InitiateUploadNewFileOperation( + OperationRegistry* registry, + net::URLRequestContextGetter* url_request_context_getter, + const DriveApiUrlGenerator& url_generator, + const base::FilePath& drive_file_path, + const std::string& content_type, + int64 content_length, + const std::string& parent_resource_id, + const std::string& title, + const InitiateUploadCallback& callback) + : InitiateUploadOperationBase(registry, + url_request_context_getter, + callback, + drive_file_path, + content_type, + content_length), + url_generator_(url_generator), + parent_resource_id_(parent_resource_id), + title_(title) { +} + +InitiateUploadNewFileOperation::~InitiateUploadNewFileOperation() {} + +GURL InitiateUploadNewFileOperation::GetURL() const { + return url_generator_.GetInitiateUploadNewFileUrl(); +} + +net::URLFetcher::RequestType +InitiateUploadNewFileOperation::GetRequestType() const { + return net::URLFetcher::POST; +} + +bool InitiateUploadNewFileOperation::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; +} + } // namespace drive } // namespace google_apis diff --git a/chrome/browser/google_apis/drive_api_operations.h b/chrome/browser/google_apis/drive_api_operations.h index 527fca6..36a0026 100644 --- a/chrome/browser/google_apis/drive_api_operations.h +++ b/chrome/browser/google_apis/drive_api_operations.h @@ -308,6 +308,42 @@ class DeleteResourceOperation : public EntryActionOperation { DISALLOW_COPY_AND_ASSIGN(DeleteResourceOperation); }; +//======================= InitiateUploadNewFileOperation ======================= + +// This class performs the operation for initiating the upload of a new file. +class InitiateUploadNewFileOperation : public InitiateUploadOperationBase { + public: + // |parent_resource_id| should be the resource id of the parent directory. + // |title| should be set. + // See also the comments of InitiateUploadOperationBase for more details + // about the other parameters. + InitiateUploadNewFileOperation( + OperationRegistry* registry, + net::URLRequestContextGetter* url_request_context_getter, + const DriveApiUrlGenerator& url_generator, + const base::FilePath& drive_file_path, + const std::string& content_type, + int64 content_length, + const std::string& parent_resource_id, + const std::string& title, + const InitiateUploadCallback& callback); + virtual ~InitiateUploadNewFileOperation(); + + protected: + // UrlFetchOperationBase overrides. + virtual GURL GetURL() const OVERRIDE; + virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE; + virtual bool GetContentData(std::string* upload_content_type, + std::string* upload_content) OVERRIDE; + + private: + const DriveApiUrlGenerator url_generator_; + const std::string parent_resource_id_; + const std::string title_; + + DISALLOW_COPY_AND_ASSIGN(InitiateUploadNewFileOperation); +}; + } // namespace drive } // namespace google_apis diff --git a/chrome/browser/google_apis/drive_api_operations_unittest.cc b/chrome/browser/google_apis/drive_api_operations_unittest.cc index 1c644bb..961f12c 100644 --- a/chrome/browser/google_apis/drive_api_operations_unittest.cc +++ b/chrome/browser/google_apis/drive_api_operations_unittest.cc @@ -5,6 +5,7 @@ #include "base/bind.h" #include "base/files/file_path.h" #include "base/message_loop_proxy.h" +#include "base/strings/string_number_conversions.h" #include "base/values.h" #include "chrome/browser/google_apis/drive_api_operations.h" #include "chrome/browser/google_apis/drive_api_parser.h" @@ -33,6 +34,8 @@ const char kTestChildrenResponse[] = "\"childLink\": \"child_link\",\n" "}\n"; +const char kTestUploadUrl[] = "https://server/upload/path"; + void CopyResultsFromGetAboutResourceCallbackAndQuit( GDataErrorCode* error_out, scoped_ptr<AboutResource>* about_resource_out, @@ -69,6 +72,9 @@ class DriveApiOperationsTest : public testing::Test { base::Bind(&DriveApiOperationsTest::HandleDataFileRequest, base::Unretained(this))); test_server_.RegisterRequestHandler( + base::Bind(&DriveApiOperationsTest::HandleInitiateUploadRequest, + base::Unretained(this))); + test_server_.RegisterRequestHandler( base::Bind(&DriveApiOperationsTest::HandleContentResponse, base::Unretained(this))); @@ -76,13 +82,13 @@ class DriveApiOperationsTest : public testing::Test { test_util::GetBaseUrlForTesting(test_server_.port()))); // Reset the server's expected behavior just in case. - expected_data_file_path_.clear(); + ResetExpectedResponse(); } virtual void TearDown() OVERRIDE { test_server_.ShutdownAndWaitUntilComplete(); request_context_getter_ = NULL; - expected_data_file_path_.clear(); + ResetExpectedResponse(); } MessageLoopForUI message_loop_; @@ -98,6 +104,10 @@ class DriveApiOperationsTest : public testing::Test { // the server. See also HandleDataFileRequest below. base::FilePath expected_data_file_path_; + // This is a url string in the expected response header from the server + // for initiating file uploading. + std::string expected_upload_url_; + // These are content and its type in the expected response from the server. // See also HandleContentResponse below. std::string expected_content_type_; @@ -109,12 +119,17 @@ class DriveApiOperationsTest : public testing::Test { test_server::HttpRequest http_request_; private: + void ResetExpectedResponse() { + expected_data_file_path_.clear(); + expected_upload_url_.clear(); + expected_content_type_.clear(); + expected_content_.clear(); + } + // For "Children: delete" request, the server will return "204 No Content" // response meaning "success". scoped_ptr<test_server::HttpResponse> HandleChildrenDeleteRequest( const test_server::HttpRequest& request) { - http_request_ = request; - if (request.method != test_server::METHOD_DELETE || request.relative_url.find("/children/") == string::npos) { // The request is not the "Children: delete" operation. Delegate the @@ -122,6 +137,8 @@ class DriveApiOperationsTest : public testing::Test { return scoped_ptr<test_server::HttpResponse>(); } + http_request_ = request; + // Return the response with just "204 No Content" status code. scoped_ptr<test_server::HttpResponse> http_response( new test_server::HttpResponse); @@ -135,31 +152,53 @@ class DriveApiOperationsTest : public testing::Test { // to the appropriate file path before sending the request to the server. scoped_ptr<test_server::HttpResponse> HandleDataFileRequest( const test_server::HttpRequest& request) { - http_request_ = request; - if (expected_data_file_path_.empty()) { // The file is not specified. Delegate the processing to the next // handler. return scoped_ptr<test_server::HttpResponse>(); } + http_request_ = request; + // Return the response from the data file. return test_util::CreateHttpResponseFromFile(expected_data_file_path_); } + // Returns the response based on set expected upload url. + // The response contains the url in its "Location: " header. Also, it doesn't + // have any content. + // To use this method, it is necessary to set |expected_upload_url_| + // to the string representation of the url to be returned. + scoped_ptr<test_server::HttpResponse> HandleInitiateUploadRequest( + const test_server::HttpRequest& request) { + if (expected_upload_url_.empty()) { + // Expected upload url is not set. Delegate the processing to the next + // handler. + return scoped_ptr<test_server::HttpResponse>(); + } + + http_request_ = request; + + scoped_ptr<test_server::HttpResponse> response( + new test_server::HttpResponse); + response->set_code(test_server::SUCCESS); + response->AddCustomHeader("Location", expected_upload_url_); + return response.Pass(); + } + // Returns the response based on set expected content and its type. // To use this method, both |expected_content_type_| and |expected_content_| // must be set in advance. scoped_ptr<test_server::HttpResponse> HandleContentResponse( const test_server::HttpRequest& request) { - http_request_ = request; - if (expected_content_type_.empty() || expected_content_.empty()) { // Expected content is not set. Delegate the processing to the next // handler. return scoped_ptr<test_server::HttpResponse>(); } + http_request_ = request; + scoped_ptr<test_server::HttpResponse> response( new test_server::HttpResponse); response->set_code(test_server::SUCCESS); @@ -374,4 +413,53 @@ TEST_F(DriveApiOperationsTest, DeleteResourceOperation) { EXPECT_FALSE(http_request_.has_content); } +TEST_F(DriveApiOperationsTest, InitiateUploadNewFileOperation) { + // Set an expected url for uploading. + expected_upload_url_ = kTestUploadUrl; + + const char kTestContentType[] = "text/plain"; + const int64 kTestContentLength = 100; + + GDataErrorCode error = GDATA_OTHER_ERROR; + GURL url; + + // Initiate uploading a new file to the directory with "parent_resource_id". + drive::InitiateUploadNewFileOperation* operation = + new drive::InitiateUploadNewFileOperation( + &operation_registry_, + request_context_getter_.get(), + *url_generator_, + base::FilePath(FILE_PATH_LITERAL("drive/file/path")), + kTestContentType, + kTestContentLength, + "parent_resource_id", // The resource id of the parent directory. + "new file title", // The title of the file being uploaded. + base::Bind(&test_util::CopyResultsFromInitiateUploadCallbackAndQuit, + &error, &url)); + operation->Start(kTestDriveApiAuthToken, kTestUserAgent, + base::Bind(&test_util::DoNothingForReAuthenticateCallback)); + MessageLoop::current()->Run(); + + EXPECT_EQ(HTTP_SUCCESS, error); + EXPECT_EQ(kTestUploadUrl, url.spec()); + EXPECT_EQ(kTestContentType, http_request_.headers["X-Upload-Content-Type"]); + EXPECT_EQ(base::Int64ToString(kTestContentLength), + http_request_.headers["X-Upload-Content-Length"]); + + EXPECT_EQ(test_server::METHOD_POST, http_request_.method); + EXPECT_EQ("/upload/drive/v2/files?uploadType=resumable", + http_request_.relative_url); + EXPECT_EQ("application/json", http_request_.headers["Content-Type"]); + EXPECT_TRUE(http_request_.has_content); + EXPECT_EQ("{\"parents\":[{" + "\"id\":\"parent_resource_id\"," + "\"kind\":\"drive#fileLink\"" + "}]," + "\"title\":\"new file title\"}", + http_request_.content); + + // Clean the operation remaining in |operation_registry_|. + operation_registry_.CancelAll(); +} + } // namespace google_apis diff --git a/chrome/browser/google_apis/drive_api_service.cc b/chrome/browser/google_apis/drive_api_service.cc index 546e3a1..3ec517f 100644 --- a/chrome/browser/google_apis/drive_api_service.cc +++ b/chrome/browser/google_apis/drive_api_service.cc @@ -467,8 +467,17 @@ void DriveAPIService::InitiateUploadNewFile( DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(!callback.is_null()); - // TODO(hidehiko): Implement this. - NOTREACHED(); + runner_->StartOperationWithRetry( + new drive::InitiateUploadNewFileOperation( + operation_registry(), + url_request_context_getter_, + url_generator_, + drive_file_path, + content_type, + content_length, + parent_resource_id, + title, + callback)); } void DriveAPIService::InitiateUploadExistingFile( diff --git a/chrome/browser/google_apis/gdata_wapi_operations_unittest.cc b/chrome/browser/google_apis/gdata_wapi_operations_unittest.cc index 42a8f8f..0925c68 100644 --- a/chrome/browser/google_apis/gdata_wapi_operations_unittest.cc +++ b/chrome/browser/google_apis/gdata_wapi_operations_unittest.cc @@ -35,17 +35,6 @@ const char kTestGDataAuthToken[] = "testtoken"; const char kTestUserAgent[] = "test-user-agent"; const char kTestETag[] = "test_etag"; -// Copies the result from InitiateUploadCallback and quit the message loop. -void CopyResultFromInitiateUploadCallbackAndQuit( - GDataErrorCode* out_result_code, - GURL* out_upload_url, - GDataErrorCode result_code, - const GURL& upload_url) { - *out_result_code = result_code; - *out_upload_url = upload_url; - MessageLoop::current()->Quit(); -} - // Copies the result from ResumeUploadCallback and quit the message loop. void CopyResultFromUploadRangeCallbackAndQuit( UploadRangeResponse* out_response, @@ -803,7 +792,7 @@ TEST_F(GDataWapiOperationsTest, UploadNewFile) { &operation_registry_, request_context_getter_.get(), *url_generator_, - base::Bind(&CopyResultFromInitiateUploadCallbackAndQuit, + base::Bind(&test_util::CopyResultsFromInitiateUploadCallbackAndQuit, &result_code, &upload_url), base::FilePath::FromUTF8Unsafe("drive/newfile.txt"), @@ -904,7 +893,7 @@ TEST_F(GDataWapiOperationsTest, UploadNewLargeFile) { &operation_registry_, request_context_getter_.get(), *url_generator_, - base::Bind(&CopyResultFromInitiateUploadCallbackAndQuit, + base::Bind(&test_util::CopyResultsFromInitiateUploadCallbackAndQuit, &result_code, &upload_url), base::FilePath::FromUTF8Unsafe("drive/newfile.txt"), @@ -1101,7 +1090,7 @@ TEST_F(GDataWapiOperationsTest, UploadNewEmptyFile) { &operation_registry_, request_context_getter_.get(), *url_generator_, - base::Bind(&CopyResultFromInitiateUploadCallbackAndQuit, + base::Bind(&test_util::CopyResultsFromInitiateUploadCallbackAndQuit, &result_code, &upload_url), base::FilePath::FromUTF8Unsafe("drive/newfile.txt"), @@ -1193,7 +1182,7 @@ TEST_F(GDataWapiOperationsTest, UploadExistingFile) { &operation_registry_, request_context_getter_.get(), *url_generator_, - base::Bind(&CopyResultFromInitiateUploadCallbackAndQuit, + base::Bind(&test_util::CopyResultsFromInitiateUploadCallbackAndQuit, &result_code, &upload_url), base::FilePath::FromUTF8Unsafe("drive/existingfile.txt"), @@ -1286,7 +1275,7 @@ TEST_F(GDataWapiOperationsTest, UploadExistingFileWithETag) { &operation_registry_, request_context_getter_.get(), *url_generator_, - base::Bind(&CopyResultFromInitiateUploadCallbackAndQuit, + base::Bind(&test_util::CopyResultsFromInitiateUploadCallbackAndQuit, &result_code, &upload_url), base::FilePath::FromUTF8Unsafe("drive/existingfile.txt"), @@ -1379,7 +1368,7 @@ TEST_F(GDataWapiOperationsTest, UploadExistingFileWithETagConflict) { &operation_registry_, request_context_getter_.get(), *url_generator_, - base::Bind(&CopyResultFromInitiateUploadCallbackAndQuit, + base::Bind(&test_util::CopyResultsFromInitiateUploadCallbackAndQuit, &result_code, &upload_url), base::FilePath::FromUTF8Unsafe("drive/existingfile.txt"), diff --git a/chrome/browser/google_apis/test_util.cc b/chrome/browser/google_apis/test_util.cc index d3c2c6c..3bd95ac 100644 --- a/chrome/browser/google_apis/test_util.cc +++ b/chrome/browser/google_apis/test_util.cc @@ -186,6 +186,15 @@ void CopyResultsFromInitiateUploadCallback( *url_out = url_in; } +void CopyResultsFromInitiateUploadCallbackAndQuit( + GDataErrorCode* error_out, + GURL* url_out, + GDataErrorCode error_in, + const GURL& url_in) { + CopyResultsFromInitiateUploadCallback(error_out, url_out, error_in, url_in); + MessageLoop::current()->Quit(); +} + void CopyResultsFromUploadRangeCallback( UploadRangeResponse* response_out, scoped_ptr<ResourceEntry>* entry_out, diff --git a/chrome/browser/google_apis/test_util.h b/chrome/browser/google_apis/test_util.h index 2f30377..6f3f1e5 100644 --- a/chrome/browser/google_apis/test_util.h +++ b/chrome/browser/google_apis/test_util.h @@ -130,6 +130,13 @@ void CopyResultsFromInitiateUploadCallback( GDataErrorCode error_in, const GURL& url_in); +// Copies the results from InitiateUploadCallback and quit the message loop. +void CopyResultsFromInitiateUploadCallbackAndQuit( + GDataErrorCode* error_out, + GURL* url_out, + GDataErrorCode error_in, + const GURL& url_in); + // Copies the results from ResumeUploadCallback. void CopyResultsFromUploadRangeCallback( UploadRangeResponse* response_out, |