summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos
diff options
context:
space:
mode:
authorgspencer@chromium.org <gspencer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-27 21:07:24 +0000
committergspencer@chromium.org <gspencer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-27 21:07:24 +0000
commiteaab7a3cc36ce7b3def0244a24d2823ec8baff91 (patch)
treead7bda7001c65de74e0b7d72b05483fa4305f391 /chrome/browser/chromeos
parent3e4d15aad961909fd541ea553bf9382dcfd016ea (diff)
downloadchromium_src-eaab7a3cc36ce7b3def0244a24d2823ec8baff91.zip
chromium_src-eaab7a3cc36ce7b3def0244a24d2823ec8baff91.tar.gz
chromium_src-eaab7a3cc36ce7b3def0244a24d2823ec8baff91.tar.bz2
Merge 142912 - gdata: Add upload_url() to GDataFile.
Per "Updating document or file content with the resumable protocol" section in the Google Documents List API version 3.0 [1], we should use "resumable-edit-media" URLs for updating existing files. Since we did not store the resumable-edit-media URLs in the existing protobuf files, we need to reject these files at the loading time. [1] https://developers.google.com/google-apps/documents-list/ BUG=127080 TEST=added some unit tests; open google drive with older protobuf. confirm that loading of the protobuf failed (error from gdata_files.cc is emitted) but everything works just fine as we fetch the feeds from the server Review URL: https://chromiumcodereview.appspot.com/10583006 TBR=satorux@chromium.org Review URL: https://chromiumcodereview.appspot.com/10696017 git-svn-id: svn://svn.chromium.org/chrome/branches/1180/src@144553 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/chromeos')
-rw-r--r--chrome/browser/chromeos/gdata/gdata.proto4
-rw-r--r--chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc3
-rw-r--r--chrome/browser/chromeos/gdata/gdata_files.cc34
-rw-r--r--chrome/browser/chromeos/gdata/gdata_files.h4
-rw-r--r--chrome/browser/chromeos/gdata/gdata_files_unittest.cc85
5 files changed, 123 insertions, 7 deletions
diff --git a/chrome/browser/chromeos/gdata/gdata.proto b/chrome/browser/chromeos/gdata/gdata.proto
index 68e20fb..a0ac9a3 100644
--- a/chrome/browser/chromeos/gdata/gdata.proto
+++ b/chrome/browser/chromeos/gdata/gdata.proto
@@ -42,6 +42,9 @@ message GDataFileProto {
optional string id = 7;
optional string file_md5 = 8;
optional string document_extension = 9;
+ // This is "resumable-edit-media" URL, used to update an existing file.
+ // See https://developers.google.com/google-apps/documents-list/
+ optional string upload_url = 11;
optional bool is_hosted_document = 10;
}
@@ -50,6 +53,7 @@ message GDataDirectoryProto {
optional GDataEntryProto gdata_entry = 1;
optional string start_feed_url = 3;
optional string next_feed_url = 4;
+ // This is "resumable-create-media" URL, used to upload a new file.
optional string upload_url = 5;
optional uint32 origin = 6;
repeated GDataDirectoryProto child_directories = 7;
diff --git a/chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc b/chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc
index 195249f..2795e68 100644
--- a/chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc
+++ b/chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc
@@ -1102,6 +1102,7 @@ class GDataFileSystemTest : public testing::Test {
// drive/File1
GDataFileProto* file = root_dir->add_child_files();
+ file->set_upload_url("http://resumable-edit-media/1");
file_base = file->mutable_gdata_entry();
platform_info = file_base->mutable_file_info();
file_base->set_title("File1");
@@ -1117,6 +1118,7 @@ class GDataFileSystemTest : public testing::Test {
// drive/Dir1/File2
file = dir1->add_child_files();
+ file->set_upload_url("http://resumable-edit-media/2");
file_base = file->mutable_gdata_entry();
platform_info = file_base->mutable_file_info();
file_base->set_title("File2");
@@ -1132,6 +1134,7 @@ class GDataFileSystemTest : public testing::Test {
// drive/Dir1/SubDir2/File3
file = dir2->add_child_files();
+ file->set_upload_url("http://resumable-edit-media/3");
file_base = file->mutable_gdata_entry();
platform_info = file_base->mutable_file_info();
file_base->set_title("File3");
diff --git a/chrome/browser/chromeos/gdata/gdata_files.cc b/chrome/browser/chromeos/gdata/gdata_files.cc
index 67e65dc..b8759d2 100644
--- a/chrome/browser/chromeos/gdata/gdata_files.cc
+++ b/chrome/browser/chromeos/gdata/gdata_files.cc
@@ -147,6 +147,12 @@ GDataEntry* GDataFile::FromDocumentEntry(GDataDirectory* parent,
if (doc->is_file()) {
file->file_info_.size = doc->file_size();
file->file_md5_ = doc->file_md5();
+
+ // The resumable-edit-media link should only be present for regualar
+ // files as hosted documents are not uploadable.
+ const Link* upload_link = doc->GetLinkByType(Link::RESUMABLE_EDIT_MEDIA);
+ if (upload_link)
+ file->upload_url_ = upload_link->href();
} else {
// ... a hosted document.
// Attach .g<something> extension to hosted documents so we can special
@@ -570,6 +576,14 @@ bool GDataFile::FromProto(const GDataFileProto& proto) {
id_ = proto.id();
file_md5_ = proto.file_md5();
document_extension_ = proto.document_extension();
+ // Reject older protobuf that does not contain the upload URL. This URL is
+ // necessary for uploading dirty files (ex. updating existing files).
+ if (!proto.has_upload_url()) {
+ LOG(ERROR) << "Incompatible proto detected (no upload URL): "
+ << proto.gdata_entry().title();
+ return false;
+ }
+ upload_url_ = GURL(proto.upload_url());
is_hosted_document_ = proto.is_hosted_document();
return true;
@@ -586,19 +600,15 @@ void GDataFile::ToProto(GDataFileProto* proto) const {
proto->set_id(id_);
proto->set_file_md5(file_md5_);
proto->set_document_extension(document_extension_);
+ // The upload URL must be stored even if it's empty, as this is used to
+ // detect older protobuf. See FromProto() above.
+ proto->set_upload_url(upload_url_.spec());
proto->set_is_hosted_document(is_hosted_document_);
}
bool GDataDirectory::FromProto(const GDataDirectoryProto& proto) {
DCHECK(proto.gdata_entry().file_info().is_directory());
- if (!GDataEntry::FromProto(proto.gdata_entry()))
- return false;
-
- start_feed_url_ = GURL(proto.start_feed_url());
- next_feed_url_ = GURL(proto.next_feed_url());
- upload_url_ = GURL(proto.upload_url());
- origin_ = ContentOrigin(proto.origin());
for (int i = 0; i < proto.child_files_size(); ++i) {
scoped_ptr<GDataFile> file(new GDataFile(this, root_));
if (!file->FromProto(proto.child_files(i))) {
@@ -616,6 +626,16 @@ bool GDataDirectory::FromProto(const GDataDirectoryProto& proto) {
AddEntry(dir.release());
}
+ // The states of the directory should be updated after children are
+ // handled successfully, so that incomplete states are not left.
+ if (!GDataEntry::FromProto(proto.gdata_entry()))
+ return false;
+
+ start_feed_url_ = GURL(proto.start_feed_url());
+ next_feed_url_ = GURL(proto.next_feed_url());
+ upload_url_ = GURL(proto.upload_url());
+ origin_ = ContentOrigin(proto.origin());
+
return true;
}
diff --git a/chrome/browser/chromeos/gdata/gdata_files.h b/chrome/browser/chromeos/gdata/gdata_files.h
index ce73e27..deed878 100644
--- a/chrome/browser/chromeos/gdata/gdata_files.h
+++ b/chrome/browser/chromeos/gdata/gdata_files.h
@@ -216,6 +216,7 @@ class GDataFile : public GDataEntry {
DocumentEntry::EntryKind kind() const { return kind_; }
const GURL& thumbnail_url() const { return thumbnail_url_; }
const GURL& alternate_url() const { return alternate_url_; }
+ const GURL& upload_url() const { return upload_url_; }
const std::string& content_mime_type() const { return content_mime_type_; }
const std::string& etag() const { return etag_; }
const std::string& id() const { return id_; }
@@ -235,6 +236,9 @@ class GDataFile : public GDataEntry {
DocumentEntry::EntryKind kind_;
GURL thumbnail_url_;
GURL alternate_url_;
+ // Upload url, corresponds to resumable-edit-media link, used for updating
+ // the content of the file.
+ GURL upload_url_;
std::string content_mime_type_;
std::string etag_;
std::string id_;
diff --git a/chrome/browser/chromeos/gdata/gdata_files_unittest.cc b/chrome/browser/chromeos/gdata/gdata_files_unittest.cc
index d7c6fdf..bbfb1c9 100644
--- a/chrome/browser/chromeos/gdata/gdata_files_unittest.cc
+++ b/chrome/browser/chromeos/gdata/gdata_files_unittest.cc
@@ -12,6 +12,28 @@
namespace gdata {
+namespace {
+
+const char kResumableEditMediaUrl[] = "http://resumable-edit-media/";
+
+} // namespace
+
+TEST(GDataFileTest, FromProto_DetectBadUploadUrl) {
+ GDataFileProto proto;
+ proto.mutable_gdata_entry()->set_title("test.txt");
+
+ GDataFile file(NULL, NULL);
+ // This should fail as the upload URL is empty.
+ ASSERT_FALSE(file.FromProto(proto));
+
+ // Set a upload URL.
+ proto.set_upload_url(kResumableEditMediaUrl);
+
+ // This should succeed as the resource ID is correct.
+ ASSERT_TRUE(file.FromProto(proto));
+ EXPECT_EQ(kResumableEditMediaUrl, file.upload_url().spec());
+}
+
TEST(GDataRootDirectoryTest, ParseFromString_DetectBadTitle) {
GDataRootDirectoryProto proto;
GDataEntryProto* mutable_entry =
@@ -71,6 +93,69 @@ TEST(GDataRootDirectoryTest, ParseFromString_DetectBadResourceID) {
EXPECT_EQ(kGDataRootDirectoryResourceId, root.resource_id());
}
+// We have a similar test in FromProto_DetectBadUploadUrl, but the test here
+// is to ensure that an error in GDataFile::FromProto() is properly
+// propagated to GDataRootDirectory::ParseFromString().
+TEST(GDataRootDirectoryTest, ParseFromString_DetectNoUploadUrl) {
+ // Set up the root directory properly.
+ GDataRootDirectoryProto root_directory_proto;
+ GDataEntryProto* mutable_entry =
+ root_directory_proto.mutable_gdata_directory()->mutable_gdata_entry();
+ mutable_entry->mutable_file_info()->set_is_directory(true);
+ mutable_entry->set_title(kGDataRootDirectory);
+ mutable_entry->set_resource_id(kGDataRootDirectoryResourceId);
+ // Set the origin to the server.
+ root_directory_proto.mutable_gdata_directory()->set_origin(FROM_SERVER);
+
+ // Add an empty sub directory under the root directory. This directory is
+ // added to ensure that nothing is left when the parsing failed.
+ GDataDirectoryProto* sub_directory_proto =
+ root_directory_proto.mutable_gdata_directory()->add_child_directories();
+ sub_directory_proto->mutable_gdata_entry()->mutable_file_info()->
+ set_is_directory(true);
+ sub_directory_proto->mutable_gdata_entry()->set_title("empty");
+
+ // Add a sub directory under the root directory.
+ sub_directory_proto =
+ root_directory_proto.mutable_gdata_directory()->add_child_directories();
+ sub_directory_proto->mutable_gdata_entry()->mutable_file_info()->
+ set_is_directory(true);
+ sub_directory_proto->mutable_gdata_entry()->set_title("dir");
+
+ // Add a new file under the sub directory "dir".
+ GDataFileProto* file_proto =
+ sub_directory_proto->add_child_files();
+ file_proto->mutable_gdata_entry()->set_title("test.txt");
+
+ GDataRootDirectory root;
+ // The origin is set to UNINITIALIZED by default.
+ ASSERT_EQ(UNINITIALIZED, root.origin());
+ std::string serialized_proto;
+ // Serialize the proto and check if it's loaded.
+ // This should fail as the upload URL is not set for |file_proto|.
+ ASSERT_TRUE(root_directory_proto.SerializeToString(&serialized_proto));
+ ASSERT_FALSE(root.ParseFromString(serialized_proto));
+ // Nothing should be added to the root directory if the parse failed.
+ ASSERT_TRUE(root.child_files().empty());
+ ASSERT_TRUE(root.child_directories().empty());
+ // The origin should remain UNINITIALIZED because the loading failed.
+ ASSERT_EQ(UNINITIALIZED, root.origin());
+
+ // Set an upload URL.
+ file_proto->set_upload_url(kResumableEditMediaUrl);
+
+ // Serialize the proto and check if it's loaded.
+ // This should succeed as the upload URL is set for |file_proto|.
+ ASSERT_TRUE(root_directory_proto.SerializeToString(&serialized_proto));
+ ASSERT_TRUE(root.ParseFromString(serialized_proto));
+ // No file should be added to the root directory.
+ ASSERT_TRUE(root.child_files().empty());
+ // Two directories ("empty", "dir") should be added to the root directory.
+ ASSERT_EQ(2U, root.child_directories().size());
+ // The origin should change to FROM_CACHE because we loaded from the cache.
+ ASSERT_EQ(FROM_CACHE, root.origin());
+}
+
TEST(GDataRootDirectoryTest, RefreshFile) {
GDataRootDirectory root;
// Add a directory to the file system.