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 #ifndef GOOGLE_APIS_DRIVE_DRIVE_API_PARSER_H_ 6 #define GOOGLE_APIS_DRIVE_DRIVE_API_PARSER_H_ 7 8 #include <string> 9 10 #include "base/compiler_specific.h" 11 #include "base/gtest_prod_util.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_vector.h" 14 #include "base/strings/string_piece.h" 15 #include "base/time/time.h" 16 #include "url/gurl.h" 17 18 namespace base { 19 class Value; 20 template <class StructType> 21 class JSONValueConverter; 22 23 namespace internal { 24 template <class NestedType> 25 class RepeatedMessageConverter; 26 } // namespace internal 27 } // namespace base 28 29 namespace google_apis { 30 31 // About resource represents the account information about the current user. 32 // https://developers.google.com/drive/v2/reference/about 33 class AboutResource { 34 public: 35 AboutResource(); 36 ~AboutResource(); 37 38 // Registers the mapping between JSON field names and the members in this 39 // class. 40 static void RegisterJSONConverter( 41 base::JSONValueConverter<AboutResource>* converter); 42 43 // Creates about resource from parsed JSON. 44 static scoped_ptr<AboutResource> CreateFrom(const base::Value& value); 45 46 // Returns the largest change ID number. 47 int64 largest_change_id() const { return largest_change_id_; } 48 // Returns total number of quota bytes. 49 int64 quota_bytes_total() const { return quota_bytes_total_; } 50 // Returns the number of quota bytes used. 51 int64 quota_bytes_used() const { return quota_bytes_used_; } 52 // Returns root folder ID. 53 const std::string& root_folder_id() const { return root_folder_id_; } 54 55 void set_largest_change_id(int64 largest_change_id) { 56 largest_change_id_ = largest_change_id; 57 } 58 void set_quota_bytes_total(int64 quota_bytes_total) { 59 quota_bytes_total_ = quota_bytes_total; 60 } 61 void set_quota_bytes_used(int64 quota_bytes_used) { 62 quota_bytes_used_ = quota_bytes_used; 63 } 64 void set_root_folder_id(const std::string& root_folder_id) { 65 root_folder_id_ = root_folder_id; 66 } 67 68 private: 69 friend class DriveAPIParserTest; 70 FRIEND_TEST_ALL_PREFIXES(DriveAPIParserTest, AboutResourceParser); 71 72 // Parses and initializes data members from content of |value|. 73 // Return false if parsing fails. 74 bool Parse(const base::Value& value); 75 76 int64 largest_change_id_; 77 int64 quota_bytes_total_; 78 int64 quota_bytes_used_; 79 std::string root_folder_id_; 80 81 // This class is copyable on purpose. 82 }; 83 84 // DriveAppIcon represents an icon for Drive Application. 85 // https://developers.google.com/drive/v2/reference/apps 86 class DriveAppIcon { 87 public: 88 enum IconCategory { 89 UNKNOWN, // Uninitialized state. 90 DOCUMENT, // Icon for a file associated with the app. 91 APPLICATION, // Icon for the application. 92 SHARED_DOCUMENT, // Icon for a shared file associated with the app. 93 }; 94 95 DriveAppIcon(); 96 ~DriveAppIcon(); 97 98 // Registers the mapping between JSON field names and the members in this 99 // class. 100 static void RegisterJSONConverter( 101 base::JSONValueConverter<DriveAppIcon>* converter); 102 103 // Creates drive app icon instance from parsed JSON. 104 static scoped_ptr<DriveAppIcon> CreateFrom(const base::Value& value); 105 106 // Category of the icon. 107 IconCategory category() const { return category_; } 108 109 // Size in pixels of one side of the icon (icons are always square). 110 int icon_side_length() const { return icon_side_length_; } 111 112 // Returns URL for this icon. 113 const GURL& icon_url() const { return icon_url_; } 114 115 void set_category(IconCategory category) { 116 category_ = category; 117 } 118 void set_icon_side_length(int icon_side_length) { 119 icon_side_length_ = icon_side_length; 120 } 121 void set_icon_url(const GURL& icon_url) { 122 icon_url_ = icon_url; 123 } 124 125 private: 126 // Parses and initializes data members from content of |value|. 127 // Return false if parsing fails. 128 bool Parse(const base::Value& value); 129 130 // Extracts the icon category from the given string. Returns false and does 131 // not change |result| when |scheme| has an unrecognizable value. 132 static bool GetIconCategory(const base::StringPiece& category, 133 IconCategory* result); 134 135 friend class base::internal::RepeatedMessageConverter<DriveAppIcon>; 136 friend class AppResource; 137 138 IconCategory category_; 139 int icon_side_length_; 140 GURL icon_url_; 141 142 DISALLOW_COPY_AND_ASSIGN(DriveAppIcon); 143 }; 144 145 // AppResource represents a Drive Application. 146 // https://developers.google.com/drive/v2/reference/apps 147 class AppResource { 148 public: 149 ~AppResource(); 150 AppResource(); 151 152 // Registers the mapping between JSON field names and the members in this 153 // class. 154 static void RegisterJSONConverter( 155 base::JSONValueConverter<AppResource>* converter); 156 157 // Creates app resource from parsed JSON. 158 static scoped_ptr<AppResource> CreateFrom(const base::Value& value); 159 160 // Returns application ID, which is 12-digit decimals (e.g. "123456780123"). 161 const std::string& application_id() const { return application_id_; } 162 163 // Returns application name. 164 const std::string& name() const { return name_; } 165 166 // Returns the name of the type of object this application creates. 167 // This is used for displaying in "Create" menu item for this app. 168 // If empty, application name is used instead. 169 const std::string& object_type() const { return object_type_; } 170 171 // Returns the product ID. 172 const std::string& product_id() const { return product_id_; } 173 174 // Returns whether this application supports creating new objects. 175 bool supports_create() const { return supports_create_; } 176 177 // Returns whether this application is removable by apps.delete API. 178 bool is_removable() const { return removable_; } 179 180 // Returns the create URL, i.e., the URL for opening a new file by the app. 181 const GURL& create_url() const { return create_url_; } 182 183 // List of primary mime types supported by this WebApp. Primary status should 184 // trigger this WebApp becoming the default handler of file instances that 185 // have these mime types. 186 const ScopedVector<std::string>& primary_mimetypes() const { 187 return primary_mimetypes_; 188 } 189 190 // List of secondary mime types supported by this WebApp. Secondary status 191 // should make this WebApp show up in "Open with..." pop-up menu of the 192 // default action menu for file with matching mime types. 193 const ScopedVector<std::string>& secondary_mimetypes() const { 194 return secondary_mimetypes_; 195 } 196 197 // List of primary file extensions supported by this WebApp. Primary status 198 // should trigger this WebApp becoming the default handler of file instances 199 // that match these extensions. 200 const ScopedVector<std::string>& primary_file_extensions() const { 201 return primary_file_extensions_; 202 } 203 204 // List of secondary file extensions supported by this WebApp. Secondary 205 // status should make this WebApp show up in "Open with..." pop-up menu of the 206 // default action menu for file with matching extensions. 207 const ScopedVector<std::string>& secondary_file_extensions() const { 208 return secondary_file_extensions_; 209 } 210 211 // Returns Icons for this application. An application can have multiple 212 // icons for different purpose (application, document, shared document) 213 // in several sizes. 214 const ScopedVector<DriveAppIcon>& icons() const { 215 return icons_; 216 } 217 218 void set_application_id(const std::string& application_id) { 219 application_id_ = application_id; 220 } 221 void set_name(const std::string& name) { name_ = name; } 222 void set_object_type(const std::string& object_type) { 223 object_type_ = object_type; 224 } 225 void set_product_id(const std::string& id) { product_id_ = id; } 226 void set_supports_create(bool supports_create) { 227 supports_create_ = supports_create; 228 } 229 void set_removable(bool removable) { removable_ = removable; } 230 void set_primary_mimetypes( 231 ScopedVector<std::string> primary_mimetypes) { 232 primary_mimetypes_ = primary_mimetypes.Pass(); 233 } 234 void set_secondary_mimetypes( 235 ScopedVector<std::string> secondary_mimetypes) { 236 secondary_mimetypes_ = secondary_mimetypes.Pass(); 237 } 238 void set_primary_file_extensions( 239 ScopedVector<std::string> primary_file_extensions) { 240 primary_file_extensions_ = primary_file_extensions.Pass(); 241 } 242 void set_secondary_file_extensions( 243 ScopedVector<std::string> secondary_file_extensions) { 244 secondary_file_extensions_ = secondary_file_extensions.Pass(); 245 } 246 void set_icons(ScopedVector<DriveAppIcon> icons) { 247 icons_ = icons.Pass(); 248 } 249 void set_create_url(const GURL& url) { 250 create_url_ = url; 251 } 252 253 private: 254 friend class base::internal::RepeatedMessageConverter<AppResource>; 255 friend class AppList; 256 257 // Parses and initializes data members from content of |value|. 258 // Return false if parsing fails. 259 bool Parse(const base::Value& value); 260 261 std::string application_id_; 262 std::string name_; 263 std::string object_type_; 264 std::string product_id_; 265 bool supports_create_; 266 bool removable_; 267 GURL create_url_; 268 ScopedVector<std::string> primary_mimetypes_; 269 ScopedVector<std::string> secondary_mimetypes_; 270 ScopedVector<std::string> primary_file_extensions_; 271 ScopedVector<std::string> secondary_file_extensions_; 272 ScopedVector<DriveAppIcon> icons_; 273 274 DISALLOW_COPY_AND_ASSIGN(AppResource); 275 }; 276 277 // AppList represents a list of Drive Applications. 278 // https://developers.google.com/drive/v2/reference/apps/list 279 class AppList { 280 public: 281 AppList(); 282 ~AppList(); 283 284 // Registers the mapping between JSON field names and the members in this 285 // class. 286 static void RegisterJSONConverter( 287 base::JSONValueConverter<AppList>* converter); 288 289 // Creates app list from parsed JSON. 290 static scoped_ptr<AppList> CreateFrom(const base::Value& value); 291 292 // ETag for this resource. 293 const std::string& etag() const { return etag_; } 294 295 // Returns a vector of applications. 296 const ScopedVector<AppResource>& items() const { return items_; } 297 298 void set_etag(const std::string& etag) { 299 etag_ = etag; 300 } 301 void set_items(ScopedVector<AppResource> items) { 302 items_ = items.Pass(); 303 } 304 305 private: 306 friend class DriveAPIParserTest; 307 FRIEND_TEST_ALL_PREFIXES(DriveAPIParserTest, AppListParser); 308 309 // Parses and initializes data members from content of |value|. 310 // Return false if parsing fails. 311 bool Parse(const base::Value& value); 312 313 std::string etag_; 314 ScopedVector<AppResource> items_; 315 316 DISALLOW_COPY_AND_ASSIGN(AppList); 317 }; 318 319 // ParentReference represents a directory. 320 // https://developers.google.com/drive/v2/reference/parents 321 class ParentReference { 322 public: 323 ParentReference(); 324 ~ParentReference(); 325 326 // Registers the mapping between JSON field names and the members in this 327 // class. 328 static void RegisterJSONConverter( 329 base::JSONValueConverter<ParentReference>* converter); 330 331 // Creates parent reference from parsed JSON. 332 static scoped_ptr<ParentReference> CreateFrom(const base::Value& value); 333 334 // Returns the file id of the reference. 335 const std::string& file_id() const { return file_id_; } 336 337 // Returns the URL for the parent in Drive. 338 const GURL& parent_link() const { return parent_link_; } 339 340 void set_file_id(const std::string& file_id) { file_id_ = file_id; } 341 void set_parent_link(const GURL& parent_link) { 342 parent_link_ = parent_link; 343 } 344 345 private: 346 // Parses and initializes data members from content of |value|. 347 // Return false if parsing fails. 348 bool Parse(const base::Value& value); 349 350 std::string file_id_; 351 GURL parent_link_; 352 }; 353 354 // FileLabels represents labels for file or folder. 355 // https://developers.google.com/drive/v2/reference/files 356 class FileLabels { 357 public: 358 FileLabels(); 359 ~FileLabels(); 360 361 // Registers the mapping between JSON field names and the members in this 362 // class. 363 static void RegisterJSONConverter( 364 base::JSONValueConverter<FileLabels>* converter); 365 366 // Creates about resource from parsed JSON. 367 static scoped_ptr<FileLabels> CreateFrom(const base::Value& value); 368 369 // Whether this file has been trashed. 370 bool is_trashed() const { return trashed_; } 371 372 void set_trashed(bool trashed) { trashed_ = trashed; } 373 374 private: 375 friend class FileResource; 376 377 // Parses and initializes data members from content of |value|. 378 // Return false if parsing fails. 379 bool Parse(const base::Value& value); 380 381 bool trashed_; 382 }; 383 384 // ImageMediaMetadata represents image metadata for a file. 385 // https://developers.google.com/drive/v2/reference/files 386 class ImageMediaMetadata { 387 public: 388 ImageMediaMetadata(); 389 ~ImageMediaMetadata(); 390 391 // Registers the mapping between JSON field names and the members in this 392 // class. 393 static void RegisterJSONConverter( 394 base::JSONValueConverter<ImageMediaMetadata>* converter); 395 396 // Creates about resource from parsed JSON. 397 static scoped_ptr<ImageMediaMetadata> CreateFrom(const base::Value& value); 398 399 // Width of the image in pixels. 400 int width() const { return width_; } 401 // Height of the image in pixels. 402 int height() const { return height_; } 403 // Rotation of the image in clockwise degrees. 404 int rotation() const { return rotation_; } 405 406 void set_width(int width) { width_ = width; } 407 void set_height(int height) { height_ = height; } 408 void set_rotation(int rotation) { rotation_ = rotation; } 409 410 private: 411 friend class FileResource; 412 413 // Parses and initializes data members from content of |value|. 414 // Return false if parsing fails. 415 bool Parse(const base::Value& value); 416 417 int width_; 418 int height_; 419 int rotation_; 420 }; 421 422 423 // FileResource represents a file or folder metadata in Drive. 424 // https://developers.google.com/drive/v2/reference/files 425 class FileResource { 426 public: 427 // Link to open a file resource on a web app with |app_id|. 428 struct OpenWithLink { 429 std::string app_id; 430 GURL open_url; 431 }; 432 433 FileResource(); 434 ~FileResource(); 435 436 // Registers the mapping between JSON field names and the members in this 437 // class. 438 static void RegisterJSONConverter( 439 base::JSONValueConverter<FileResource>* converter); 440 441 // Creates file resource from parsed JSON. 442 static scoped_ptr<FileResource> CreateFrom(const base::Value& value); 443 444 // Returns true if this is a directory. 445 // Note: "folder" is used elsewhere in this file to match Drive API reference, 446 // but outside this file we use "directory" to match HTML5 filesystem API. 447 bool IsDirectory() const; 448 449 // Returns true if this is a hosted document. 450 // A hosted document is a document in one of Google Docs formats (Documents, 451 // Spreadsheets, Slides, ...) whose content is not exposed via the API. It is 452 // available only as |alternate_link()| to the document hosted on the server. 453 bool IsHostedDocument() const; 454 455 // Returns file ID. This is unique in all files in Google Drive. 456 const std::string& file_id() const { return file_id_; } 457 458 // Returns ETag for this file. 459 const std::string& etag() const { return etag_; } 460 461 // Returns the title of this file. 462 const std::string& title() const { return title_; } 463 464 // Returns MIME type of this file. 465 const std::string& mime_type() const { return mime_type_; } 466 467 // Returns labels for this file. 468 const FileLabels& labels() const { return labels_; } 469 470 // Returns image media metadata for this file. 471 const ImageMediaMetadata& image_media_metadata() const { 472 return image_media_metadata_; 473 } 474 475 // Returns created time of this file. 476 const base::Time& created_date() const { return created_date_; } 477 478 // Returns modified time of this file. 479 const base::Time& modified_date() const { return modified_date_; } 480 481 // Returns last access time by the user. 482 const base::Time& last_viewed_by_me_date() const { 483 return last_viewed_by_me_date_; 484 } 485 486 // Returns time when the file was shared with the user. 487 const base::Time& shared_with_me_date() const { 488 return shared_with_me_date_; 489 } 490 491 // Returns the 'shared' attribute of the file. 492 bool shared() const { return shared_; } 493 494 // Returns MD5 checksum of this file. 495 const std::string& md5_checksum() const { return md5_checksum_; } 496 497 // Returns the size of this file in bytes. 498 int64 file_size() const { return file_size_; } 499 500 // Return the link to open the file in Google editor or viewer. 501 // E.g. Google Document, Google Spreadsheet. 502 const GURL& alternate_link() const { return alternate_link_; } 503 504 // Returns parent references (directories) of this file. 505 const std::vector<ParentReference>& parents() const { return parents_; } 506 507 // Returns the list of links to open the resource with a web app. 508 const std::vector<OpenWithLink>& open_with_links() const { 509 return open_with_links_; 510 } 511 512 void set_file_id(const std::string& file_id) { 513 file_id_ = file_id; 514 } 515 void set_etag(const std::string& etag) { 516 etag_ = etag; 517 } 518 void set_title(const std::string& title) { 519 title_ = title; 520 } 521 void set_mime_type(const std::string& mime_type) { 522 mime_type_ = mime_type; 523 } 524 FileLabels* mutable_labels() { 525 return &labels_; 526 } 527 ImageMediaMetadata* mutable_image_media_metadata() { 528 return &image_media_metadata_; 529 } 530 void set_created_date(const base::Time& created_date) { 531 created_date_ = created_date; 532 } 533 void set_modified_date(const base::Time& modified_date) { 534 modified_date_ = modified_date; 535 } 536 void set_last_viewed_by_me_date(const base::Time& last_viewed_by_me_date) { 537 last_viewed_by_me_date_ = last_viewed_by_me_date; 538 } 539 void set_shared_with_me_date(const base::Time& shared_with_me_date) { 540 shared_with_me_date_ = shared_with_me_date; 541 } 542 void set_shared(bool shared) { 543 shared_ = shared; 544 } 545 void set_md5_checksum(const std::string& md5_checksum) { 546 md5_checksum_ = md5_checksum; 547 } 548 void set_file_size(int64 file_size) { 549 file_size_ = file_size; 550 } 551 void set_alternate_link(const GURL& alternate_link) { 552 alternate_link_ = alternate_link; 553 } 554 std::vector<ParentReference>* mutable_parents() { return &parents_; } 555 std::vector<OpenWithLink>* mutable_open_with_links() { 556 return &open_with_links_; 557 } 558 559 private: 560 friend class base::internal::RepeatedMessageConverter<FileResource>; 561 friend class ChangeResource; 562 friend class FileList; 563 564 // Parses and initializes data members from content of |value|. 565 // Return false if parsing fails. 566 bool Parse(const base::Value& value); 567 568 std::string file_id_; 569 std::string etag_; 570 std::string title_; 571 std::string mime_type_; 572 FileLabels labels_; 573 ImageMediaMetadata image_media_metadata_; 574 base::Time created_date_; 575 base::Time modified_date_; 576 base::Time last_viewed_by_me_date_; 577 base::Time shared_with_me_date_; 578 bool shared_; 579 std::string md5_checksum_; 580 int64 file_size_; 581 GURL alternate_link_; 582 std::vector<ParentReference> parents_; 583 std::vector<OpenWithLink> open_with_links_; 584 }; 585 586 // FileList represents a collection of files and folders. 587 // https://developers.google.com/drive/v2/reference/files/list 588 class FileList { 589 public: 590 FileList(); 591 ~FileList(); 592 593 // Registers the mapping between JSON field names and the members in this 594 // class. 595 static void RegisterJSONConverter( 596 base::JSONValueConverter<FileList>* converter); 597 598 // Returns true if the |value| has kind field for FileList. 599 static bool HasFileListKind(const base::Value& value); 600 601 // Creates file list from parsed JSON. 602 static scoped_ptr<FileList> CreateFrom(const base::Value& value); 603 604 // Returns a link to the next page of files. The URL includes the next page 605 // token. 606 const GURL& next_link() const { return next_link_; } 607 608 // Returns a set of files in this list. 609 const ScopedVector<FileResource>& items() const { return items_; } 610 ScopedVector<FileResource>* mutable_items() { return &items_; } 611 612 void set_next_link(const GURL& next_link) { 613 next_link_ = next_link; 614 } 615 616 private: 617 friend class DriveAPIParserTest; 618 FRIEND_TEST_ALL_PREFIXES(DriveAPIParserTest, FileListParser); 619 620 // Parses and initializes data members from content of |value|. 621 // Return false if parsing fails. 622 bool Parse(const base::Value& value); 623 624 GURL next_link_; 625 ScopedVector<FileResource> items_; 626 627 DISALLOW_COPY_AND_ASSIGN(FileList); 628 }; 629 630 // ChangeResource represents a change in a file. 631 // https://developers.google.com/drive/v2/reference/changes 632 class ChangeResource { 633 public: 634 ChangeResource(); 635 ~ChangeResource(); 636 637 // Registers the mapping between JSON field names and the members in this 638 // class. 639 static void RegisterJSONConverter( 640 base::JSONValueConverter<ChangeResource>* converter); 641 642 // Creates change resource from parsed JSON. 643 static scoped_ptr<ChangeResource> CreateFrom(const base::Value& value); 644 645 // Returns change ID for this change. This is a monotonically increasing 646 // number. 647 int64 change_id() const { return change_id_; } 648 649 // Returns a string file ID for corresponding file of the change. 650 const std::string& file_id() const { return file_id_; } 651 652 // Returns true if this file is deleted in the change. 653 bool is_deleted() const { return deleted_; } 654 655 // Returns FileResource of the file which the change refers to. 656 const FileResource* file() const { return file_.get(); } 657 FileResource* mutable_file() { return file_.get(); } 658 659 // Returns the time of this modification. 660 const base::Time& modification_date() const { return modification_date_; } 661 662 void set_change_id(int64 change_id) { 663 change_id_ = change_id; 664 } 665 void set_file_id(const std::string& file_id) { 666 file_id_ = file_id; 667 } 668 void set_deleted(bool deleted) { 669 deleted_ = deleted; 670 } 671 void set_file(scoped_ptr<FileResource> file) { 672 file_ = file.Pass(); 673 } 674 void set_modification_date(const base::Time& modification_date) { 675 modification_date_ = modification_date; 676 } 677 678 private: 679 friend class base::internal::RepeatedMessageConverter<ChangeResource>; 680 friend class ChangeList; 681 682 // Parses and initializes data members from content of |value|. 683 // Return false if parsing fails. 684 bool Parse(const base::Value& value); 685 686 int64 change_id_; 687 std::string file_id_; 688 bool deleted_; 689 scoped_ptr<FileResource> file_; 690 base::Time modification_date_; 691 692 DISALLOW_COPY_AND_ASSIGN(ChangeResource); 693 }; 694 695 // ChangeList represents a set of changes in the drive. 696 // https://developers.google.com/drive/v2/reference/changes/list 697 class ChangeList { 698 public: 699 ChangeList(); 700 ~ChangeList(); 701 702 // Registers the mapping between JSON field names and the members in this 703 // class. 704 static void RegisterJSONConverter( 705 base::JSONValueConverter<ChangeList>* converter); 706 707 // Returns true if the |value| has kind field for ChangeList. 708 static bool HasChangeListKind(const base::Value& value); 709 710 // Creates change list from parsed JSON. 711 static scoped_ptr<ChangeList> CreateFrom(const base::Value& value); 712 713 // Returns a link to the next page of files. The URL includes the next page 714 // token. 715 const GURL& next_link() const { return next_link_; } 716 717 // Returns the largest change ID number. 718 int64 largest_change_id() const { return largest_change_id_; } 719 720 // Returns a set of changes in this list. 721 const ScopedVector<ChangeResource>& items() const { return items_; } 722 ScopedVector<ChangeResource>* mutable_items() { return &items_; } 723 724 void set_next_link(const GURL& next_link) { 725 next_link_ = next_link; 726 } 727 void set_largest_change_id(int64 largest_change_id) { 728 largest_change_id_ = largest_change_id; 729 } 730 731 private: 732 friend class DriveAPIParserTest; 733 FRIEND_TEST_ALL_PREFIXES(DriveAPIParserTest, ChangeListParser); 734 735 // Parses and initializes data members from content of |value|. 736 // Return false if parsing fails. 737 bool Parse(const base::Value& value); 738 739 GURL next_link_; 740 int64 largest_change_id_; 741 ScopedVector<ChangeResource> items_; 742 743 DISALLOW_COPY_AND_ASSIGN(ChangeList); 744 }; 745 746 } // namespace google_apis 747 748 #endif // GOOGLE_APIS_DRIVE_DRIVE_API_PARSER_H_ 749