summaryrefslogtreecommitdiffstats
path: root/chrome/browser/google_apis
diff options
context:
space:
mode:
authorhidehiko@chromium.org <hidehiko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-01 03:56:24 +0000
committerhidehiko@chromium.org <hidehiko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-01 03:56:24 +0000
commitbcc2c6dcda4c70cf546cec0b25228fa571b4924c (patch)
tree782d4a7d55a30afd437ac34f704363782e8ef15a /chrome/browser/google_apis
parentcc7dec210cd2a325e65eaab44e4569846de72862 (diff)
downloadchromium_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.cc62
-rw-r--r--chrome/browser/google_apis/drive_api_operations.h36
-rw-r--r--chrome/browser/google_apis/drive_api_operations_unittest.cc104
-rw-r--r--chrome/browser/google_apis/drive_api_service.cc13
-rw-r--r--chrome/browser/google_apis/gdata_wapi_operations_unittest.cc23
-rw-r--r--chrome/browser/google_apis/test_util.cc9
-rw-r--r--chrome/browser/google_apis/test_util.h7
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,