• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "google_apis/drive/drive_api_parser.h"
6 
7 #include <algorithm>
8 
9 #include "base/basictypes.h"
10 #include "base/files/file_path.h"
11 #include "base/json/json_value_converter.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_piece.h"
15 #include "base/strings/string_util.h"
16 #include "base/values.h"
17 #include "google_apis/drive/time_util.h"
18 
19 using base::Value;
20 using base::DictionaryValue;
21 using base::ListValue;
22 
23 namespace google_apis {
24 
25 namespace {
26 
CreateFileResourceFromValue(const base::Value * value,scoped_ptr<FileResource> * file)27 bool CreateFileResourceFromValue(const base::Value* value,
28                                  scoped_ptr<FileResource>* file) {
29   *file = FileResource::CreateFrom(*value);
30   return !!*file;
31 }
32 
33 // Converts |url_string| to |result|.  Always returns true to be used
34 // for JSONValueConverter::RegisterCustomField method.
35 // TODO(mukai): make it return false in case of invalid |url_string|.
GetGURLFromString(const base::StringPiece & url_string,GURL * result)36 bool GetGURLFromString(const base::StringPiece& url_string, GURL* result) {
37   *result = GURL(url_string.as_string());
38   return true;
39 }
40 
41 // Converts |value| to |result|.
GetParentsFromValue(const base::Value * value,std::vector<ParentReference> * result)42 bool GetParentsFromValue(const base::Value* value,
43                          std::vector<ParentReference>* result) {
44   DCHECK(value);
45   DCHECK(result);
46 
47   const base::ListValue* list_value = NULL;
48   if (!value->GetAsList(&list_value))
49     return false;
50 
51   base::JSONValueConverter<ParentReference> converter;
52   result->resize(list_value->GetSize());
53   for (size_t i = 0; i < list_value->GetSize(); ++i) {
54     const base::Value* parent_value = NULL;
55     if (!list_value->Get(i, &parent_value) ||
56         !converter.Convert(*parent_value, &(*result)[i]))
57       return false;
58   }
59 
60   return true;
61 }
62 
63 // Converts |value| to |result|. The key of |value| is app_id, and its value
64 // is URL to open the resource on the web app.
GetOpenWithLinksFromDictionaryValue(const base::Value * value,std::vector<FileResource::OpenWithLink> * result)65 bool GetOpenWithLinksFromDictionaryValue(
66     const base::Value* value,
67     std::vector<FileResource::OpenWithLink>* result) {
68   DCHECK(value);
69   DCHECK(result);
70 
71   const base::DictionaryValue* dictionary_value;
72   if (!value->GetAsDictionary(&dictionary_value))
73     return false;
74 
75   result->reserve(dictionary_value->size());
76   for (DictionaryValue::Iterator iter(*dictionary_value);
77        !iter.IsAtEnd(); iter.Advance()) {
78     std::string string_value;
79     if (!iter.value().GetAsString(&string_value))
80       return false;
81 
82     FileResource::OpenWithLink open_with_link;
83     open_with_link.app_id = iter.key();
84     open_with_link.open_url = GURL(string_value);
85     result->push_back(open_with_link);
86   }
87 
88   return true;
89 }
90 
91 // Drive v2 API JSON names.
92 
93 // Definition order follows the order of documentation in
94 // https://developers.google.com/drive/v2/reference/
95 
96 // Common
97 const char kKind[] = "kind";
98 const char kId[] = "id";
99 const char kETag[] = "etag";
100 const char kItems[] = "items";
101 const char kLargestChangeId[] = "largestChangeId";
102 
103 // About Resource
104 // https://developers.google.com/drive/v2/reference/about
105 const char kAboutKind[] = "drive#about";
106 const char kQuotaBytesTotal[] = "quotaBytesTotal";
107 const char kQuotaBytesUsed[] = "quotaBytesUsed";
108 const char kRootFolderId[] = "rootFolderId";
109 
110 // App Icon
111 // https://developers.google.com/drive/v2/reference/apps
112 const char kCategory[] = "category";
113 const char kSize[] = "size";
114 const char kIconUrl[] = "iconUrl";
115 
116 // Apps Resource
117 // https://developers.google.com/drive/v2/reference/apps
118 const char kAppKind[] = "drive#app";
119 const char kName[] = "name";
120 const char kObjectType[] = "objectType";
121 const char kProductId[] = "productId";
122 const char kSupportsCreate[] = "supportsCreate";
123 const char kRemovable[] = "removable";
124 const char kPrimaryMimeTypes[] = "primaryMimeTypes";
125 const char kSecondaryMimeTypes[] = "secondaryMimeTypes";
126 const char kPrimaryFileExtensions[] = "primaryFileExtensions";
127 const char kSecondaryFileExtensions[] = "secondaryFileExtensions";
128 const char kIcons[] = "icons";
129 const char kCreateUrl[] = "createUrl";
130 
131 // Apps List
132 // https://developers.google.com/drive/v2/reference/apps/list
133 const char kAppListKind[] = "drive#appList";
134 
135 // Parent Resource
136 // https://developers.google.com/drive/v2/reference/parents
137 const char kParentReferenceKind[] = "drive#parentReference";
138 const char kParentLink[] = "parentLink";
139 
140 // File Resource
141 // https://developers.google.com/drive/v2/reference/files
142 const char kFileKind[] = "drive#file";
143 const char kTitle[] = "title";
144 const char kMimeType[] = "mimeType";
145 const char kCreatedDate[] = "createdDate";
146 const char kModificationDate[] = "modificationDate";
147 const char kModifiedDate[] = "modifiedDate";
148 const char kLastViewedByMeDate[] = "lastViewedByMeDate";
149 const char kSharedWithMeDate[] = "sharedWithMeDate";
150 const char kMd5Checksum[] = "md5Checksum";
151 const char kFileSize[] = "fileSize";
152 const char kAlternateLink[] = "alternateLink";
153 const char kParents[] = "parents";
154 const char kOpenWithLinks[] = "openWithLinks";
155 const char kLabels[] = "labels";
156 const char kImageMediaMetadata[] = "imageMediaMetadata";
157 const char kShared[] = "shared";
158 // These 5 flags are defined under |labels|.
159 const char kLabelTrashed[] = "trashed";
160 // These 3 flags are defined under |imageMediaMetadata|.
161 const char kImageMediaMetadataWidth[] = "width";
162 const char kImageMediaMetadataHeight[] = "height";
163 const char kImageMediaMetadataRotation[] = "rotation";
164 
165 const char kDriveFolderMimeType[] = "application/vnd.google-apps.folder";
166 
167 // Files List
168 // https://developers.google.com/drive/v2/reference/files/list
169 const char kFileListKind[] = "drive#fileList";
170 const char kNextLink[] = "nextLink";
171 
172 // Change Resource
173 // https://developers.google.com/drive/v2/reference/changes
174 const char kChangeKind[] = "drive#change";
175 const char kFileId[] = "fileId";
176 const char kDeleted[] = "deleted";
177 const char kFile[] = "file";
178 
179 // Changes List
180 // https://developers.google.com/drive/v2/reference/changes/list
181 const char kChangeListKind[] = "drive#changeList";
182 
183 // Maps category name to enum IconCategory.
184 struct AppIconCategoryMap {
185   DriveAppIcon::IconCategory category;
186   const char* category_name;
187 };
188 
189 const AppIconCategoryMap kAppIconCategoryMap[] = {
190   { DriveAppIcon::DOCUMENT, "document" },
191   { DriveAppIcon::APPLICATION, "application" },
192   { DriveAppIcon::SHARED_DOCUMENT, "documentShared" },
193 };
194 
195 // Checks if the JSON is expected kind.  In Drive API, JSON data structure has
196 // |kind| property which denotes the type of the structure (e.g. "drive#file").
IsResourceKindExpected(const base::Value & value,const std::string & expected_kind)197 bool IsResourceKindExpected(const base::Value& value,
198                             const std::string& expected_kind) {
199   const base::DictionaryValue* as_dict = NULL;
200   std::string kind;
201   return value.GetAsDictionary(&as_dict) &&
202       as_dict->HasKey(kKind) &&
203       as_dict->GetString(kKind, &kind) &&
204       kind == expected_kind;
205 }
206 
207 }  // namespace
208 
209 ////////////////////////////////////////////////////////////////////////////////
210 // AboutResource implementation
211 
AboutResource()212 AboutResource::AboutResource()
213     : largest_change_id_(0),
214       quota_bytes_total_(0),
215       quota_bytes_used_(0) {}
216 
~AboutResource()217 AboutResource::~AboutResource() {}
218 
219 // static
CreateFrom(const base::Value & value)220 scoped_ptr<AboutResource> AboutResource::CreateFrom(const base::Value& value) {
221   scoped_ptr<AboutResource> resource(new AboutResource());
222   if (!IsResourceKindExpected(value, kAboutKind) || !resource->Parse(value)) {
223     LOG(ERROR) << "Unable to create: Invalid About resource JSON!";
224     return scoped_ptr<AboutResource>();
225   }
226   return resource.Pass();
227 }
228 
229 // static
RegisterJSONConverter(base::JSONValueConverter<AboutResource> * converter)230 void AboutResource::RegisterJSONConverter(
231     base::JSONValueConverter<AboutResource>* converter) {
232   converter->RegisterCustomField<int64>(kLargestChangeId,
233                                         &AboutResource::largest_change_id_,
234                                         &base::StringToInt64);
235   converter->RegisterCustomField<int64>(kQuotaBytesTotal,
236                                         &AboutResource::quota_bytes_total_,
237                                         &base::StringToInt64);
238   converter->RegisterCustomField<int64>(kQuotaBytesUsed,
239                                         &AboutResource::quota_bytes_used_,
240                                         &base::StringToInt64);
241   converter->RegisterStringField(kRootFolderId,
242                                  &AboutResource::root_folder_id_);
243 }
244 
Parse(const base::Value & value)245 bool AboutResource::Parse(const base::Value& value) {
246   base::JSONValueConverter<AboutResource> converter;
247   if (!converter.Convert(value, this)) {
248     LOG(ERROR) << "Unable to parse: Invalid About resource JSON!";
249     return false;
250   }
251   return true;
252 }
253 
254 ////////////////////////////////////////////////////////////////////////////////
255 // DriveAppIcon implementation
256 
DriveAppIcon()257 DriveAppIcon::DriveAppIcon() : category_(UNKNOWN), icon_side_length_(0) {}
258 
~DriveAppIcon()259 DriveAppIcon::~DriveAppIcon() {}
260 
261 // static
RegisterJSONConverter(base::JSONValueConverter<DriveAppIcon> * converter)262 void DriveAppIcon::RegisterJSONConverter(
263     base::JSONValueConverter<DriveAppIcon>* converter) {
264   converter->RegisterCustomField<IconCategory>(
265       kCategory,
266       &DriveAppIcon::category_,
267       &DriveAppIcon::GetIconCategory);
268   converter->RegisterIntField(kSize, &DriveAppIcon::icon_side_length_);
269   converter->RegisterCustomField<GURL>(kIconUrl,
270                                        &DriveAppIcon::icon_url_,
271                                        GetGURLFromString);
272 }
273 
274 // static
CreateFrom(const base::Value & value)275 scoped_ptr<DriveAppIcon> DriveAppIcon::CreateFrom(const base::Value& value) {
276   scoped_ptr<DriveAppIcon> resource(new DriveAppIcon());
277   if (!resource->Parse(value)) {
278     LOG(ERROR) << "Unable to create: Invalid DriveAppIcon JSON!";
279     return scoped_ptr<DriveAppIcon>();
280   }
281   return resource.Pass();
282 }
283 
Parse(const base::Value & value)284 bool DriveAppIcon::Parse(const base::Value& value) {
285   base::JSONValueConverter<DriveAppIcon> converter;
286   if (!converter.Convert(value, this)) {
287     LOG(ERROR) << "Unable to parse: Invalid DriveAppIcon";
288     return false;
289   }
290   return true;
291 }
292 
293 // static
GetIconCategory(const base::StringPiece & category,DriveAppIcon::IconCategory * result)294 bool DriveAppIcon::GetIconCategory(const base::StringPiece& category,
295                                    DriveAppIcon::IconCategory* result) {
296   for (size_t i = 0; i < arraysize(kAppIconCategoryMap); i++) {
297     if (category == kAppIconCategoryMap[i].category_name) {
298       *result = kAppIconCategoryMap[i].category;
299       return true;
300     }
301   }
302   DVLOG(1) << "Unknown icon category " << category;
303   return false;
304 }
305 
306 ////////////////////////////////////////////////////////////////////////////////
307 // AppResource implementation
308 
AppResource()309 AppResource::AppResource()
310     : supports_create_(false),
311       removable_(false) {
312 }
313 
~AppResource()314 AppResource::~AppResource() {}
315 
316 // static
RegisterJSONConverter(base::JSONValueConverter<AppResource> * converter)317 void AppResource::RegisterJSONConverter(
318     base::JSONValueConverter<AppResource>* converter) {
319   converter->RegisterStringField(kId, &AppResource::application_id_);
320   converter->RegisterStringField(kName, &AppResource::name_);
321   converter->RegisterStringField(kObjectType, &AppResource::object_type_);
322   converter->RegisterStringField(kProductId, &AppResource::product_id_);
323   converter->RegisterBoolField(kSupportsCreate, &AppResource::supports_create_);
324   converter->RegisterBoolField(kRemovable, &AppResource::removable_);
325   converter->RegisterRepeatedString(kPrimaryMimeTypes,
326                                     &AppResource::primary_mimetypes_);
327   converter->RegisterRepeatedString(kSecondaryMimeTypes,
328                                     &AppResource::secondary_mimetypes_);
329   converter->RegisterRepeatedString(kPrimaryFileExtensions,
330                                     &AppResource::primary_file_extensions_);
331   converter->RegisterRepeatedString(kSecondaryFileExtensions,
332                                     &AppResource::secondary_file_extensions_);
333   converter->RegisterRepeatedMessage(kIcons, &AppResource::icons_);
334   converter->RegisterCustomField<GURL>(kCreateUrl,
335                                        &AppResource::create_url_,
336                                        GetGURLFromString);
337 }
338 
339 // static
CreateFrom(const base::Value & value)340 scoped_ptr<AppResource> AppResource::CreateFrom(const base::Value& value) {
341   scoped_ptr<AppResource> resource(new AppResource());
342   if (!IsResourceKindExpected(value, kAppKind) || !resource->Parse(value)) {
343     LOG(ERROR) << "Unable to create: Invalid AppResource JSON!";
344     return scoped_ptr<AppResource>();
345   }
346   return resource.Pass();
347 }
348 
Parse(const base::Value & value)349 bool AppResource::Parse(const base::Value& value) {
350   base::JSONValueConverter<AppResource> converter;
351   if (!converter.Convert(value, this)) {
352     LOG(ERROR) << "Unable to parse: Invalid AppResource";
353     return false;
354   }
355   return true;
356 }
357 
358 ////////////////////////////////////////////////////////////////////////////////
359 // AppList implementation
360 
AppList()361 AppList::AppList() {}
362 
~AppList()363 AppList::~AppList() {}
364 
365 // static
RegisterJSONConverter(base::JSONValueConverter<AppList> * converter)366 void AppList::RegisterJSONConverter(
367     base::JSONValueConverter<AppList>* converter) {
368   converter->RegisterStringField(kETag, &AppList::etag_);
369   converter->RegisterRepeatedMessage<AppResource>(kItems,
370                                                    &AppList::items_);
371 }
372 
373 // static
CreateFrom(const base::Value & value)374 scoped_ptr<AppList> AppList::CreateFrom(const base::Value& value) {
375   scoped_ptr<AppList> resource(new AppList());
376   if (!IsResourceKindExpected(value, kAppListKind) || !resource->Parse(value)) {
377     LOG(ERROR) << "Unable to create: Invalid AppList JSON!";
378     return scoped_ptr<AppList>();
379   }
380   return resource.Pass();
381 }
382 
Parse(const base::Value & value)383 bool AppList::Parse(const base::Value& value) {
384   base::JSONValueConverter<AppList> converter;
385   if (!converter.Convert(value, this)) {
386     LOG(ERROR) << "Unable to parse: Invalid AppList";
387     return false;
388   }
389   return true;
390 }
391 
392 ////////////////////////////////////////////////////////////////////////////////
393 // ParentReference implementation
394 
ParentReference()395 ParentReference::ParentReference() {}
396 
~ParentReference()397 ParentReference::~ParentReference() {}
398 
399 // static
RegisterJSONConverter(base::JSONValueConverter<ParentReference> * converter)400 void ParentReference::RegisterJSONConverter(
401     base::JSONValueConverter<ParentReference>* converter) {
402   converter->RegisterStringField(kId, &ParentReference::file_id_);
403   converter->RegisterCustomField<GURL>(kParentLink,
404                                        &ParentReference::parent_link_,
405                                        GetGURLFromString);
406 }
407 
408 // static
409 scoped_ptr<ParentReference>
CreateFrom(const base::Value & value)410 ParentReference::CreateFrom(const base::Value& value) {
411   scoped_ptr<ParentReference> reference(new ParentReference());
412   if (!IsResourceKindExpected(value, kParentReferenceKind) ||
413       !reference->Parse(value)) {
414     LOG(ERROR) << "Unable to create: Invalid ParentRefernce JSON!";
415     return scoped_ptr<ParentReference>();
416   }
417   return reference.Pass();
418 }
419 
Parse(const base::Value & value)420 bool ParentReference::Parse(const base::Value& value) {
421   base::JSONValueConverter<ParentReference> converter;
422   if (!converter.Convert(value, this)) {
423     LOG(ERROR) << "Unable to parse: Invalid ParentReference";
424     return false;
425   }
426   return true;
427 }
428 
429 ////////////////////////////////////////////////////////////////////////////////
430 // FileResource implementation
431 
FileResource()432 FileResource::FileResource() : shared_(false), file_size_(0) {}
433 
~FileResource()434 FileResource::~FileResource() {}
435 
436 // static
RegisterJSONConverter(base::JSONValueConverter<FileResource> * converter)437 void FileResource::RegisterJSONConverter(
438     base::JSONValueConverter<FileResource>* converter) {
439   converter->RegisterStringField(kId, &FileResource::file_id_);
440   converter->RegisterStringField(kETag, &FileResource::etag_);
441   converter->RegisterStringField(kTitle, &FileResource::title_);
442   converter->RegisterStringField(kMimeType, &FileResource::mime_type_);
443   converter->RegisterNestedField(kLabels, &FileResource::labels_);
444   converter->RegisterNestedField(kImageMediaMetadata,
445                                  &FileResource::image_media_metadata_);
446   converter->RegisterCustomField<base::Time>(
447       kCreatedDate,
448       &FileResource::created_date_,
449       &util::GetTimeFromString);
450   converter->RegisterCustomField<base::Time>(
451       kModifiedDate,
452       &FileResource::modified_date_,
453       &util::GetTimeFromString);
454   converter->RegisterCustomField<base::Time>(
455       kLastViewedByMeDate,
456       &FileResource::last_viewed_by_me_date_,
457       &util::GetTimeFromString);
458   converter->RegisterCustomField<base::Time>(
459       kSharedWithMeDate,
460       &FileResource::shared_with_me_date_,
461       &util::GetTimeFromString);
462   converter->RegisterBoolField(kShared, &FileResource::shared_);
463   converter->RegisterStringField(kMd5Checksum, &FileResource::md5_checksum_);
464   converter->RegisterCustomField<int64>(kFileSize,
465                                         &FileResource::file_size_,
466                                         &base::StringToInt64);
467   converter->RegisterCustomField<GURL>(kAlternateLink,
468                                        &FileResource::alternate_link_,
469                                        GetGURLFromString);
470   converter->RegisterCustomValueField<std::vector<ParentReference> >(
471       kParents,
472       &FileResource::parents_,
473       GetParentsFromValue);
474   converter->RegisterCustomValueField<std::vector<OpenWithLink> >(
475       kOpenWithLinks,
476       &FileResource::open_with_links_,
477       GetOpenWithLinksFromDictionaryValue);
478 }
479 
480 // static
CreateFrom(const base::Value & value)481 scoped_ptr<FileResource> FileResource::CreateFrom(const base::Value& value) {
482   scoped_ptr<FileResource> resource(new FileResource());
483   if (!IsResourceKindExpected(value, kFileKind) || !resource->Parse(value)) {
484     LOG(ERROR) << "Unable to create: Invalid FileResource JSON!";
485     return scoped_ptr<FileResource>();
486   }
487   return resource.Pass();
488 }
489 
IsDirectory() const490 bool FileResource::IsDirectory() const {
491   return mime_type_ == kDriveFolderMimeType;
492 }
493 
Parse(const base::Value & value)494 bool FileResource::Parse(const base::Value& value) {
495   base::JSONValueConverter<FileResource> converter;
496   if (!converter.Convert(value, this)) {
497     LOG(ERROR) << "Unable to parse: Invalid FileResource";
498     return false;
499   }
500   return true;
501 }
502 
503 ////////////////////////////////////////////////////////////////////////////////
504 // FileList implementation
505 
FileList()506 FileList::FileList() {}
507 
~FileList()508 FileList::~FileList() {}
509 
510 // static
RegisterJSONConverter(base::JSONValueConverter<FileList> * converter)511 void FileList::RegisterJSONConverter(
512     base::JSONValueConverter<FileList>* converter) {
513   converter->RegisterCustomField<GURL>(kNextLink,
514                                        &FileList::next_link_,
515                                        GetGURLFromString);
516   converter->RegisterRepeatedMessage<FileResource>(kItems,
517                                                    &FileList::items_);
518 }
519 
520 // static
HasFileListKind(const base::Value & value)521 bool FileList::HasFileListKind(const base::Value& value) {
522   return IsResourceKindExpected(value, kFileListKind);
523 }
524 
525 // static
CreateFrom(const base::Value & value)526 scoped_ptr<FileList> FileList::CreateFrom(const base::Value& value) {
527   scoped_ptr<FileList> resource(new FileList());
528   if (!HasFileListKind(value) || !resource->Parse(value)) {
529     LOG(ERROR) << "Unable to create: Invalid FileList JSON!";
530     return scoped_ptr<FileList>();
531   }
532   return resource.Pass();
533 }
534 
Parse(const base::Value & value)535 bool FileList::Parse(const base::Value& value) {
536   base::JSONValueConverter<FileList> converter;
537   if (!converter.Convert(value, this)) {
538     LOG(ERROR) << "Unable to parse: Invalid FileList";
539     return false;
540   }
541   return true;
542 }
543 
544 ////////////////////////////////////////////////////////////////////////////////
545 // ChangeResource implementation
546 
ChangeResource()547 ChangeResource::ChangeResource() : change_id_(0), deleted_(false) {}
548 
~ChangeResource()549 ChangeResource::~ChangeResource() {}
550 
551 // static
RegisterJSONConverter(base::JSONValueConverter<ChangeResource> * converter)552 void ChangeResource::RegisterJSONConverter(
553     base::JSONValueConverter<ChangeResource>* converter) {
554   converter->RegisterCustomField<int64>(kId,
555                                         &ChangeResource::change_id_,
556                                         &base::StringToInt64);
557   converter->RegisterStringField(kFileId, &ChangeResource::file_id_);
558   converter->RegisterBoolField(kDeleted, &ChangeResource::deleted_);
559   converter->RegisterCustomValueField(kFile, &ChangeResource::file_,
560                                       &CreateFileResourceFromValue);
561   converter->RegisterCustomField<base::Time>(
562       kModificationDate, &ChangeResource::modification_date_,
563       &util::GetTimeFromString);
564 }
565 
566 // static
567 scoped_ptr<ChangeResource>
CreateFrom(const base::Value & value)568 ChangeResource::CreateFrom(const base::Value& value) {
569   scoped_ptr<ChangeResource> resource(new ChangeResource());
570   if (!IsResourceKindExpected(value, kChangeKind) || !resource->Parse(value)) {
571     LOG(ERROR) << "Unable to create: Invalid ChangeResource JSON!";
572     return scoped_ptr<ChangeResource>();
573   }
574   return resource.Pass();
575 }
576 
Parse(const base::Value & value)577 bool ChangeResource::Parse(const base::Value& value) {
578   base::JSONValueConverter<ChangeResource> converter;
579   if (!converter.Convert(value, this)) {
580     LOG(ERROR) << "Unable to parse: Invalid ChangeResource";
581     return false;
582   }
583   return true;
584 }
585 
586 ////////////////////////////////////////////////////////////////////////////////
587 // ChangeList implementation
588 
ChangeList()589 ChangeList::ChangeList() : largest_change_id_(0) {}
590 
~ChangeList()591 ChangeList::~ChangeList() {}
592 
593 // static
RegisterJSONConverter(base::JSONValueConverter<ChangeList> * converter)594 void ChangeList::RegisterJSONConverter(
595     base::JSONValueConverter<ChangeList>* converter) {
596   converter->RegisterCustomField<GURL>(kNextLink,
597                                        &ChangeList::next_link_,
598                                        GetGURLFromString);
599   converter->RegisterCustomField<int64>(kLargestChangeId,
600                                         &ChangeList::largest_change_id_,
601                                         &base::StringToInt64);
602   converter->RegisterRepeatedMessage<ChangeResource>(kItems,
603                                                      &ChangeList::items_);
604 }
605 
606 // static
HasChangeListKind(const base::Value & value)607 bool ChangeList::HasChangeListKind(const base::Value& value) {
608   return IsResourceKindExpected(value, kChangeListKind);
609 }
610 
611 // static
CreateFrom(const base::Value & value)612 scoped_ptr<ChangeList> ChangeList::CreateFrom(const base::Value& value) {
613   scoped_ptr<ChangeList> resource(new ChangeList());
614   if (!HasChangeListKind(value) || !resource->Parse(value)) {
615     LOG(ERROR) << "Unable to create: Invalid ChangeList JSON!";
616     return scoped_ptr<ChangeList>();
617   }
618   return resource.Pass();
619 }
620 
Parse(const base::Value & value)621 bool ChangeList::Parse(const base::Value& value) {
622   base::JSONValueConverter<ChangeList> converter;
623   if (!converter.Convert(value, this)) {
624     LOG(ERROR) << "Unable to parse: Invalid ChangeList";
625     return false;
626   }
627   return true;
628 }
629 
630 
631 ////////////////////////////////////////////////////////////////////////////////
632 // FileLabels implementation
633 
FileLabels()634 FileLabels::FileLabels() : trashed_(false) {}
635 
~FileLabels()636 FileLabels::~FileLabels() {}
637 
638 // static
RegisterJSONConverter(base::JSONValueConverter<FileLabels> * converter)639 void FileLabels::RegisterJSONConverter(
640     base::JSONValueConverter<FileLabels>* converter) {
641   converter->RegisterBoolField(kLabelTrashed, &FileLabels::trashed_);
642 }
643 
644 // static
CreateFrom(const base::Value & value)645 scoped_ptr<FileLabels> FileLabels::CreateFrom(const base::Value& value) {
646   scoped_ptr<FileLabels> resource(new FileLabels());
647   if (!resource->Parse(value)) {
648     LOG(ERROR) << "Unable to create: Invalid FileLabels JSON!";
649     return scoped_ptr<FileLabels>();
650   }
651   return resource.Pass();
652 }
653 
Parse(const base::Value & value)654 bool FileLabels::Parse(const base::Value& value) {
655   base::JSONValueConverter<FileLabels> converter;
656   if (!converter.Convert(value, this)) {
657     LOG(ERROR) << "Unable to parse: Invalid FileLabels.";
658     return false;
659   }
660   return true;
661 }
662 
663 ////////////////////////////////////////////////////////////////////////////////
664 // ImageMediaMetadata implementation
665 
ImageMediaMetadata()666 ImageMediaMetadata::ImageMediaMetadata()
667     : width_(-1),
668       height_(-1),
669       rotation_(-1) {}
670 
~ImageMediaMetadata()671 ImageMediaMetadata::~ImageMediaMetadata() {}
672 
673 // static
RegisterJSONConverter(base::JSONValueConverter<ImageMediaMetadata> * converter)674 void ImageMediaMetadata::RegisterJSONConverter(
675     base::JSONValueConverter<ImageMediaMetadata>* converter) {
676   converter->RegisterIntField(kImageMediaMetadataWidth,
677                               &ImageMediaMetadata::width_);
678   converter->RegisterIntField(kImageMediaMetadataHeight,
679                               &ImageMediaMetadata::height_);
680   converter->RegisterIntField(kImageMediaMetadataRotation,
681                               &ImageMediaMetadata::rotation_);
682 }
683 
684 // static
CreateFrom(const base::Value & value)685 scoped_ptr<ImageMediaMetadata> ImageMediaMetadata::CreateFrom(
686     const base::Value& value) {
687   scoped_ptr<ImageMediaMetadata> resource(new ImageMediaMetadata());
688   if (!resource->Parse(value)) {
689     LOG(ERROR) << "Unable to create: Invalid ImageMediaMetadata JSON!";
690     return scoped_ptr<ImageMediaMetadata>();
691   }
692   return resource.Pass();
693 }
694 
Parse(const base::Value & value)695 bool ImageMediaMetadata::Parse(const base::Value& value) {
696   base::JSONValueConverter<ImageMediaMetadata> converter;
697   if (!converter.Convert(value, this)) {
698     LOG(ERROR) << "Unable to parse: Invalid ImageMediaMetadata.";
699     return false;
700   }
701   return true;
702 }
703 
704 }  // namespace google_apis
705