Commit 71c53fdf authored by zelidrag@chromium.org's avatar zelidrag@chromium.org

Support for delta feed processing.

BUG=chromium-os:29052
TEST=GDataFileSystemTest.ChangeFeed_*

Review URL: https://chromiumcodereview.appspot.com/10006023

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132299 0039d316-1c4b-4281-b951-d872f2087c98
parent e639d856
...@@ -1589,8 +1589,8 @@ void GetGDataFilePropertiesFunction::OnFileProperties( ...@@ -1589,8 +1589,8 @@ void GetGDataFilePropertiesFunction::OnFileProperties(
} }
property_dict->SetString("thumbnailUrl", file->thumbnail_url().spec()); property_dict->SetString("thumbnailUrl", file->thumbnail_url().spec());
if (!file->edit_url().is_empty()) if (!file->alternate_url().is_empty())
property_dict->SetString("editUrl", file->edit_url().spec()); property_dict->SetString("editUrl", file->alternate_url().spec());
if (!file->content_url().is_empty()) if (!file->content_url().is_empty())
property_dict->SetString("contentUrl", file->content_url().spec()); property_dict->SetString("contentUrl", file->content_url().spec());
......
...@@ -228,7 +228,7 @@ class GetFilePropertiesDelegate : public gdata::FindFileDelegate { ...@@ -228,7 +228,7 @@ class GetFilePropertiesDelegate : public gdata::FindFileDelegate {
if (error == base::PLATFORM_FILE_OK && file && file->AsGDataFile()) { if (error == base::PLATFORM_FILE_OK && file && file->AsGDataFile()) {
resource_id_ = file->AsGDataFile()->resource_id(); resource_id_ = file->AsGDataFile()->resource_id();
file_name_ = file->AsGDataFile()->file_name(); file_name_ = file->AsGDataFile()->file_name();
edit_url_ = file->AsGDataFile()->edit_url(); edit_url_ = file->AsGDataFile()->alternate_url();
} }
} }
......
...@@ -26,7 +26,7 @@ message GDataFileBaseProto { ...@@ -26,7 +26,7 @@ message GDataFileBaseProto {
optional string file_name = 2; optional string file_name = 2;
optional string title = 3; optional string title = 3;
optional string resource_id = 4; optional string resource_id = 4;
optional string self_url = 5; optional string edit_url = 5;
optional string content_url = 6; optional string content_url = 6;
} }
...@@ -35,7 +35,7 @@ message GDataFileProto { ...@@ -35,7 +35,7 @@ message GDataFileProto {
optional GDataFileBaseProto gdata_file_base = 1; optional GDataFileBaseProto gdata_file_base = 1;
optional uint32 kind = 2; optional uint32 kind = 2;
optional string thumbnail_url = 3; optional string thumbnail_url = 3;
optional string edit_url = 4; optional string alternate_url = 4;
optional string content_mime_type = 5; optional string content_mime_type = 5;
optional string etag = 6; optional string etag = 6;
optional string id = 7; optional string id = 7;
......
...@@ -132,7 +132,7 @@ struct GDataFileProperties { ...@@ -132,7 +132,7 @@ struct GDataFileProperties {
std::string file_md5; std::string file_md5;
std::string mime_type; std::string mime_type;
GURL content_url; GURL content_url;
GURL edit_url; GURL alternate_url;
bool is_hosted_document; bool is_hosted_document;
}; };
...@@ -505,14 +505,6 @@ class GDataFileSystem : public GDataFileSystemInterface, ...@@ -505,14 +505,6 @@ class GDataFileSystem : public GDataFileSystemInterface,
DIRECTORY_ALREADY_PRESENT, DIRECTORY_ALREADY_PRESENT,
}; };
// Document feed chunk type.
enum FeedChunkType {
// The very first part of content we fetch (i.e. first 200 items),
FEED_CHUNK_INITIAL,
// The rest of the feed that excludes FEED_CHUNK_INITIAL,
FEED_CHUNK_REST
};
// Defines set of parameters passes to intermediate callbacks during // Defines set of parameters passes to intermediate callbacks during
// execution of CreateDirectory() method. // execution of CreateDirectory() method.
struct CreateDirectoryParams { struct CreateDirectoryParams {
...@@ -555,36 +547,39 @@ class GDataFileSystem : public GDataFileSystemInterface, ...@@ -555,36 +547,39 @@ class GDataFileSystem : public GDataFileSystemInterface,
// Defines set of parameters sent to callback OnGetDocuments(). // Defines set of parameters sent to callback OnGetDocuments().
struct GetDocumentsParams { struct GetDocumentsParams {
GetDocumentsParams(const FilePath& search_file_path, GetDocumentsParams(int start_changestamp,
FeedChunkType chunk_type, int root_feed_changestamp,
int largest_changestamp,
std::vector<DocumentFeed*>* feed_list, std::vector<DocumentFeed*>* feed_list,
const FilePath& search_file_path,
const FindFileCallback& callback); const FindFileCallback& callback);
~GetDocumentsParams(); ~GetDocumentsParams();
FilePath search_file_path; // Changestamps are positive numbers in increasing order. The difference
GDataFileSystem::FeedChunkType chunk_type; // between two changestamps is proportional equal to number of items in
int largest_changestamp; // delta feed between them - bigger the difference, more likely bigger
// number of items in delta feeds.
int start_changestamp;
int root_feed_changestamp;
scoped_ptr<std::vector<DocumentFeed*> > feed_list; scoped_ptr<std::vector<DocumentFeed*> > feed_list;
FilePath search_file_path;
FindFileCallback callback; FindFileCallback callback;
}; };
// Defines set of parameters sent to callback OnGetDocuments(). // Defines set of parameters sent to callback OnGetDocuments().
struct LoadRootFeedParams { struct LoadRootFeedParams {
LoadRootFeedParams(FilePath search_file_path, LoadRootFeedParams(FilePath search_file_path,
FeedChunkType chunk_type,
int largest_changestamp,
bool should_load_from_server, bool should_load_from_server,
const FindFileCallback& callback); const FindFileCallback& callback);
~LoadRootFeedParams(); ~LoadRootFeedParams();
FilePath search_file_path; FilePath search_file_path;
GDataFileSystem::FeedChunkType chunk_type;
int largest_changestamp;
bool should_load_from_server; bool should_load_from_server;
const FindFileCallback callback; const FindFileCallback callback;
}; };
typedef std::map<std::string /* resource_id */, GDataFileBase*>
FileResourceIdMap;
// Callback similar to FileOperationCallback but with a given |file_path|. // Callback similar to FileOperationCallback but with a given |file_path|.
typedef base::Callback<void(base::PlatformFileError error, typedef base::Callback<void(base::PlatformFileError error,
const FilePath& file_path)> const FilePath& file_path)>
...@@ -834,16 +829,6 @@ class GDataFileSystem : public GDataFileSystemInterface, ...@@ -834,16 +829,6 @@ class GDataFileSystem : public GDataFileSystemInterface,
base::PlatformFileError AddFileToDirectoryOnFilesystem( base::PlatformFileError AddFileToDirectoryOnFilesystem(
const FilePath& file_path, const FilePath& dir_path); const FilePath& file_path, const FilePath& dir_path);
// Restores account metadata and root feed from cache.
void RestoreRootFeedFromCache(const FilePath& search_file_path,
const FindFileCallback& callback);
// Helper function for loading account metadata during cache restore.
void OnLoadCachedMetadata(const FilePath& search_file_path,
const FindFileCallback& callback,
base::PlatformFileError* error,
base::Value* metadata_value);
// Removes a file or directory at |file_path| from another directory at // Removes a file or directory at |file_path| from another directory at
// |dir_path| on in-memory snapshot of the file system. // |dir_path| on in-memory snapshot of the file system.
// Returns PLATFORM_FILE_OK if successful. // Returns PLATFORM_FILE_OK if successful.
...@@ -863,10 +848,33 @@ class GDataFileSystem : public GDataFileSystemInterface, ...@@ -863,10 +848,33 @@ class GDataFileSystem : public GDataFileSystemInterface,
// Updates whole directory structure feeds collected in |feed_list|. // Updates whole directory structure feeds collected in |feed_list|.
// On success, returns PLATFORM_FILE_OK. Record file statistics as UMA // On success, returns PLATFORM_FILE_OK. Record file statistics as UMA
// histograms. // histograms.
base::PlatformFileError UpdateDirectoryWithDocumentFeed( base::PlatformFileError UpdateFromFeed(
const std::vector<DocumentFeed*>& feed_list, const std::vector<DocumentFeed*>& feed_list,
ContentOrigin origin, ContentOrigin origin,
int largest_changestamp); int largest_changestamp,
int root_feed_changestamp);
// Applies the pre-processed feed from |file_map| map onto the file system.
void ApplyFeedFromFileUrlMap(bool is_delta_feed,
int feed_changestamp,
const FileResourceIdMap& file_map);
// Finds directory where new |file| should be added to during feed processing.
// |orphaned_entries_dir| collects files/dirs that don't have a parent in
// either locally cached file system or in this new feed.
GDataDirectory* FindDirectoryForNewEntry(
GDataFileBase* new_file,
const FileResourceIdMap& file_map,
GDataRootDirectory* orphaned_entries);
// Converts list of document feeds from collected feeds into
// FileResourceIdMap.
base::PlatformFileError FeedToFileResourceMap(
const std::vector<DocumentFeed*>& feed_list,
FileResourceIdMap* file_map,
int* feed_changestamp,
int* num_regular_files,
int* num_hosted_documents);
// Converts |entry_value| into GFileDocument instance and adds it // Converts |entry_value| into GFileDocument instance and adds it
// to virtual file system at |directory_path|. // to virtual file system at |directory_path|.
...@@ -882,33 +890,38 @@ class GDataFileSystem : public GDataFileSystemInterface, ...@@ -882,33 +890,38 @@ class GDataFileSystem : public GDataFileSystemInterface,
// Retreives account metadata and determines from the last change timestamp // Retreives account metadata and determines from the last change timestamp
// if the feed content loading from the server needs to be initiated. // if the feed content loading from the server needs to be initiated.
void ReloadFeedFromServerIfNeeded(const FilePath& search_file_path, void ReloadFeedFromServerIfNeeded(ContentOrigin initial_origin,
ContentOrigin initial_origin, int local_changestamp,
const FilePath& search_file_path,
const FindFileCallback& callback); const FindFileCallback& callback);
// Helper callback for handling results of metadata retrieval initiated from // Helper callback for handling results of metadata retrieval initiated from
// ReloadFeedFromServerIfNeeded(). This method makes a decision about fetching // ReloadFeedFromServerIfNeeded(). This method makes a decision about fetching
// the content of the root feed during the root directory refresh process. // the content of the root feed during the root directory refresh process.
void OnGetAccountMetadata(const FilePath& search_file_path, void OnGetAccountMetadata(ContentOrigin initial_origin,
ContentOrigin initial_origin, int local_changestamp,
const FilePath& search_file_path,
const FindFileCallback& callback, const FindFileCallback& callback,
GDataErrorCode error, GDataErrorCode error,
scoped_ptr<base::Value> feed_data); scoped_ptr<base::Value> feed_data);
// Starts root feed load from the server. If successful, it will try to find // Starts root feed load from the server. Value of |start_changestamp|
// the file upon retrieval completion. // determines the type of feed to load - 0 means root feed, every other
void LoadFeedFromServer(const FilePath& search_file_path, // value would trigger delta feed.
int largest_changestamp, // In the case of loading the root feed we use |root_feed_changestamp| as its
// initial changestamp value since it does not come with that info.
// If successful, it will try to find the file upon retrieval completion.
void LoadFeedFromServer(int start_changestamp,
int root_feed_changestamp,
const FilePath& search_file_path,
const FindFileCallback& callback); const FindFileCallback& callback);
// Starts root feed load from the cache. If successful, it will try to find // Starts root feed load from the cache. If successful, it will try to find
// the file upon retrieval completion. In addition to that, it will // the file upon retrieval completion. In addition to that, it will
// initate retrieval of the root feed from the server if // initate retrieval of the root feed from the server if
// |should_load_from_server| is set. // |should_load_from_server| is set.
void LoadRootFeedFromCache(FeedChunkType chunk_type, void LoadRootFeedFromCache(bool should_load_from_server,
int largest_changestamp,
const FilePath& search_file_path, const FilePath& search_file_path,
bool should_load_from_server,
const FindFileCallback& callback); const FindFileCallback& callback);
// Loads json file content content from |file_path| on IO thread pool. // Loads json file content content from |file_path| on IO thread pool.
...@@ -917,7 +930,7 @@ class GDataFileSystem : public GDataFileSystemInterface, ...@@ -917,7 +930,7 @@ class GDataFileSystem : public GDataFileSystemInterface,
base::Value* result); base::Value* result);
// Callback for handling root directory refresh from the cache. // Callback for handling root directory refresh from the cache.
void OnProtoLoaded(const LoadRootFeedParams& params, void OnProtoLoaded(LoadRootFeedParams* params,
base::PlatformFileError* error, base::PlatformFileError* error,
std::string* proto); std::string* proto);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "chrome/browser/chromeos/gdata/gdata.pb.h" #include "chrome/browser/chromeos/gdata/gdata.pb.h"
#include "chrome/browser/chromeos/gdata/gdata_file_system.h" #include "chrome/browser/chromeos/gdata/gdata_file_system.h"
#include "chrome/browser/chromeos/gdata/gdata_parser.h" #include "chrome/browser/chromeos/gdata/gdata_parser.h"
#include "net/base/escape.h"
namespace { namespace {
...@@ -43,6 +44,12 @@ std::string CacheSubDirectoryTypeToString( ...@@ -43,6 +44,12 @@ std::string CacheSubDirectoryTypeToString(
return "unknown subdir"; return "unknown subdir";
} }
// Extracts resource_id out of edit url.
std::string ExtractResourceId(const GURL& url) {
return net::UnescapeURLComponent(url.ExtractFileName(),
net::UnescapeRule::URL_SPECIAL_CHARS);
}
} // namespace } // namespace
namespace gdata { namespace gdata {
...@@ -51,7 +58,8 @@ namespace gdata { ...@@ -51,7 +58,8 @@ namespace gdata {
GDataFileBase::GDataFileBase(GDataDirectory* parent, GDataRootDirectory* root) GDataFileBase::GDataFileBase(GDataDirectory* parent, GDataRootDirectory* root)
: parent_(parent), : parent_(parent),
root_(root) { root_(root),
deleted_(false) {
} }
GDataFileBase::~GDataFileBase() { GDataFileBase::~GDataFileBase() {
...@@ -170,9 +178,10 @@ GDataFileBase* GDataFile::FromDocumentEntry(GDataDirectory* parent, ...@@ -170,9 +178,10 @@ GDataFileBase* GDataFile::FromDocumentEntry(GDataDirectory* parent,
file->file_info_.size = 0; file->file_info_.size = 0;
} }
file->kind_ = doc->kind(); file->kind_ = doc->kind();
const Link* self_link = doc->GetLinkByType(Link::SELF); const Link* edit_link = doc->GetLinkByType(Link::EDIT);
DCHECK(self_link); DCHECK(edit_link) << "No edit link for file " << file->title_;
file->self_url_ = self_link->href(); if (edit_link)
file->edit_url_ = edit_link->href();
file->content_url_ = doc->content_url(); file->content_url_ = doc->content_url();
file->content_mime_type_ = doc->content_mime_type(); file->content_mime_type_ = doc->content_mime_type();
file->etag_ = doc->etag(); file->etag_ = doc->etag();
...@@ -182,6 +191,10 @@ GDataFileBase* GDataFile::FromDocumentEntry(GDataDirectory* parent, ...@@ -182,6 +191,10 @@ GDataFileBase* GDataFile::FromDocumentEntry(GDataDirectory* parent,
file->file_info_.last_modified = doc->updated_time(); file->file_info_.last_modified = doc->updated_time();
file->file_info_.last_accessed = doc->updated_time(); file->file_info_.last_accessed = doc->updated_time();
file->file_info_.creation_time = doc->published_time(); file->file_info_.creation_time = doc->published_time();
file->deleted_ = doc->deleted();
const Link* parent_link = doc->GetLinkByType(Link::PARENT);
if (parent_link)
file->parent_resource_id_ = ExtractResourceId(parent_link->href());
// SetFileNameFromTitle() must be called after |title_|, // SetFileNameFromTitle() must be called after |title_|,
// |is_hosted_document_| and |document_extension_| are set. // |is_hosted_document_| and |document_extension_| are set.
...@@ -193,7 +206,7 @@ GDataFileBase* GDataFile::FromDocumentEntry(GDataDirectory* parent, ...@@ -193,7 +206,7 @@ GDataFileBase* GDataFile::FromDocumentEntry(GDataDirectory* parent,
const Link* alternate_link = doc->GetLinkByType(Link::ALTERNATE); const Link* alternate_link = doc->GetLinkByType(Link::ALTERNATE);
if (alternate_link) if (alternate_link)
file->edit_url_ = alternate_link->href(); file->alternate_url_ = alternate_link->href();
return file; return file;
} }
...@@ -233,9 +246,16 @@ GDataFileBase* GDataDirectory::FromDocumentEntry(GDataDirectory* parent, ...@@ -233,9 +246,16 @@ GDataFileBase* GDataDirectory::FromDocumentEntry(GDataDirectory* parent,
dir->start_feed_url_ = doc->content_url(); dir->start_feed_url_ = doc->content_url();
dir->resource_id_ = doc->resource_id(); dir->resource_id_ = doc->resource_id();
dir->content_url_ = doc->content_url(); dir->content_url_ = doc->content_url();
const Link* self_link = doc->GetLinkByType(Link::SELF); dir->deleted_ = doc->deleted();
DCHECK(self_link);
dir->self_url_ = self_link->href(); const Link* edit_link = doc->GetLinkByType(Link::EDIT);
DCHECK(edit_link) << "No edit link for dir " << dir->title_;
if (edit_link)
dir->edit_url_ = edit_link->href();
const Link* parent_link = doc->GetLinkByType(Link::PARENT);
if (parent_link)
dir->parent_resource_id_ = ExtractResourceId(parent_link->href());
const Link* upload_link = doc->GetLinkByType(Link::RESUMABLE_CREATE_MEDIA); const Link* upload_link = doc->GetLinkByType(Link::RESUMABLE_CREATE_MEDIA);
if (upload_link) if (upload_link)
...@@ -290,6 +310,11 @@ void GDataDirectory::AddFile(GDataFileBase* file) { ...@@ -290,6 +310,11 @@ void GDataDirectory::AddFile(GDataFileBase* file) {
if (full_file_name.value() != file->file_name()) if (full_file_name.value() != file->file_name())
file->set_file_name(full_file_name.value()); file->set_file_name(full_file_name.value());
children_.insert(std::make_pair(file->file_name(), file)); children_.insert(std::make_pair(file->file_name(), file));
DVLOG(1) << "Adding: "
<< this->GetFilePath().value()
<< "/" + file->file_name()
<< ", resource " << file->parent_resource_id()
<< "/" + file->resource_id();
// Add file to resource map. // Add file to resource map.
root_->AddFileToResourceMap(file); root_->AddFileToResourceMap(file);
...@@ -312,6 +337,17 @@ bool GDataDirectory::TakeFile(GDataFileBase* file) { ...@@ -312,6 +337,17 @@ bool GDataDirectory::TakeFile(GDataFileBase* file) {
return true; return true;
} }
bool GDataDirectory::TakeOverFiles(GDataDirectory* dir) {
for (GDataFileCollection::iterator iter = dir->children_.begin();
iter != dir->children_.end(); ++iter) {
GDataFileBase* file = iter->second;
file->SetFileNameFromTitle();
AddFile(file);
}
dir->children_.clear();
return true;
}
bool GDataDirectory::RemoveFile(GDataFileBase* file) { bool GDataDirectory::RemoveFile(GDataFileBase* file) {
DCHECK(file); DCHECK(file);
...@@ -378,17 +414,12 @@ GDataRootDirectory* GDataRootDirectory::AsGDataRootDirectory() { ...@@ -378,17 +414,12 @@ GDataRootDirectory* GDataRootDirectory::AsGDataRootDirectory() {
void GDataRootDirectory::AddFileToResourceMap(GDataFileBase* file) { void GDataRootDirectory::AddFileToResourceMap(GDataFileBase* file) {
// GDataFileSystem has already locked. // GDataFileSystem has already locked.
// Only files have resource. resource_map_.insert(std::make_pair(file->resource_id(), file));
if (file->AsGDataFile()) {
resource_map_.insert(
std::make_pair(file->AsGDataFile()->resource_id(), file));
}
} }
void GDataRootDirectory::RemoveFileFromResourceMap(GDataFileBase* file) { void GDataRootDirectory::RemoveFileFromResourceMap(GDataFileBase* file) {
// GDataFileSystem has already locked. // GDataFileSystem has already locked.
if (file->AsGDataFile()) resource_map_.erase(file->resource_id());
resource_map_.erase(file->AsGDataFile()->resource_id());
} }
void GDataRootDirectory::RemoveFilesFromResourceMap( void GDataRootDirectory::RemoveFilesFromResourceMap(
...@@ -402,9 +433,7 @@ void GDataRootDirectory::RemoveFilesFromResourceMap( ...@@ -402,9 +433,7 @@ void GDataRootDirectory::RemoveFilesFromResourceMap(
continue; continue;
} }
// Only files have resource. resource_map_.erase(iter->second->resource_id());
if (iter->second->AsGDataFile())
resource_map_.erase(iter->second->AsGDataFile()->resource_id());
} }
} }
...@@ -538,7 +567,7 @@ void GDataFileBase::FromProto(const GDataFileBaseProto& proto) { ...@@ -538,7 +567,7 @@ void GDataFileBase::FromProto(const GDataFileBaseProto& proto) {
file_name_ = proto.file_name(); file_name_ = proto.file_name();
title_ = proto.title(); title_ = proto.title();
resource_id_ = proto.resource_id(); resource_id_ = proto.resource_id();
self_url_ = GURL(proto.self_url()); edit_url_ = GURL(proto.edit_url());
content_url_ = GURL(proto.content_url()); content_url_ = GURL(proto.content_url());
} }
...@@ -557,7 +586,7 @@ void GDataFileBase::ToProto(GDataFileBaseProto* proto) const { ...@@ -557,7 +586,7 @@ void GDataFileBase::ToProto(GDataFileBaseProto* proto) const {
proto->set_file_name(file_name_); proto->set_file_name(file_name_);
proto->set_title(title_); proto->set_title(title_);
proto->set_resource_id(resource_id_); proto->set_resource_id(resource_id_);
proto->set_self_url(self_url_.spec()); proto->set_edit_url(edit_url_.spec());
proto->set_content_url(content_url_.spec()); proto->set_content_url(content_url_.spec());
} }
...@@ -565,7 +594,7 @@ void GDataFile::FromProto(const GDataFileProto& proto) { ...@@ -565,7 +594,7 @@ void GDataFile::FromProto(const GDataFileProto& proto) {
GDataFileBase::FromProto(proto.gdata_file_base()); GDataFileBase::FromProto(proto.gdata_file_base());
kind_ = DocumentEntry::EntryKind(proto.kind()); kind_ = DocumentEntry::EntryKind(proto.kind());
thumbnail_url_ = GURL(proto.thumbnail_url()); thumbnail_url_ = GURL(proto.thumbnail_url());
edit_url_ = GURL(proto.edit_url()); alternate_url_ = GURL(proto.alternate_url());
content_mime_type_ = proto.content_mime_type(); content_mime_type_ = proto.content_mime_type();
etag_ = proto.etag(); etag_ = proto.etag();
id_ = proto.id(); id_ = proto.id();
...@@ -578,7 +607,7 @@ void GDataFile::ToProto(GDataFileProto* proto) const { ...@@ -578,7 +607,7 @@ void GDataFile::ToProto(GDataFileProto* proto) const {
GDataFileBase::ToProto(proto->mutable_gdata_file_base()); GDataFileBase::ToProto(proto->mutable_gdata_file_base());
proto->set_kind(kind_); proto->set_kind(kind_);
proto->set_thumbnail_url(thumbnail_url_.spec()); proto->set_thumbnail_url(thumbnail_url_.spec());
proto->set_edit_url(edit_url_.spec()); proto->set_alternate_url(alternate_url_.spec());
proto->set_content_mime_type(content_mime_type_); proto->set_content_mime_type(content_mime_type_);
proto->set_etag(etag_); proto->set_etag(etag_);
proto->set_id(id_); proto->set_id(id_);
......
...@@ -101,8 +101,17 @@ class GDataFileBase { ...@@ -101,8 +101,17 @@ class GDataFileBase {
// The content URL is used for downloading regular files as is. // The content URL is used for downloading regular files as is.
const GURL& content_url() const { return content_url_; } const GURL& content_url() const { return content_url_; }
// The self URL is used for removing files and hosted documents. // The edit URL is used for removing files and hosted documents.
const GURL& self_url() const { return self_url_; } const GURL& edit_url() const { return edit_url_; }
// The resource id of the parent folder. This piece of information is needed
// to pair files from change feeds with their directory parents withing the
// existing file system snapshot (GDataRootDirectory::resource_map_).
const std::string& parent_resource_id() const { return parent_resource_id_; }
// True if file was deleted. Used only for instances that are generated from
// delta feeds.
bool is_deleted() const { return deleted_; }
// Returns virtual file path representing this file system entry. This path // Returns virtual file path representing this file system entry. This path
// corresponds to file path expected by public methods of GDataFileSyste // corresponds to file path expected by public methods of GDataFileSyste
...@@ -135,10 +144,12 @@ class GDataFileBase { ...@@ -135,10 +144,12 @@ class GDataFileBase {
// so we can represent them with unique URLs/paths in File API layer. // so we can represent them with unique URLs/paths in File API layer.
// For example, two files in the same directory with the same name "Foo" // For example, two files in the same directory with the same name "Foo"
// will show up in the virtual directory as "Foo" and "Foo (2)". // will show up in the virtual directory as "Foo" and "Foo (2)".
GURL self_url_; GURL edit_url_;
GURL content_url_; GURL content_url_;
GDataDirectory* parent_; GDataDirectory* parent_;
GDataRootDirectory* root_; // Weak pointer to GDataRootDirectory. GDataRootDirectory* root_; // Weak pointer to GDataRootDirectory.
bool deleted_;
std::string parent_resource_id_;
private: private:
DISALLOW_COPY_AND_ASSIGN(GDataFileBase); DISALLOW_COPY_AND_ASSIGN(GDataFileBase);
...@@ -200,7 +211,7 @@ class GDataFile : public GDataFileBase { ...@@ -200,7 +211,7 @@ class GDataFile : public GDataFileBase {
DocumentEntry::EntryKind kind() const { return kind_; } DocumentEntry::EntryKind kind() const { return kind_; }
const GURL& thumbnail_url() const { return thumbnail_url_; } const GURL& thumbnail_url() const { return thumbnail_url_; }
const GURL& edit_url() const { return edit_url_; } const GURL& alternate_url() const { return alternate_url_; }
const std::string& content_mime_type() const { return content_mime_type_; } const std::string& content_mime_type() const { return content_mime_type_; }
const std::string& etag() const { return etag_; } const std::string& etag() const { return etag_; }
const std::string& id() const { return id_; } const std::string& id() const { return id_; }
...@@ -219,7 +230,7 @@ class GDataFile : public GDataFileBase { ...@@ -219,7 +230,7 @@ class GDataFile : public GDataFileBase {
// Content URL for files. // Content URL for files.
DocumentEntry::EntryKind kind_; DocumentEntry::EntryKind kind_;
GURL thumbnail_url_; GURL thumbnail_url_;
GURL edit_url_; GURL alternate_url_;
std::string content_mime_type_; std::string content_mime_type_;
std::string etag_; std::string etag_;
std::string id_; std::string id_;
...@@ -258,6 +269,9 @@ class GDataDirectory : public GDataFileBase { ...@@ -258,6 +269,9 @@ class GDataDirectory : public GDataFileBase {
// the file system. // the file system.
bool TakeFile(GDataFileBase* file); bool TakeFile(GDataFileBase* file);
// Takes over all files from |dir|.
bool TakeOverFiles(GDataDirectory* dir);
// Removes the file from its children list and destroys the file instance. // Removes the file from its children list and destroys the file instance.
bool RemoveFile(GDataFileBase* file); bool RemoveFile(GDataFileBase* file);
......
...@@ -251,9 +251,13 @@ ...@@ -251,9 +251,13 @@
"rel": "http://schemas.google.com/docs/2007/thumbnail", "rel": "http://schemas.google.com/docs/2007/thumbnail",
"type": "image/jpeg" "type": "image/jpeg"
}, { }, {
"href": "https://3_document_self_link", "href": "https://3_document_self_link/document:3_document_resource_id",
"rel": "self", "rel": "self",
"type": "application/atom+xml" "type": "application/atom+xml"
}, {
"href": "https://3_document_self_link/document:3_document_resource_id",
"rel": "edit",
"type": "application/atom+xml"
} ], } ],
"published": { "published": {
"$t": "2011-12-12T23:28:46.686Z" "$t": "2011-12-12T23:28:46.686Z"
......
{
"encoding": "UTF-8",
"feed": {
"author": [ {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "change",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#change"
} ],
"docs$largestChangestamp": {
"value": "16809"
},
"docs$quotaBytesUsedInTrash": {
"$t": "402724784"
},
"entry": [ {
"app$edited": {
"$t": "2011-12-14T00:41:08.287Z",
"xmlns$app": "http://www.w3.org/2007/app"
},
"author": [ {
"email": {
"$t": "entry_tester@testing.com"
},
"name": {
"$t": "entry_tester"
}
} ],
"category": [ {
"label": "viewed",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#viewed"
}, {
"label": "folder",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#folder"
} ],
"content": {
"src": "https://1_folder_content_url",
"type": "application/atom+xml;type=feed"
},
"docs$writersCanInvite": {
"value": "true"
},
"gd$etag": "\"HhMOFgcNHSt7ImBr\"",
"gd$feedLink": [ {
"href": "https://1_folder_feed_linkurl",
"rel": "http://schemas.google.com/acl/2007#accessControlList"
} ],
"gd$lastModifiedBy": {
"email": {
"$t": "tester@testing.com"
},
"name": {
"$t": "tester"
}
},
"gd$lastViewed": {
"$t": "2011-11-02T04:37:38.469Z"
},
"gd$quotaBytesUsed": {
"$t": "0"
},
"gd$resourceId": {
"$t": "folder:1_folder_resource_id"
},
"id": {
"$t": "https://1_folder_id"
},
"link": [ {
"href": "https://sub_dir_folder_2_self_link/folder:sub_dir_folder_2_self_link",
"rel": "http://schemas.google.com/docs/2007#parent",
"title": "Directory 2",
"type": "application/atom+xml"
}, {
"href": "https://1_folder_alternate_link",
"rel": "alternate",
"type": "text/html"
}, {
"href": "https://1_folder_resumable_create_media_link",
"rel": "http://schemas.google.com/g/2005#resumable-create-media",
"type": "application/atom+xml"
}, {
"href": "https://dir_1_self_link/folder:1_folder_resource_id",
"rel": "self",
"type": "application/atom+xml"
}, {
"href": "https://dir_1_self_link/folder:1_folder_resource_id",
"rel": "edit",
"type": "application/atom+xml"
} ],
"published": {
"$t": "2010-11-07T05:03:54.719Z"
},
"title": {
"$t": "Directory 1"
},
"updated": {
"$t": "2011-04-01T18:34:08.234Z"
}
}, {
"app$edited": {
"$t": "2011-12-14T00:41:08.287Z",
"xmlns$app": "http://www.w3.org/2007/app"
},
"author": [ {
"email": {
"$t": "entry_tester@testing.com"
},
"name": {
"$t": "entry_tester"
}
} ],
"category": [ {
"label": "viewed",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#viewed"
}, {
"label": "folder",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#folder"
} ],
"content": {
"src": "https://1_folder_content_url",
"type": "application/atom+xml;type=feed"
},
"docs$writersCanInvite": {
"value": "true"
},
"gd$etag": "\"HhMOFgcNHSt7ImBr\"",
"gd$feedLink": [ {
"href": "https://1_folder_feed_linkurl",
"rel": "http://schemas.google.com/acl/2007#accessControlList"
} ],
"gd$lastModifiedBy": {
"email": {
"$t": "tester@testing.com"
},
"name": {
"$t": "tester"
}
},
"gd$lastViewed": {
"$t": "2011-11-02T04:37:38.469Z"
},
"gd$quotaBytesUsed": {
"$t": "0"
},
"gd$resourceId": {
"$t": "folder:sub_dir_folder_2_self_link"
},
"id": {
"$t": "https://sub_dir_folder_2_self_link"
},
"link": [ {
"href": "https://1_folder_alternate_link",
"rel": "alternate",
"type": "text/html"
}, {
"href": "https://1_folder_resumable_create_media_link",
"rel": "http://schemas.google.com/g/2005#resumable-create-media",
"type": "application/atom+xml"
}, {
"href": "https://sub_dir_folder_2_self_link/folder:sub_dir_folder_2_self_link",
"rel": "self",
"type": "application/atom+xml"
}, {
"href": "https://sub_dir_folder_2_self_link/folder:sub_dir_folder_2_self_link",
"rel": "edit",
"type": "application/atom+xml"
}, {
"href": "https://slash_dir_self_link",
"rel": "http://schemas.google.com/docs/2007#parent",
"type": "application/atom+xml"
} ],
"published": {
"$t": "2010-11-07T05:03:54.719Z"
},
"title": {
"$t": "Directory 2"
},
"updated": {
"$t": "2011-04-01T18:34:08.234Z"
}
} ],
"gd$etag": "W/\"DkIMQHs-eSt7ImA9WhVXEUw.\"",
"gd$quotaBytesTotal": {
"$t": "215822106624"
},
"gd$quotaBytesUsed": {
"$t": "416375123"
},
"id": {
"$t": "https://docs.google.com/feeds/default/private/changes"
},
"link": [ {
"href": "https://docs.google.com/feeds/default/private/changes",
"rel": "http://schemas.google.com/g/2005#feed",
"type": "application/atom+xml"
}, {
"href": "https://docs.google.com/feeds/default/private/changes?alt=json&start-index=16804&max-results=1000",
"rel": "self",
"type": "application/atom+xml"
} ],
"openSearch$startIndex": {
"$t": "16804"
},
"openSearch$totalResults": {
"$t": "16808"
},
"title": {
"$t": "Changed Documents - tester@test.com"
},
"updated": {
"$t": "2012-04-11T03:23:01.551Z"
},
"xmlns": "http://www.w3.org/2005/Atom",
"xmlns$docs": "http://schemas.google.com/docs/2007",
"xmlns$gd": "http://schemas.google.com/g/2005",
"xmlns$openSearch": "http://a9.com/-/spec/opensearch/1.1/"
},
"version": "1.0"
}
{
"encoding": "UTF-8",
"feed": {
"author": [ {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "change",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#change"
} ],
"docs$largestChangestamp": {
"value": "16730"
},
"docs$quotaBytesUsedInTrash": {
"$t": "402724784"
},
"entry": [ {
"app$edited": {
"$t": "2012-04-10T22:50:55.965Z",
"xmlns$app": "http://www.w3.org/2007/app"
},
"author": [ {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "document",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#document"
}, {
"label": "viewed",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#viewed"
}, {
"label": "modified-by-me",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#modified-by-me"
} ],
"content": {
"src": "https://content_url",
"type": "text/html"
},
"docs$changestamp": {
"value": "16683"
},
"docs$modifiedByMeDate": {
"$t": "2012-04-10T22:50:55.797Z"
},
"docs$writersCanInvite": {
"value": "true"
},
"gd$etag": "\"WVAJThBcDyt7ImBk\"",
"gd$feedLink": [ {
"href": "https://feedLink",
"rel": "http://schemas.google.com/docs/2007/revisions"
} ],
"gd$lastModifiedBy": {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
},
"gd$lastViewed": {
"$t": "2012-04-10T22:50:55.797Z"
},
"gd$quotaBytesUsed": {
"$t": "0"
},
"gd$resourceId": {
"$t": "document:added_in_root_id"
},
"id": {
"$t": "https://document%3Aadded_in_root_id"
},
"link": [ {
"href": "https://dir_1_self_link/folder:1_folder_resource_id",
"rel": "http://schemas.google.com/docs/2007#parent",
"title": "Directory 1",
"type": "application/atom+xml"
}, {
"href": "https://alternate/document%3Aadded_in_root_id/edit",
"rel": "alternate",
"type": "text/html"
}, {
"href": "https://added_in_root.png",
"rel": "http://schemas.google.com/docs/2007#icon",
"type": "image/png"
}, {
"href": "https://",
"rel": "http://schemas.google.com/g/2005#resumable-edit-media",
"type": "application/atom+xml"
}, {
"href": "https://edit_url/document%3Aadded_in_root_id",
"rel": "edit",
"type": "application/atom+xml"
}, {
"href": "https://edit-media/document%3Aadded_in_root_id",
"rel": "edit-media",
"type": "text/html"
}, {
"href": "https://changes/16683",
"rel": "self",
"type": "application/atom+xml"
} ],
"published": {
"$t": "2012-04-10T22:50:53.237Z"
},
"title": {
"$t": "Added file"
},
"updated": {
"$t": "2012-04-10T22:50:55.797Z"
}
}, {
"app$edited": {
"$t": "2011-12-14T00:41:08.287Z",
"xmlns$app": "http://www.w3.org/2007/app"
},
"author": [ {
"email": {
"$t": "entry_tester@testing.com"
},
"name": {
"$t": "entry_tester"
}
} ],
"category": [ {
"label": "viewed",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#viewed"
}, {
"label": "folder",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#folder"
} ],
"content": {
"src": "https://1_folder_content_url",
"type": "application/atom+xml;type=feed"
},
"docs$writersCanInvite": {
"value": "true"
},
"gd$etag": "\"HhMOFgcNHSt7ImBr\"",
"gd$feedLink": [ {
"href": "https://1_folder_feed_linkurl",
"rel": "http://schemas.google.com/acl/2007#accessControlList"
} ],
"gd$lastModifiedBy": {
"email": {
"$t": "tester@testing.com"
},
"name": {
"$t": "tester"
}
},
"gd$lastViewed": {
"$t": "2011-11-02T04:37:38.469Z"
},
"gd$quotaBytesUsed": {
"$t": "0"
},
"gd$resourceId": {
"$t": "folder:1_folder_resource_id"
},
"id": {
"$t": "https://1_folder_id"
},
"link": [ {
"href": "https://1_folder_alternate_link",
"rel": "alternate",
"type": "text/html"
}, {
"href": "https://1_folder_resumable_create_media_link",
"rel": "http://schemas.google.com/g/2005#resumable-create-media",
"type": "application/atom+xml"
}, {
"href": "https://dir_1_self_link/folder:1_folder_resource_id",
"rel": "self",
"type": "application/atom+xml"
}, {
"href": "https://dir_1_self_link/folder:1_folder_resource_id",
"rel": "edit",
"type": "application/atom+xml"
} ],
"published": {
"$t": "2010-11-07T05:03:54.719Z"
},
"title": {
"$t": "Directory 1"
},
"updated": {
"$t": "2011-04-01T18:34:08.234Z"
}
} ],
"gd$etag": "W/\"AkYGSHc8eyt7ImA9WhVXEU0.\"",
"gd$quotaBytesTotal": {
"$t": "215822106624"
},
"gd$quotaBytesUsed": {
"$t": "416375123"
},
"id": {
"$t": "https://docs.google.com/feeds/default/private/changes"
},
"link": [ {
"href": "https://docs.google.com/feeds/default/private/changes",
"rel": "http://schemas.google.com/g/2005#feed",
"type": "application/atom+xml"
}, {
"href": "https://docs.google.com/feeds/default/private/changes?alt=json&start-index=16718&max-results=1000",
"rel": "self",
"type": "application/atom+xml"
} ],
"openSearch$startIndex": {
"$t": "16718"
},
"openSearch$totalResults": {
"$t": "16730"
},
"title": {
"$t": "Changed Documents - tester@test.com"
},
"updated": {
"$t": "2012-04-11T01:35:29.973Z"
},
"xmlns": "http://www.w3.org/2005/Atom",
"xmlns$docs": "http://schemas.google.com/docs/2007",
"xmlns$gd": "http://schemas.google.com/g/2005",
"xmlns$openSearch": "http://a9.com/-/spec/opensearch/1.1/"
},
"version": "1.0"
}
{
"encoding": "UTF-8",
"feed": {
"author": [ {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "change",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#change"
} ],
"docs$largestChangestamp": {
"value": "16730"
},
"docs$quotaBytesUsedInTrash": {
"$t": "402724784"
},
"entry": [ {
"app$edited": {
"$t": "2012-04-10T22:50:55.965Z",
"xmlns$app": "http://www.w3.org/2007/app"
},
"author": [ {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "document",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#document"
}, {
"label": "viewed",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#viewed"
}, {
"label": "modified-by-me",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#modified-by-me"
} ],
"content": {
"src": "https://content_url",
"type": "text/html"
},
"docs$changestamp": {
"value": "16683"
},
"docs$modifiedByMeDate": {
"$t": "2012-04-10T22:50:55.797Z"
},
"docs$writersCanInvite": {
"value": "true"
},
"gd$etag": "\"WVAJThBcDyt7ImBk\"",
"gd$feedLink": [ {
"href": "https://feedLink",
"rel": "http://schemas.google.com/docs/2007/revisions"
} ],
"gd$lastModifiedBy": {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
},
"gd$lastViewed": {
"$t": "2012-04-10T22:50:55.797Z"
},
"gd$quotaBytesUsed": {
"$t": "0"
},
"gd$resourceId": {
"$t": "document:file_added_in_new_dir_id"
},
"id": {
"$t": "https://document%3Afile_added_in_new_dir_id"
},
"link": [ {
"href": "https://new_dir_self_link/folder:new_folder_resource_id",
"rel": "http://schemas.google.com/docs/2007#parent",
"title": "New Directory",
"type": "application/atom+xml"
}, {
"href": "https://alternate/document%3Afile_added_in_new_dir_id/edit",
"rel": "alternate",
"type": "text/html"
}, {
"href": "https://added_in_root.png",
"rel": "http://schemas.google.com/docs/2007#icon",
"type": "image/png"
}, {
"href": "https://",
"rel": "http://schemas.google.com/g/2005#resumable-edit-media",
"type": "application/atom+xml"
}, {
"href": "https://edit_url/document%3Afile_added_in_new_dir_id",
"rel": "edit",
"type": "application/atom+xml"
}, {
"href": "https://edit-media/document%3Afile_added_in_new_dir_id",
"rel": "edit-media",
"type": "text/html"
}, {
"href": "https://changes/16683",
"rel": "self",
"type": "application/atom+xml"
} ],
"published": {
"$t": "2012-04-10T22:50:53.237Z"
},
"title": {
"$t": "File in new dir"
},
"updated": {
"$t": "2012-04-10T22:50:55.797Z"
}
}, {
"app$edited": {
"$t": "2011-12-14T00:41:08.287Z",
"xmlns$app": "http://www.w3.org/2007/app"
},
"author": [ {
"email": {
"$t": "entry_tester@testing.com"
},
"name": {
"$t": "entry_tester"
}
} ],
"category": [ {
"label": "viewed",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#viewed"
}, {
"label": "folder",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#folder"
} ],
"content": {
"src": "https://1_folder_content_url",
"type": "application/atom+xml;type=feed"
},
"docs$writersCanInvite": {
"value": "true"
},
"gd$etag": "\"HhMOFgcNHSt7ImBr\"",
"gd$feedLink": [ {
"href": "https://1_folder_feed_linkurl",
"rel": "http://schemas.google.com/acl/2007#accessControlList"
} ],
"gd$lastModifiedBy": {
"email": {
"$t": "tester@testing.com"
},
"name": {
"$t": "tester"
}
},
"gd$lastViewed": {
"$t": "2011-11-02T04:37:38.469Z"
},
"gd$quotaBytesUsed": {
"$t": "0"
},
"gd$resourceId": {
"$t": "folder:new_folder_resource_id"
},
"id": {
"$t": "https://new_folder_id"
},
"link": [ {
"href": "https://1_folder_alternate_link",
"rel": "alternate",
"type": "text/html"
}, {
"href": "https://1_folder_resumable_create_media_link",
"rel": "http://schemas.google.com/g/2005#resumable-create-media",
"type": "application/atom+xml"
}, {
"href": "https://new_dir_self_link/folder:new_folder_resource_id",
"rel": "self",
"type": "application/atom+xml"
}, {
"href": "https://new_dir_self_link/folder:new_folder_resource_id",
"rel": "edit",
"type": "application/atom+xml"
} ],
"published": {
"$t": "2010-11-07T05:03:54.719Z"
},
"title": {
"$t": "New Directory"
},
"updated": {
"$t": "2011-04-01T18:34:08.234Z"
}
} ],
"gd$etag": "W/\"AkYGSHc8eyt7ImA9WhVXEU0.\"",
"gd$quotaBytesTotal": {
"$t": "215822106624"
},
"gd$quotaBytesUsed": {
"$t": "416375123"
},
"id": {
"$t": "https://docs.google.com/feeds/default/private/changes"
},
"link": [ {
"href": "https://docs.google.com/feeds/default/private/changes",
"rel": "http://schemas.google.com/g/2005#feed",
"type": "application/atom+xml"
}, {
"href": "https://docs.google.com/feeds/default/private/changes?alt=json&start-index=16718&max-results=1000",
"rel": "self",
"type": "application/atom+xml"
} ],
"openSearch$startIndex": {
"$t": "16718"
},
"openSearch$totalResults": {
"$t": "16730"
},
"title": {
"$t": "Changed Documents - tester@test.com"
},
"updated": {
"$t": "2012-04-11T01:35:29.973Z"
},
"xmlns": "http://www.w3.org/2005/Atom",
"xmlns$docs": "http://schemas.google.com/docs/2007",
"xmlns$gd": "http://schemas.google.com/g/2005",
"xmlns$openSearch": "http://a9.com/-/spec/opensearch/1.1/"
},
"version": "1.0"
}
{
"encoding": "UTF-8",
"feed": {
"author": [ {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "change",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#change"
} ],
"docs$largestChangestamp": {
"value": "16683"
},
"docs$quotaBytesUsedInTrash": {
"$t": "402724784"
},
"entry": [ {
"app$edited": {
"$t": "2012-04-10T22:50:55.965Z",
"xmlns$app": "http://www.w3.org/2007/app"
},
"author": [ {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "document",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#document"
}, {
"label": "viewed",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#viewed"
}, {
"label": "modified-by-me",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#modified-by-me"
} ],
"content": {
"src": "https://content_url",
"type": "text/html"
},
"docs$changestamp": {
"value": "16683"
},
"docs$modifiedByMeDate": {
"$t": "2012-04-10T22:50:55.797Z"
},
"docs$writersCanInvite": {
"value": "true"
},
"gd$etag": "\"WVAJThBcDyt7ImBk\"",
"gd$feedLink": [ {
"href": "https://feedLink",
"rel": "http://schemas.google.com/docs/2007/revisions"
} ],
"gd$lastModifiedBy": {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
},
"gd$lastViewed": {
"$t": "2012-04-10T22:50:55.797Z"
},
"gd$quotaBytesUsed": {
"$t": "0"
},
"gd$resourceId": {
"$t": "document:added_in_root_id"
},
"id": {
"$t": "https://document%3Aadded_in_root_id"
},
"link": [ {
"href": "https://alternate/document%3Aadded_in_root_id/edit",
"rel": "alternate",
"type": "text/html"
}, {
"href": "https://added_in_root.png",
"rel": "http://schemas.google.com/docs/2007#icon",
"type": "image/png"
}, {
"href": "https://",
"rel": "http://schemas.google.com/g/2005#resumable-edit-media",
"type": "application/atom+xml"
}, {
"href": "https://edit_url/document%3Aadded_in_root_id",
"rel": "edit",
"type": "application/atom+xml"
}, {
"href": "https://edit-media/document%3Aadded_in_root_id",
"rel": "edit-media",
"type": "text/html"
}, {
"href": "https://changes/16683",
"rel": "self",
"type": "application/atom+xml"
} ],
"published": {
"$t": "2012-04-10T22:50:53.237Z"
},
"title": {
"$t": "Added file"
},
"updated": {
"$t": "2012-04-10T22:50:55.797Z"
}
} ],
"gd$etag": "W/\"XXXXXXXXXXX.\"",
"gd$quotaBytesTotal": {
"$t": "215822106624"
},
"gd$quotaBytesUsed": {
"$t": "416375123"
},
"id": {
"$t": "https://docs.google.com/feeds/default/private/changes"
},
"link": [ {
"href": "https://docs.google.com/feeds/default/private/changes",
"rel": "http://schemas.google.com/g/2005#feed",
"type": "application/atom+xml"
}, {
"href": "https://docs.google.com/feeds/default/private/changes?alt=json&start-index=1&max-results=1000",
"rel": "self",
"type": "application/atom+xml"
} ],
"openSearch$startIndex": {
"$t": "1"
},
"openSearch$totalResults": {
"$t": "16683"
},
"title": {
"$t": "Changed Documents - tester@test.com"
},
"updated": {
"$t": "2012-04-10T22:50:55.797Z"
},
"xmlns": "http://www.w3.org/2005/Atom",
"xmlns$docs": "http://schemas.google.com/docs/2007",
"xmlns$gd": "http://schemas.google.com/g/2005",
"xmlns$openSearch": "http://a9.com/-/spec/opensearch/1.1/"
},
"version": "1.0"
}
{
"encoding": "UTF-8",
"feed": {
"author": [ {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "change",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#change"
} ],
"docs$largestChangestamp": {
"value": "16770"
},
"docs$quotaBytesUsedInTrash": {
"$t": "402724784"
},
"entry": [ {
"app$edited": {
"$t": "2012-04-10T22:50:55.965Z",
"xmlns$app": "http://www.w3.org/2007/app"
},
"author": [ {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "document",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#document"
}, {
"label": "viewed",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#viewed"
}, {
"label": "modified-by-me",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#modified-by-me"
} ],
"content": {
"src": "https://content_url",
"type": "text/html"
},
"docs$changestamp": {
"value": "16683"
},
"docs$modifiedByMeDate": {
"$t": "2012-04-10T22:50:55.797Z"
},
"docs$writersCanInvite": {
"value": "true"
},
"gd$deleted": {
},
"gd$etag": "\"WVAJThBcDyt7ImBk\"",
"gd$feedLink": [ {
"href": "https://feedLink",
"rel": "http://schemas.google.com/docs/2007/revisions"
} ],
"gd$lastModifiedBy": {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
},
"gd$lastViewed": {
"$t": "2012-04-10T22:50:55.797Z"
},
"gd$quotaBytesUsed": {
"$t": "0"
},
"gd$resourceId": {
"$t": "document:added_in_root_id"
},
"id": {
"$t": "https://document%3Aadded_in_root_id"
},
"link": [ {
"href": "https://dir_1_self_link/folder:1_folder_resource_id",
"rel": "http://schemas.google.com/docs/2007#parent",
"title": "Directory 1",
"type": "application/atom+xml"
}, {
"href": "https://alternate/document%3Aadded_in_root_id/edit",
"rel": "alternate",
"type": "text/html"
}, {
"href": "https://added_in_root.png",
"rel": "http://schemas.google.com/docs/2007#icon",
"type": "image/png"
}, {
"href": "https://",
"rel": "http://schemas.google.com/g/2005#resumable-edit-media",
"type": "application/atom+xml"
}, {
"href": "https://edit_url/document%3Aadded_in_root_id",
"rel": "edit",
"type": "application/atom+xml"
}, {
"href": "https://edit-media/document%3Aadded_in_root_id",
"rel": "edit-media",
"type": "text/html"
}, {
"href": "https://changes/16683",
"rel": "self",
"type": "application/atom+xml"
} ],
"published": {
"$t": "2012-04-10T22:50:53.237Z"
},
"title": {
"$t": "Added file"
},
"updated": {
"$t": "2012-04-10T22:50:55.797Z"
}
} ],
"gd$etag": "W/\"AkYGR3w7cSt7ImA9WhVXEU0.\"",
"gd$quotaBytesTotal": {
"$t": "215822106624"
},
"gd$quotaBytesUsed": {
"$t": "416375123"
},
"id": {
"$t": "https://docs.google.com/feeds/default/private/changes"
},
"link": [ {
"href": "https://docs.google.com/feeds/default/private/changes",
"rel": "http://schemas.google.com/g/2005#feed",
"type": "application/atom+xml"
}, {
"href": "https://docs.google.com/feeds/default/private/changes?alt=json&start-index=16770&max-results=1000",
"rel": "self",
"type": "application/atom+xml"
} ],
"openSearch$startIndex": {
"$t": "16770"
},
"openSearch$totalResults": {
"$t": "16770"
},
"title": {
"$t": "Changed Documents - tester@test.com"
},
"updated": {
"$t": "2012-04-11T01:35:26.209Z"
},
"xmlns": "http://www.w3.org/2005/Atom",
"xmlns$docs": "http://schemas.google.com/docs/2007",
"xmlns$gd": "http://schemas.google.com/g/2005",
"xmlns$openSearch": "http://a9.com/-/spec/opensearch/1.1/"
},
"version": "1.0"
}
{
"encoding": "UTF-8",
"feed": {
"author": [ {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "change",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#change"
} ],
"docs$largestChangestamp": {
"value": "16687"
},
"docs$quotaBytesUsedInTrash": {
"$t": "402724784"
},
"entry": [ {
"app$edited": {
"$t": "2012-04-10T22:50:55.965Z",
"xmlns$app": "http://www.w3.org/2007/app"
},
"author": [ {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "document",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#document"
}, {
"label": "viewed",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#viewed"
}, {
"label": "modified-by-me",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#modified-by-me"
} ],
"content": {
"src": "https://content_url",
"type": "text/html"
},
"docs$changestamp": {
"value": "16683"
},
"docs$modifiedByMeDate": {
"$t": "2012-04-10T22:50:55.797Z"
},
"docs$writersCanInvite": {
"value": "true"
},
"gd$deleted": {
},
"gd$etag": "\"WVAJThBcDyt7ImBk\"",
"gd$feedLink": [ {
"href": "https://feedLink",
"rel": "http://schemas.google.com/docs/2007/revisions"
} ],
"gd$lastModifiedBy": {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
},
"gd$lastViewed": {
"$t": "2012-04-10T22:50:55.797Z"
},
"gd$quotaBytesUsed": {
"$t": "0"
},
"gd$resourceId": {
"$t": "document:added_in_root_id"
},
"id": {
"$t": "https://document%3Aadded_in_root_id"
},
"link": [ {
"href": "https://alternate/document%3Aadded_in_root_id/edit",
"rel": "alternate",
"type": "text/html"
}, {
"href": "https://added_in_root.png",
"rel": "http://schemas.google.com/docs/2007#icon",
"type": "image/png"
}, {
"href": "https://",
"rel": "http://schemas.google.com/g/2005#resumable-edit-media",
"type": "application/atom+xml"
}, {
"href": "https://edit_url/document%3Aadded_in_root_id",
"rel": "edit",
"type": "application/atom+xml"
}, {
"href": "https://edit-media/document%3Aadded_in_root_id",
"rel": "edit-media",
"type": "text/html"
}, {
"href": "https://changes/16683",
"rel": "self",
"type": "application/atom+xml"
} ],
"published": {
"$t": "2012-04-10T22:50:53.237Z"
},
"title": {
"$t": "Added file"
},
"updated": {
"$t": "2012-04-10T22:50:55.797Z"
}
} ],
"gd$etag": "W/\"AkUBR3w7eit7ImA9WhVXEEQ.\"",
"gd$quotaBytesTotal": {
"$t": "215822106624"
},
"gd$quotaBytesUsed": {
"$t": "416375123"
},
"id": {
"$t": "https://docs.google.com/feeds/default/private/changes"
},
"link": [ {
"href": "https://docs.google.com/feeds/default/private/changes",
"rel": "http://schemas.google.com/g/2005#feed",
"type": "application/atom+xml"
}, {
"href": "https://docs.google.com/feeds/default/private/changes?alt=json&start-index=16686&max-results=1000",
"rel": "self",
"type": "application/atom+xml"
} ],
"openSearch$startIndex": {
"$t": "16686"
},
"openSearch$totalResults": {
"$t": "16687"
},
"title": {
"$t": "Changed Documents - tester@test.com"
},
"updated": {
"$t": "2012-04-10T22:50:56.202Z"
},
"xmlns": "http://www.w3.org/2005/Atom",
"xmlns$docs": "http://schemas.google.com/docs/2007",
"xmlns$gd": "http://schemas.google.com/g/2005",
"xmlns$openSearch": "http://a9.com/-/spec/opensearch/1.1/"
},
"version": "1.0"
}
{
"encoding": "UTF-8",
"feed": {
"author": [ {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "change",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#change"
} ],
"docs$largestChangestamp": {
"value": "16815"
},
"docs$quotaBytesUsedInTrash": {
"$t": "402724784"
},
"entry": [ {
"app$edited": {
"$t": "2011-12-14T00:40:57.162Z",
"xmlns$app": "http://www.w3.org/2007/app"
},
"author": [ {
"email": {
"$t": "tester@testing.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "audio/mpeg",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#file"
} ],
"content": {
"src": "https://file_content_url/",
"type": "audio/mpeg"
},
"docs$filename": {
"$t": "SubDirectory File 1.txt"
},
"docs$md5Checksum": {
"$t": "3b4382ebefec6e743578c76bbd0575ce"
},
"docs$size": {
"$t": "892721"
},
"docs$suggestedFilename": {
"$t": "SubDirectory File 1.txt"
},
"docs$writersCanInvite": {
"value": "true"
},
"gd$etag": "\"HhMOFgxXHit7ImBr\"",
"gd$feedLink": [ {
"href": "https://file_feed_link_url",
"rel": "http://schemas.google.com/docs/2007/revisions"
} ],
"gd$lastModifiedBy": {
"email": {
"$t": "tester@testing.com"
},
"name": {
"$t": "tester"
}
},
"gd$quotaBytesUsed": {
"$t": "892721"
},
"gd$resourceId": {
"$t": "file:2_file_resouce_id"
},
"id": {
"$t": "2_file_id"
},
"link": [ {
"href": "https://file_link_alternate",
"rel": "alternate",
"type": "text/html"
}, {
"href": "https://file_link_resumable_edit_media",
"rel": "http://schemas.google.com/g/2005#resumable-edit-media",
"type": "application/atom+xml"
}, {
"href": "https://dir1_file_link_self/file:2_file_resouce_id",
"rel": "self",
"type": "application/atom+xml"
}, {
"href": "https://dir1_file_link_self/file:2_file_resouce_id",
"rel": "edit",
"type": "application/atom+xml"
}, {
"href": "https://file_edit_media",
"rel": "edit-media",
"type": "audio/mpeg"
} ],
"published": {
"$t": "2011-12-14T00:40:47.330Z"
},
"title": {
"$t": "SubDirectory File 1.txt"
},
"updated": {
"$t": "2011-12-14T00:40:47.330Z"
}
}, {
"app$edited": {
"$t": "2011-12-14T00:41:08.287Z",
"xmlns$app": "http://www.w3.org/2007/app"
},
"author": [ {
"email": {
"$t": "entry_tester@testing.com"
},
"name": {
"$t": "entry_tester"
}
} ],
"category": [ {
"label": "viewed",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#viewed"
}, {
"label": "folder",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#folder"
} ],
"content": {
"src": "https://1_folder_content_url",
"type": "application/atom+xml;type=feed"
},
"docs$writersCanInvite": {
"value": "true"
},
"gd$etag": "\"HhMOFgcNHSt7ImBr\"",
"gd$feedLink": [ {
"href": "https://1_folder_feed_linkurl",
"rel": "http://schemas.google.com/acl/2007#accessControlList"
} ],
"gd$lastModifiedBy": {
"email": {
"$t": "tester@testing.com"
},
"name": {
"$t": "tester"
}
},
"gd$lastViewed": {
"$t": "2011-11-02T04:37:38.469Z"
},
"gd$quotaBytesUsed": {
"$t": "0"
},
"gd$resourceId": {
"$t": "folder:1_folder_resource_id"
},
"id": {
"$t": "https://1_folder_id"
},
"link": [ {
"href": "https://1_folder_alternate_link",
"rel": "alternate",
"type": "text/html"
}, {
"href": "https://1_folder_resumable_create_media_link",
"rel": "http://schemas.google.com/g/2005#resumable-create-media",
"type": "application/atom+xml"
}, {
"href": "https://dir_1_self_link/folder:1_folder_resource_id",
"rel": "self",
"type": "application/atom+xml"
}, {
"href": "https://dir_1_self_link/folder:1_folder_resource_id",
"rel": "edit",
"type": "application/atom+xml"
} ],
"published": {
"$t": "2010-11-07T05:03:54.719Z"
},
"title": {
"$t": "Directory 1"
},
"updated": {
"$t": "2011-04-01T18:34:08.234Z"
}
} ],
"gd$etag": "W/\"Dk8BQXo4fit7ImA9WhVXEUw.\"",
"gd$quotaBytesTotal": {
"$t": "215822106624"
},
"gd$quotaBytesUsed": {
"$t": "416375123"
},
"id": {
"$t": "https://docs.google.com/feeds/default/private/changes"
},
"link": [ {
"href": "https://docs.google.com/feeds/default/private/changes",
"rel": "http://schemas.google.com/g/2005#feed",
"type": "application/atom+xml"
}, {
"href": "https://docs.google.com/feeds/default/private/changes?alt=json&start-index=16810&max-results=1000",
"rel": "self",
"type": "application/atom+xml"
} ],
"openSearch$startIndex": {
"$t": "16810"
},
"openSearch$totalResults": {
"$t": "16815"
},
"title": {
"$t": "Changed Documents - tester@test.com"
},
"updated": {
"$t": "2012-04-11T03:27:30.436Z"
},
"xmlns": "http://www.w3.org/2005/Atom",
"xmlns$docs": "http://schemas.google.com/docs/2007",
"xmlns$gd": "http://schemas.google.com/g/2005",
"xmlns$openSearch": "http://a9.com/-/spec/opensearch/1.1/"
},
"version": "1.0"
}
{
"encoding": "UTF-8",
"feed": {
"author": [ {
"email": {
"$t": "tester@test.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "change",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#change"
} ],
"docs$largestChangestamp": {
"value": "16767"
},
"docs$quotaBytesUsedInTrash": {
"$t": "402724784"
},
"entry": [ {
"app$edited": {
"$t": "2011-12-14T00:41:08.287Z",
"xmlns$app": "http://www.w3.org/2007/app"
},
"author": [ {
"email": {
"$t": "entry_tester@testing.com"
},
"name": {
"$t": "entry_tester"
}
} ],
"category": [ {
"label": "viewed",
"scheme": "http://schemas.google.com/g/2005/labels",
"term": "http://schemas.google.com/g/2005/labels#viewed"
}, {
"label": "folder",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#folder"
} ],
"content": {
"src": "https://1_folder_content_url",
"type": "application/atom+xml;type=feed"
},
"docs$writersCanInvite": {
"value": "true"
},
"gd$etag": "\"HhMOFgcNHSt7ImBr\"",
"gd$feedLink": [ {
"href": "https://1_folder_feed_linkurl",
"rel": "http://schemas.google.com/acl/2007#accessControlList"
} ],
"gd$lastModifiedBy": {
"email": {
"$t": "tester@testing.com"
},
"name": {
"$t": "tester"
}
},
"gd$lastViewed": {
"$t": "2011-11-02T04:37:38.469Z"
},
"gd$quotaBytesUsed": {
"$t": "0"
},
"gd$resourceId": {
"$t": "folder:1_folder_resource_id"
},
"id": {
"$t": "https://1_folder_id"
},
"link": [ {
"href": "https://1_folder_alternate_link",
"rel": "alternate",
"type": "text/html"
}, {
"href": "https://1_folder_resumable_create_media_link",
"rel": "http://schemas.google.com/g/2005#resumable-create-media",
"type": "application/atom+xml"
}, {
"href": "https://dir_1_self_link/folder:1_folder_resource_id",
"rel": "self",
"type": "application/atom+xml"
}, {
"href": "https://dir_1_self_link/folder:1_folder_resource_id",
"rel": "edit",
"type": "application/atom+xml"
} ],
"published": {
"$t": "2010-11-07T05:03:54.719Z"
},
"title": {
"$t": "Directory 1"
},
"updated": {
"$t": "2011-04-01T18:34:08.234Z"
}
}, {
"app$edited": {
"$t": "2011-12-14T00:40:57.162Z",
"xmlns$app": "http://www.w3.org/2007/app"
},
"author": [ {
"email": {
"$t": "tester@testing.com"
},
"name": {
"$t": "tester"
}
} ],
"category": [ {
"label": "audio/mpeg",
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/docs/2007#file"
} ],
"content": {
"src": "https://file_content_url/",
"type": "audio/mpeg"
},
"docs$filename": {
"$t": "SubDirectory File 1.txt"
},
"docs$md5Checksum": {
"$t": "3b4382ebefec6e743578c76bbd0575ce"
},
"docs$size": {
"$t": "892721"
},
"docs$suggestedFilename": {
"$t": "SubDirectory File 1.txt"
},
"docs$writersCanInvite": {
"value": "true"
},
"gd$etag": "\"HhMOFgxXHit7ImBr\"",
"gd$feedLink": [ {
"href": "https://file_feed_link_url",
"rel": "http://schemas.google.com/docs/2007/revisions"
} ],
"gd$lastModifiedBy": {
"email": {
"$t": "tester@testing.com"
},
"name": {
"$t": "tester"
}
},
"gd$quotaBytesUsed": {
"$t": "892721"
},
"gd$resourceId": {
"$t": "file:2_file_resouce_id"
},
"id": {
"$t": "2_file_id"
},
"link": [ {
"href": "https://file_link_alternate",
"rel": "alternate",
"type": "text/html"
}, {
"href": "https://file_link_resumable_edit_media",
"rel": "http://schemas.google.com/g/2005#resumable-edit-media",
"type": "application/atom+xml"
}, {
"href": "https://dir1_file_link_self/file:2_file_resouce_id",
"rel": "self",
"type": "application/atom+xml"
}, {
"href": "https://dir_1_self_link/folder:1_folder_resource_id",
"rel": "http://schemas.google.com/docs/2007#parent",
"type": "application/atom+xml"
}, {
"href": "https://dir1_file_link_self/file:2_file_resouce_id",
"rel": "edit",
"type": "application/atom+xml"
}, {
"href": "https://file_edit_media",
"rel": "edit-media",
"type": "audio/mpeg"
} ],
"published": {
"$t": "2011-12-14T00:40:47.330Z"
},
"title": {
"$t": "New SubDirectory File 1.txt"
},
"updated": {
"$t": "2011-12-14T00:40:47.330Z"
}
} ],
"gd$etag": "W/\"CEYAQXc4eCt7ImA9WhVXEUw.\"",
"gd$quotaBytesTotal": {
"$t": "215822106624"
},
"gd$quotaBytesUsed": {
"$t": "416375123"
},
"id": {
"$t": "https://docs.google.com/feeds/default/private/changes"
},
"link": [ {
"href": "https://docs.google.com/feeds/default/private/changes",
"rel": "http://schemas.google.com/g/2005#feed",
"type": "application/atom+xml"
}, {
"href": "https://docs.google.com/feeds/default/private/changes?alt=json&start-index=16766&max-results=1000",
"rel": "self",
"type": "application/atom+xml"
} ],
"openSearch$startIndex": {
"$t": "16766"
},
"openSearch$totalResults": {
"$t": "16767"
},
"title": {
"$t": "Changed Documents - tester@test.com"
},
"updated": {
"$t": "2012-04-11T02:42:20.930Z"
},
"xmlns": "http://www.w3.org/2005/Atom",
"xmlns$docs": "http://schemas.google.com/docs/2007",
"xmlns$gd": "http://schemas.google.com/g/2005",
"xmlns$openSearch": "http://a9.com/-/spec/opensearch/1.1/"
},
"version": "1.0"
}
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