blob: d2fe9fae5a7e2bc9ffa5a50341ba03e68dfd10ef [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "google_apis/drive/drive_api_parser.h"
#include <stddef.h>
#include <memory>
#include <string_view>
#include "base/json/json_value_converter.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "google_apis/common/parser_util.h"
#include "google_apis/common/time_util.h"
namespace google_apis {
namespace {
const int64_t kUnsetFileSize = -1;
bool CreateFileResourceFromValue(const base::Value* value,
std::unique_ptr<FileResource>* file) {
*file = FileResource::CreateFrom(*value);
return !!*file;
}
bool CreateTeamDriveResourceFromValue(
const base::Value* value,
std::unique_ptr<TeamDriveResource>* file) {
*file = TeamDriveResource::CreateFrom(*value);
return !!*file;
}
// Converts |url_string| to |result|. Always returns true to be used
// for JSONValueConverter::RegisterCustomField method.
// TODO(mukai): make it return false in case of invalid |url_string|.
bool GetGURLFromString(std::string_view url_string, GURL* result) {
*result = GURL(url_string);
return true;
}
// Converts |value| to |result|.
bool GetParentsFromValue(const base::Value* value,
std::vector<ParentReference>* result) {
DCHECK(value);
DCHECK(result);
if (!value->is_list())
return false;
const base::Value::List& list = value->GetList();
base::JSONValueConverter<ParentReference> converter;
result->resize(list.size());
for (size_t i = 0; i < list.size(); ++i) {
const base::Value& parent_value = list[i];
if (!converter.Convert(parent_value, &(*result)[i]))
return false;
}
return true;
}
// Converts |value| to |result|. The key of |value| is app_id, and its value
// is URL to open the resource on the web app.
bool GetOpenWithLinksFromDictionaryValue(
const base::Value* value,
std::vector<FileResource::OpenWithLink>* result) {
DCHECK(value);
DCHECK(result);
const auto* dict = value->GetIfDict();
if (!dict) {
return false;
}
result->reserve(dict->size());
for (const auto item : *dict) {
const std::string* string_value = item.second.GetIfString();
if (!string_value)
return false;
FileResource::OpenWithLink open_with_link;
open_with_link.app_id = item.first;
open_with_link.open_url = GURL(*string_value);
result->push_back(open_with_link);
}
return true;
}
// Drive v2 API JSON names.
// Definition order follows the order of documentation in
// https://developers.google.com/drive/v2/reference/
// Common
const char kLargestChangeId[] = "largestChangeId";
const char kNextPageToken[] = "nextPageToken";
// About Resource
// https://developers.google.com/drive/v2/reference/about
const char kAboutKind[] = "drive#about";
const char kQuotaBytesTotal[] = "quotaBytesTotal";
const char kQuotaBytesUsedAggregate[] = "quotaBytesUsedAggregate";
const char kRootFolderId[] = "rootFolderId";
// Parent Resource
// https://developers.google.com/drive/v2/reference/parents
const char kParentReferenceKind[] = "drive#parentReference";
// File Resource
// https://developers.google.com/drive/v2/reference/files
const char kFileKind[] = "drive#file";
const char kTitle[] = "title";
const char kMimeType[] = "mimeType";
const char kCreatedDate[] = "createdDate";
const char kModificationDate[] = "modificationDate";
const char kModifiedDate[] = "modifiedDate";
const char kModifiedByMeDate[] = "modifiedByMeDate";
const char kLastViewedByMeDate[] = "lastViewedByMeDate";
const char kSharedWithMeDate[] = "sharedWithMeDate";
const char kMd5Checksum[] = "md5Checksum";
const char kFileSize[] = "fileSize";
const char kAlternateLink[] = "alternateLink";
const char kParents[] = "parents";
const char kOpenWithLinks[] = "openWithLinks";
const char kLabels[] = "labels";
const char kImageMediaMetadata[] = "imageMediaMetadata";
const char kShared[] = "shared";
// These 5 flags are defined under |labels|.
const char kLabelTrashed[] = "trashed";
const char kLabelStarred[] = "starred";
// These 3 flags are defined under |imageMediaMetadata|.
const char kImageMediaMetadataWidth[] = "width";
const char kImageMediaMetadataHeight[] = "height";
const char kImageMediaMetadataRotation[] = "rotation";
// URL to the share dialog UI, which is provided only in v2internal.
const char kShareLink[] = "shareLink";
const char kDriveFolderMimeType[] = "application/vnd.google-apps.folder";
// Team Drive
const char kTeamDriveKind[] = "drive#teamDrive";
const char kTeamDriveListKind[] = "drive#teamDriveList";
const char kCapabilities[] = "capabilities";
// Team Drive capabilities.
// See "capabilities" in
// https://developers.google.com/drive/v2/reference/teamdrives#resource.
const char kCanAddChildren[] = "canAddChildren";
const char kCanComment[] = "canComment";
const char kCanCopy[] = "canCopy";
const char kCanDeleteTeamDrive[] = "canDeleteTeamDrive";
const char kCanDownload[] = "canDownload";
const char kCanEdit[] = "canEdit";
const char kCanListChildren[] = "canListChildren";
const char kCanManageMembers[] = "canManageMembers";
const char kCanReadRevisions[] = "canReadRevisions";
const char kCanRemoveChildren[] = "canRemoveChildren";
const char kCanRename[] = "canRename";
const char kCanRenameTeamDrive[] = "canRenameTeamDrive";
const char kCanShare[] = "canShare";
// Files List
// https://developers.google.com/drive/v2/reference/files/list
const char kFileListKind[] = "drive#fileList";
const char kNextLink[] = "nextLink";
// File Resource capabilities.
// See "capabilities" in
// https://developers.google.com/drive/v2/reference/files#resource.
const char kCanChangeRestrictedDownload[] = "canChangeRestrictedDownload";
const char kCanDelete[] = "canDelete";
const char kCanMoveItemIntoTeamDrive[] = "canMoveItemIntoTeamDrive";
const char kCanMoveTeamDriveItem[] = "canMoveTeamDriveItem";
const char kCanReadTeamDrive[] = "canReadTeamDrive";
const char kCanTrash[] = "canTrash";
const char kCanUntrash[] = "canUntrash";
// Change Resource
// https://developers.google.com/drive/v2/reference/changes
const char kChangeKind[] = "drive#change";
const char kType[] = "type";
const char kFileId[] = "fileId";
const char kDeleted[] = "deleted";
const char kFile[] = "file";
const char kTeamDrive[] = "teamDrive";
const char kTeamDriveId[] = "teamDriveId";
const char kStartPageToken[] = "startPageToken";
const char kNewStartPageToken[] = "newStartPageToken";
// Changes List
// https://developers.google.com/drive/v2/reference/changes/list
const char kChangeListKind[] = "drive#changeList";
// Maps category name to enum ChangeType.
struct ChangeTypeMap {
ChangeResource::ChangeType type;
const char* type_name;
};
constexpr ChangeTypeMap kChangeTypeMap[] = {
{ChangeResource::FILE, "file"},
{ChangeResource::TEAM_DRIVE, "teamDrive"},
};
} // namespace
////////////////////////////////////////////////////////////////////////////////
// AboutResource implementation
AboutResource::AboutResource()
: largest_change_id_(0),
quota_bytes_total_(0),
quota_bytes_used_aggregate_(0) {}
AboutResource::~AboutResource() {}
// static
std::unique_ptr<AboutResource> AboutResource::CreateFrom(
const base::Value& value) {
std::unique_ptr<AboutResource> resource(new AboutResource());
if (!IsResourceKindExpected(value, kAboutKind) || !resource->Parse(value)) {
LOG(ERROR) << "Unable to create: Invalid About resource JSON!";
return nullptr;
}
return resource;
}
// static
void AboutResource::RegisterJSONConverter(
base::JSONValueConverter<AboutResource>* converter) {
converter->RegisterCustomField<int64_t>(kLargestChangeId,
&AboutResource::largest_change_id_,
&base::StringToInt64);
converter->RegisterCustomField<int64_t>(kQuotaBytesTotal,
&AboutResource::quota_bytes_total_,
&base::StringToInt64);
converter->RegisterCustomField<int64_t>(
kQuotaBytesUsedAggregate, &AboutResource::quota_bytes_used_aggregate_,
&base::StringToInt64);
converter->RegisterStringField(kRootFolderId,
&AboutResource::root_folder_id_);
}
bool AboutResource::Parse(const base::Value& value) {
base::JSONValueConverter<AboutResource> converter;
if (!converter.Convert(value, this)) {
LOG(ERROR) << "Unable to parse: Invalid About resource JSON!";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// TeamDriveCapabilities implementation
TeamDriveCapabilities::TeamDriveCapabilities()
: can_add_children_(false),
can_comment_(false),
can_copy_(false),
can_delete_team_drive_(false),
can_download_(false),
can_edit_(false),
can_list_children_(false),
can_manage_members_(false),
can_read_revisions_(false),
can_remove_children_(false),
can_rename_(false),
can_rename_team_drive_(false),
can_share_(false) {}
TeamDriveCapabilities::TeamDriveCapabilities(const TeamDriveCapabilities& src) =
default;
TeamDriveCapabilities::~TeamDriveCapabilities() = default;
// static
void TeamDriveCapabilities::RegisterJSONConverter(
base::JSONValueConverter<TeamDriveCapabilities>* converter) {
converter->RegisterBoolField(kCanAddChildren,
&TeamDriveCapabilities::can_add_children_);
converter->RegisterBoolField(kCanComment,
&TeamDriveCapabilities::can_comment_);
converter->RegisterBoolField(kCanCopy, &TeamDriveCapabilities::can_copy_);
converter->RegisterBoolField(kCanDeleteTeamDrive,
&TeamDriveCapabilities::can_delete_team_drive_);
converter->RegisterBoolField(kCanDownload,
&TeamDriveCapabilities::can_download_);
converter->RegisterBoolField(kCanEdit, &TeamDriveCapabilities::can_edit_);
converter->RegisterBoolField(kCanListChildren,
&TeamDriveCapabilities::can_list_children_);
converter->RegisterBoolField(kCanManageMembers,
&TeamDriveCapabilities::can_manage_members_);
converter->RegisterBoolField(kCanReadRevisions,
&TeamDriveCapabilities::can_read_revisions_);
converter->RegisterBoolField(kCanRemoveChildren,
&TeamDriveCapabilities::can_remove_children_);
converter->RegisterBoolField(kCanRename, &TeamDriveCapabilities::can_rename_);
converter->RegisterBoolField(kCanRenameTeamDrive,
&TeamDriveCapabilities::can_rename_team_drive_);
converter->RegisterBoolField(kCanShare, &TeamDriveCapabilities::can_share_);
}
////////////////////////////////////////////////////////////////////////////////
// TeamDriveResource implementation
TeamDriveResource::TeamDriveResource() {}
TeamDriveResource::~TeamDriveResource() {}
// static
std::unique_ptr<TeamDriveResource> TeamDriveResource::CreateFrom(
const base::Value& value) {
std::unique_ptr<TeamDriveResource> resource(new TeamDriveResource());
if (!IsResourceKindExpected(value, kTeamDriveKind) ||
!resource->Parse(value)) {
LOG(ERROR) << "Unable to create: Invalid Team Drive resource JSON!";
return nullptr;
}
return resource;
}
// static
void TeamDriveResource::RegisterJSONConverter(
base::JSONValueConverter<TeamDriveResource>* converter) {
converter->RegisterStringField(kApiResponseIdKey, &TeamDriveResource::id_);
converter->RegisterStringField(kApiResponseNameKey,
&TeamDriveResource::name_);
converter->RegisterNestedField(kCapabilities,
&TeamDriveResource::capabilities_);
}
bool TeamDriveResource::Parse(const base::Value& value) {
base::JSONValueConverter<TeamDriveResource> converter;
if (!converter.Convert(value, this)) {
LOG(ERROR) << "Unable to parse: Invalid Team Drive resource JSON!";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// TeamDriveList implementation
TeamDriveList::TeamDriveList() {}
TeamDriveList::~TeamDriveList() {}
// static
void TeamDriveList::RegisterJSONConverter(
base::JSONValueConverter<TeamDriveList>* converter) {
converter->RegisterStringField(kNextPageToken,
&TeamDriveList::next_page_token_);
converter->RegisterRepeatedMessage<TeamDriveResource>(kApiResponseItemsKey,
&TeamDriveList::items_);
}
// static
bool TeamDriveList::HasTeamDriveListKind(const base::Value& value) {
return IsResourceKindExpected(value, kTeamDriveListKind);
}
// static
std::unique_ptr<TeamDriveList> TeamDriveList::CreateFrom(
const base::Value& value) {
std::unique_ptr<TeamDriveList> resource(new TeamDriveList());
if (!HasTeamDriveListKind(value) || !resource->Parse(value)) {
LOG(ERROR) << "Unable to create: Invalid TeamDriveList JSON!";
return nullptr;
}
return resource;
}
bool TeamDriveList::Parse(const base::Value& value) {
base::JSONValueConverter<TeamDriveList> converter;
if (!converter.Convert(value, this)) {
LOG(ERROR) << "Unable to parse: Invalid TeamDriveList";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// ParentReference implementation
ParentReference::ParentReference() {}
ParentReference::~ParentReference() {}
// static
void ParentReference::RegisterJSONConverter(
base::JSONValueConverter<ParentReference>* converter) {
converter->RegisterStringField(kApiResponseIdKey, &ParentReference::file_id_);
}
// static
std::unique_ptr<ParentReference> ParentReference::CreateFrom(
const base::Value& value) {
std::unique_ptr<ParentReference> reference(new ParentReference());
if (!IsResourceKindExpected(value, kParentReferenceKind) ||
!reference->Parse(value)) {
LOG(ERROR) << "Unable to create: Invalid ParentRefernce JSON!";
return nullptr;
}
return reference;
}
bool ParentReference::Parse(const base::Value& value) {
base::JSONValueConverter<ParentReference> converter;
if (!converter.Convert(value, this)) {
LOG(ERROR) << "Unable to parse: Invalid ParentReference";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// FileResourceCapabilities implementation
FileResourceCapabilities::FileResourceCapabilities()
: can_add_children_(false),
can_change_restricted_download_(false),
can_comment_(false),
can_copy_(false),
can_delete_(false),
can_download_(false),
can_edit_(false),
can_list_children_(false),
can_move_item_into_team_drive_(false),
can_move_team_drive_item_(false),
can_read_revisions_(false),
can_read_team_drive_(false),
can_remove_children_(false),
can_rename_(false),
can_share_(false),
can_trash_(false),
can_untrash_(false) {}
FileResourceCapabilities::FileResourceCapabilities(
const FileResourceCapabilities& src) = default;
FileResourceCapabilities::~FileResourceCapabilities() {}
// static
void FileResourceCapabilities::RegisterJSONConverter(
base::JSONValueConverter<FileResourceCapabilities>* converter) {
converter->RegisterBoolField(kCanAddChildren,
&FileResourceCapabilities::can_add_children_);
converter->RegisterBoolField(
kCanChangeRestrictedDownload,
&FileResourceCapabilities::can_change_restricted_download_);
converter->RegisterBoolField(kCanComment,
&FileResourceCapabilities::can_comment_);
converter->RegisterBoolField(kCanCopy, &FileResourceCapabilities::can_copy_);
converter->RegisterBoolField(kCanDelete,
&FileResourceCapabilities::can_delete_);
converter->RegisterBoolField(kCanDownload,
&FileResourceCapabilities::can_download_);
converter->RegisterBoolField(kCanEdit, &FileResourceCapabilities::can_edit_);
converter->RegisterBoolField(kCanListChildren,
&FileResourceCapabilities::can_list_children_);
converter->RegisterBoolField(
kCanMoveItemIntoTeamDrive,
&FileResourceCapabilities::can_move_item_into_team_drive_);
converter->RegisterBoolField(
kCanMoveTeamDriveItem,
&FileResourceCapabilities::can_move_team_drive_item_);
converter->RegisterBoolField(kCanReadRevisions,
&FileResourceCapabilities::can_read_revisions_);
converter->RegisterBoolField(kCanReadTeamDrive,
&FileResourceCapabilities::can_read_team_drive_);
converter->RegisterBoolField(kCanRemoveChildren,
&FileResourceCapabilities::can_remove_children_);
converter->RegisterBoolField(kCanRename,
&FileResourceCapabilities::can_rename_);
converter->RegisterBoolField(kCanShare,
&FileResourceCapabilities::can_share_);
converter->RegisterBoolField(kCanTrash,
&FileResourceCapabilities::can_trash_);
converter->RegisterBoolField(kCanUntrash,
&FileResourceCapabilities::can_untrash_);
}
////////////////////////////////////////////////////////////////////////////////
// FileResource implementation
FileResource::FileResource() : shared_(false), file_size_(kUnsetFileSize) {}
FileResource::FileResource(const FileResource& other) = default;
FileResource::~FileResource() {}
// static
void FileResource::RegisterJSONConverter(
base::JSONValueConverter<FileResource>* converter) {
converter->RegisterStringField(kApiResponseIdKey, &FileResource::file_id_);
converter->RegisterStringField(kApiResponseETagKey, &FileResource::etag_);
converter->RegisterStringField(kTitle, &FileResource::title_);
converter->RegisterStringField(kMimeType, &FileResource::mime_type_);
converter->RegisterNestedField(kLabels, &FileResource::labels_);
converter->RegisterNestedField(kImageMediaMetadata,
&FileResource::image_media_metadata_);
converter->RegisterNestedField(kCapabilities, &FileResource::capabilities_);
converter->RegisterCustomField<base::Time>(
kCreatedDate, &FileResource::created_date_, &util::GetTimeFromString);
converter->RegisterCustomField<base::Time>(
kModifiedDate, &FileResource::modified_date_, &util::GetTimeFromString);
converter->RegisterCustomField<base::Time>(
kModifiedByMeDate, &FileResource::modified_by_me_date_,
&util::GetTimeFromString);
converter->RegisterCustomField<base::Time>(
kLastViewedByMeDate, &FileResource::last_viewed_by_me_date_,
&util::GetTimeFromString);
converter->RegisterCustomField<base::Time>(
kSharedWithMeDate, &FileResource::shared_with_me_date_,
&util::GetTimeFromString);
converter->RegisterBoolField(kShared, &FileResource::shared_);
converter->RegisterStringField(kMd5Checksum, &FileResource::md5_checksum_);
converter->RegisterCustomField<int64_t>(kFileSize, &FileResource::file_size_,
&base::StringToInt64);
converter->RegisterCustomField<GURL>(
kAlternateLink, &FileResource::alternate_link_, GetGURLFromString);
converter->RegisterCustomField<GURL>(kShareLink, &FileResource::share_link_,
GetGURLFromString);
converter->RegisterCustomValueField<std::vector<ParentReference>>(
kParents, &FileResource::parents_, GetParentsFromValue);
converter->RegisterCustomValueField<std::vector<OpenWithLink>>(
kOpenWithLinks, &FileResource::open_with_links_,
GetOpenWithLinksFromDictionaryValue);
converter->RegisterStringField(kTeamDriveId, &FileResource::team_drive_id_);
}
// static
std::unique_ptr<FileResource> FileResource::CreateFrom(
const base::Value& value) {
std::unique_ptr<FileResource> resource(new FileResource());
if (!IsResourceKindExpected(value, kFileKind) || !resource->Parse(value)) {
LOG(ERROR) << "Unable to create: Invalid FileResource JSON!";
return nullptr;
}
return resource;
}
bool FileResource::IsDirectory() const {
return mime_type_ == kDriveFolderMimeType;
}
bool FileResource::IsHostedDocument() const {
// Hosted documents don't have fileSize field set:
// https://developers.google.com/drive/v2/reference/files
return !IsDirectory() && file_size_ == kUnsetFileSize;
}
bool FileResource::Parse(const base::Value& value) {
base::JSONValueConverter<FileResource> converter;
if (!converter.Convert(value, this)) {
LOG(ERROR) << "Unable to parse: Invalid FileResource";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// FileList implementation
FileList::FileList() {}
FileList::~FileList() {}
// static
void FileList::RegisterJSONConverter(
base::JSONValueConverter<FileList>* converter) {
converter->RegisterCustomField<GURL>(kNextLink, &FileList::next_link_,
GetGURLFromString);
converter->RegisterRepeatedMessage<FileResource>(kApiResponseItemsKey,
&FileList::items_);
}
// static
bool FileList::HasFileListKind(const base::Value& value) {
return IsResourceKindExpected(value, kFileListKind);
}
// static
std::unique_ptr<FileList> FileList::CreateFrom(const base::Value& value) {
std::unique_ptr<FileList> resource(new FileList());
if (!HasFileListKind(value) || !resource->Parse(value)) {
LOG(ERROR) << "Unable to create: Invalid FileList JSON!";
return nullptr;
}
return resource;
}
bool FileList::Parse(const base::Value& value) {
base::JSONValueConverter<FileList> converter;
if (!converter.Convert(value, this)) {
LOG(ERROR) << "Unable to parse: Invalid FileList";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// ChangeResource implementation
ChangeResource::ChangeResource()
: change_id_(0), type_(UNKNOWN), deleted_(false) {}
ChangeResource::~ChangeResource() {}
// static
void ChangeResource::RegisterJSONConverter(
base::JSONValueConverter<ChangeResource>* converter) {
converter->RegisterCustomField<int64_t>(
kApiResponseIdKey, &ChangeResource::change_id_, &base::StringToInt64);
converter->RegisterCustomField<ChangeType>(kType, &ChangeResource::type_,
&ChangeResource::GetType);
converter->RegisterStringField(kFileId, &ChangeResource::file_id_);
converter->RegisterBoolField(kDeleted, &ChangeResource::deleted_);
converter->RegisterCustomValueField(kFile, &ChangeResource::file_,
&CreateFileResourceFromValue);
converter->RegisterCustomField<base::Time>(
kModificationDate, &ChangeResource::modification_date_,
&util::GetTimeFromString);
converter->RegisterStringField(kTeamDriveId, &ChangeResource::team_drive_id_);
converter->RegisterCustomValueField(kTeamDrive, &ChangeResource::team_drive_,
&CreateTeamDriveResourceFromValue);
}
// static
std::unique_ptr<ChangeResource> ChangeResource::CreateFrom(
const base::Value& value) {
std::unique_ptr<ChangeResource> resource(new ChangeResource());
if (!IsResourceKindExpected(value, kChangeKind) || !resource->Parse(value)) {
LOG(ERROR) << "Unable to create: Invalid ChangeResource JSON!";
return nullptr;
}
return resource;
}
bool ChangeResource::Parse(const base::Value& value) {
base::JSONValueConverter<ChangeResource> converter;
if (!converter.Convert(value, this)) {
LOG(ERROR) << "Unable to parse: Invalid ChangeResource";
return false;
}
return true;
}
// static
bool ChangeResource::GetType(std::string_view type_name,
ChangeResource::ChangeType* result) {
for (size_t i = 0; i < std::size(kChangeTypeMap); i++) {
if (type_name == kChangeTypeMap[i].type_name) {
*result = kChangeTypeMap[i].type;
return true;
}
}
DVLOG(1) << "Unknown change type" << type_name;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// ChangeList implementation
ChangeList::ChangeList() = default;
ChangeList::~ChangeList() = default;
// static
void ChangeList::RegisterJSONConverter(
base::JSONValueConverter<ChangeList>* converter) {
converter->RegisterCustomField<GURL>(kNextLink, &ChangeList::next_link_,
GetGURLFromString);
converter->RegisterCustomField<int64_t>(
kLargestChangeId, &ChangeList::largest_change_id_, &base::StringToInt64);
converter->RegisterStringField(kNewStartPageToken,
&ChangeList::new_start_page_token_);
converter->RegisterRepeatedMessage<ChangeResource>(kApiResponseItemsKey,
&ChangeList::items_);
}
// static
bool ChangeList::HasChangeListKind(const base::Value& value) {
return IsResourceKindExpected(value, kChangeListKind);
}
// static
std::unique_ptr<ChangeList> ChangeList::CreateFrom(const base::Value& value) {
std::unique_ptr<ChangeList> resource(new ChangeList());
if (!HasChangeListKind(value) || !resource->Parse(value)) {
LOG(ERROR) << "Unable to create: Invalid ChangeList JSON!";
return nullptr;
}
return resource;
}
bool ChangeList::Parse(const base::Value& value) {
base::JSONValueConverter<ChangeList> converter;
if (!converter.Convert(value, this)) {
LOG(ERROR) << "Unable to parse: Invalid ChangeList";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// FileLabels implementation
FileLabels::FileLabels() : trashed_(false), starred_(false) {}
FileLabels::~FileLabels() {}
// static
void FileLabels::RegisterJSONConverter(
base::JSONValueConverter<FileLabels>* converter) {
converter->RegisterBoolField(kLabelTrashed, &FileLabels::trashed_);
converter->RegisterBoolField(kLabelStarred, &FileLabels::starred_);
}
// static
std::unique_ptr<FileLabels> FileLabels::CreateFrom(const base::Value& value) {
std::unique_ptr<FileLabels> resource(new FileLabels());
if (!resource->Parse(value)) {
LOG(ERROR) << "Unable to create: Invalid FileLabels JSON!";
return nullptr;
}
return resource;
}
bool FileLabels::Parse(const base::Value& value) {
base::JSONValueConverter<FileLabels> converter;
if (!converter.Convert(value, this)) {
LOG(ERROR) << "Unable to parse: Invalid FileLabels.";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// ImageMediaMetadata implementation
ImageMediaMetadata::ImageMediaMetadata()
: width_(-1), height_(-1), rotation_(-1) {}
ImageMediaMetadata::~ImageMediaMetadata() {}
// static
void ImageMediaMetadata::RegisterJSONConverter(
base::JSONValueConverter<ImageMediaMetadata>* converter) {
converter->RegisterIntField(kImageMediaMetadataWidth,
&ImageMediaMetadata::width_);
converter->RegisterIntField(kImageMediaMetadataHeight,
&ImageMediaMetadata::height_);
converter->RegisterIntField(kImageMediaMetadataRotation,
&ImageMediaMetadata::rotation_);
}
// static
std::unique_ptr<ImageMediaMetadata> ImageMediaMetadata::CreateFrom(
const base::Value& value) {
std::unique_ptr<ImageMediaMetadata> resource(new ImageMediaMetadata());
if (!resource->Parse(value)) {
LOG(ERROR) << "Unable to create: Invalid ImageMediaMetadata JSON!";
return nullptr;
}
return resource;
}
bool ImageMediaMetadata::Parse(const base::Value& value) {
base::JSONValueConverter<ImageMediaMetadata> converter;
if (!converter.Convert(value, this)) {
LOG(ERROR) << "Unable to parse: Invalid ImageMediaMetadata.";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// StartPageToken implementation
StartPageToken::StartPageToken() = default;
StartPageToken::~StartPageToken() = default;
// static
void StartPageToken::RegisterJSONConverter(
base::JSONValueConverter<StartPageToken>* converter) {
converter->RegisterStringField(kStartPageToken,
&StartPageToken::start_page_token_);
}
// static
std::unique_ptr<StartPageToken> StartPageToken::CreateFrom(
const base::Value& value) {
std::unique_ptr<StartPageToken> result = std::make_unique<StartPageToken>();
if (!result->Parse(value)) {
LOG(ERROR) << "Unable to parse: Invalid StartPageToken JSON.";
return nullptr;
}
return result;
}
bool StartPageToken::Parse(const base::Value& value) {
base::JSONValueConverter<StartPageToken> converter;
if (!converter.Convert(value, this)) {
LOG(ERROR) << "Unable to parse: Invalid StartPageToken.";
return false;
}
return true;
}
} // namespace google_apis