Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: chrome/browser/chromeos/gdata/gdata_wapi_parser.h

Issue 10920091: Move Drive API files to google_apis directory (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Disable some tests Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 CHROME_BROWSER_CHROMEOS_GDATA_GDATA_WAPI_PARSER_H_
6 #define CHROME_BROWSER_CHROMEOS_GDATA_GDATA_WAPI_PARSER_H_
7
8 #include <string>
9 #include <utility>
10 #include <vector>
11
12 #include "base/compiler_specific.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/memory/scoped_vector.h"
15 #include "base/string_piece.h"
16 #include "base/time.h"
17 #include "chrome/browser/chromeos/gdata/drive_entry_kinds.h"
18 #include "googleurl/src/gurl.h"
19
20 class FilePath;
21 class Profile;
22 class XmlReader;
23
24 namespace base {
25 class Value;
26 class DictionaryValue;
27 template <class StructType>
28 class JSONValueConverter;
29
30 namespace internal {
31 template <class NestedType>
32 class RepeatedMessageConverter;
33 } // namespace internal
34
35 } // namespace base
36
37 // Defines data elements of Google Documents API as described in
38 // http://code.google.com/apis/documents/.
39 namespace gdata {
40
41 // TODO(kochi): These forward declarations will be unnecessary once
42 // http://crbug.com/142293 is resolved.
43 class ChangeList;
44 class ChangeResource;
45 class FileList;
46 class FileResource;
47
48 // Defines link (URL) of an entity (document, file, feed...). Each entity could
49 // have more than one link representing it.
50 class Link {
51 public:
52 enum LinkType {
53 LINK_UNKNOWN,
54 LINK_SELF,
55 LINK_NEXT,
56 LINK_PARENT,
57 LINK_ALTERNATE,
58 LINK_EDIT,
59 LINK_EDIT_MEDIA,
60 LINK_ALT_EDIT_MEDIA,
61 LINK_ALT_POST,
62 LINK_FEED,
63 LINK_POST,
64 LINK_BATCH,
65 LINK_RESUMABLE_EDIT_MEDIA,
66 LINK_RESUMABLE_CREATE_MEDIA,
67 LINK_TABLES_FEED,
68 LINK_WORKSHEET_FEED,
69 LINK_THUMBNAIL,
70 LINK_EMBED,
71 LINK_PRODUCT,
72 LINK_ICON,
73 LINK_OPEN_WITH,
74 };
75 Link();
76 ~Link();
77
78 // Registers the mapping between JSON field names and the members in
79 // this class.
80 static void RegisterJSONConverter(base::JSONValueConverter<Link>* converter);
81
82 // Creates document entry from parsed XML.
83 static Link* CreateFromXml(XmlReader* xml_reader);
84
85 // Type of the link.
86 LinkType type() const { return type_; }
87
88 // URL of the link.
89 const GURL& href() const { return href_; }
90
91 // Title of the link.
92 const string16& title() const { return title_; }
93
94 // For OPEN_WITH links, this contains the application ID. For all other link
95 // types, it is the empty string.
96 const std::string& app_id() const { return app_id_; }
97
98 // Link MIME type.
99 const std::string& mime_type() const { return mime_type_; }
100
101 private:
102 friend class DocumentEntry;
103 // Converts value of link.rel into LinkType. Outputs to |type| and returns
104 // true when |rel| has a valid value. Otherwise does nothing and returns
105 // false.
106 static bool GetLinkType(const base::StringPiece& rel, LinkType* type);
107
108 // Converts value of link.rel to application ID, if there is one embedded in
109 // the link.rel field. Outputs to |app_id| and returns true when |rel| has a
110 // valid value. Otherwise does nothing and returns false.
111 static bool GetAppID(const base::StringPiece& rel, std::string* app_id);
112
113 LinkType type_;
114 GURL href_;
115 string16 title_;
116 std::string app_id_;
117 std::string mime_type_;
118
119 DISALLOW_COPY_AND_ASSIGN(Link);
120 };
121
122 // Feed links define links (URLs) to special list of entries (i.e. list of
123 // previous document revisions).
124 class FeedLink {
125 public:
126 enum FeedLinkType {
127 FEED_LINK_UNKNOWN,
128 FEED_LINK_ACL,
129 FEED_LINK_REVISIONS,
130 };
131 FeedLink();
132
133 // Registers the mapping between JSON field names and the members in
134 // this class.
135 static void RegisterJSONConverter(
136 base::JSONValueConverter<FeedLink>* converter);
137
138 static FeedLink* CreateFromXml(XmlReader* xml_reader);
139
140 // MIME type of the feed.
141 FeedLinkType type() const { return type_; }
142
143 // URL of the feed.
144 const GURL& href() const { return href_; }
145
146 private:
147 friend class DocumentEntry;
148 // Converts value of gd$feedLink.rel into FeedLinkType enum.
149 // Outputs to |result| and returns true when |rel| has a valid
150 // value. Otherwise does nothing and returns false.
151 static bool GetFeedLinkType(
152 const base::StringPiece& rel, FeedLinkType* result);
153
154 FeedLinkType type_;
155 GURL href_;
156
157 DISALLOW_COPY_AND_ASSIGN(FeedLink);
158 };
159
160 // Author represents an author of an entity.
161 class Author {
162 public:
163 Author();
164
165 // Registers the mapping between JSON field names and the members in
166 // this class.
167 static void RegisterJSONConverter(
168 base::JSONValueConverter<Author>* converter);
169
170 static Author* CreateFromXml(XmlReader* xml_reader);
171
172 // Getters.
173 const string16& name() const { return name_; }
174 const std::string& email() const { return email_; }
175
176 private:
177 friend class DocumentEntry;
178
179 string16 name_;
180 std::string email_;
181
182 DISALLOW_COPY_AND_ASSIGN(Author);
183 };
184
185 // Entry category.
186 class Category {
187 public:
188 enum CategoryType {
189 CATEGORY_UNKNOWN,
190 CATEGORY_ITEM,
191 CATEGORY_KIND,
192 CATEGORY_LABEL,
193 };
194
195 Category();
196
197 // Registers the mapping between JSON field names and the members in
198 // this class.
199 static void RegisterJSONConverter(
200 base::JSONValueConverter<Category>* converter);
201
202 static Category* CreateFromXml(XmlReader* xml_reader);
203
204 // Category label.
205 const string16& label() const { return label_; }
206
207 // Category type.
208 CategoryType type() const { return type_; }
209
210 // Category term.
211 const std::string& term() const { return term_; }
212
213 private:
214 friend class DocumentEntry;
215 // Converts category scheme into CategoryType enum. For example,
216 // http://schemas.google.com/g/2005#kind => Category::CATEGORY_KIND
217 // Returns false and does not change |result| when |scheme| has an
218 // unrecognizable value.
219 static bool GetCategoryTypeFromScheme(
220 const base::StringPiece& scheme, CategoryType* result);
221
222 string16 label_;
223 CategoryType type_;
224 std::string term_;
225
226 DISALLOW_COPY_AND_ASSIGN(Category);
227 };
228
229 // Content details of a document: mime-type, url, and so on.
230 class Content {
231 public:
232 Content();
233
234 // Registers the mapping between JSON field names and the members in
235 // this class.
236 static void RegisterJSONConverter(
237 base::JSONValueConverter<Content>* converter);
238
239 static Content* CreateFromXml(XmlReader* xml_reader);
240
241 const GURL& url() const { return url_; }
242 const std::string& mime_type() const { return mime_type_; }
243
244 private:
245 friend class DocumentEntry;
246
247 GURL url_;
248 std::string mime_type_;
249 };
250
251 // This stores a representation of an application icon as registered with the
252 // installed applications section of the account metadata feed. There can be
253 // multiple icons registered for each application, differing in size, category
254 // and MIME type.
255 class AppIcon {
256 public:
257 enum IconCategory {
258 ICON_UNKNOWN, // Uninitialized state
259 ICON_DOCUMENT, // Document icon for various MIME types
260 ICON_APPLICATION, // Application icon for various MIME types
261 ICON_SHARED_DOCUMENT, // Icon for documents that are shared from other
262 // users.
263 };
264
265 AppIcon();
266 ~AppIcon();
267
268 // Registers the mapping between JSON field names and the members in
269 // this class.
270 static void RegisterJSONConverter(
271 base::JSONValueConverter<AppIcon>* converter);
272
273 // Category of the icon.
274 IconCategory category() const { return category_; }
275
276 // Size in pixels of one side of the icon (icons are always square).
277 int icon_side_length() const { return icon_side_length_; }
278
279 // Get a list of links available for this AppIcon.
280 const ScopedVector<Link>& links() const { return links_; }
281
282 // Get the icon URL from the internal list of links. Returns the first
283 // icon URL found in the list.
284 GURL GetIconURL() const;
285
286 private:
287 // Extracts the icon category from the given string. Returns false and does
288 // not change |result| when |scheme| has an unrecognizable value.
289 static bool GetIconCategory(const base::StringPiece& category,
290 IconCategory* result);
291
292 IconCategory category_;
293 int icon_side_length_;
294 ScopedVector<Link> links_;
295
296 DISALLOW_COPY_AND_ASSIGN(AppIcon);
297 };
298
299 // Base class for feed entries.
300 class FeedEntry {
301 public:
302 FeedEntry();
303 virtual ~FeedEntry();
304
305 // Returns a link of a given |type| for this entry. If not found, it returns
306 // NULL.
307 const Link* GetLinkByType(Link::LinkType type) const;
308
309 // Entry update time.
310 base::Time updated_time() const { return updated_time_; }
311
312 // Entry ETag.
313 const std::string& etag() const { return etag_; }
314
315 // List of entry authors.
316 const ScopedVector<Author>& authors() const { return authors_; }
317
318 // List of entry links.
319 const ScopedVector<Link>& links() const { return links_; }
320
321 // List of entry categories.
322 const ScopedVector<Category>& categories() const { return categories_; }
323
324 // Registers the mapping between JSON field names and the members in
325 // this class.
326 static void RegisterJSONConverter(
327 base::JSONValueConverter<FeedEntry>* converter);
328
329 protected:
330 std::string etag_;
331 ScopedVector<Author> authors_;
332 ScopedVector<Link> links_;
333 ScopedVector<Category> categories_;
334 base::Time updated_time_;
335
336 DISALLOW_COPY_AND_ASSIGN(FeedEntry);
337 };
338
339 // Document feed entry.
340 class DocumentEntry : public FeedEntry {
341 public:
342 virtual ~DocumentEntry();
343
344 // Extracts "entry" dictionary from the JSON value, and parse the contents,
345 // using CreateFrom(). Returns NULL on failure. The input JSON data, coming
346 // from the gdata server, looks like:
347 //
348 // {
349 // "encoding": "UTF-8",
350 // "entry": { ... }, // This function will extract this and parse.
351 // "version": "1.0"
352 // }
353 //
354 // The caller should delete the returned object.
355 static DocumentEntry* ExtractAndParse(const base::Value& value);
356
357 // Creates document entry from parsed JSON Value. You should call
358 // this instead of instantiating JSONValueConverter by yourself
359 // because this method does some post-process for some fields. See
360 // FillRemainingFields comment and implementation for the details.
361 static DocumentEntry* CreateFrom(const base::Value& value);
362
363 // Creates document entry from parsed XML.
364 static DocumentEntry* CreateFromXml(XmlReader* xml_reader);
365
366 // Creates document entry from FileResource.
367 // TODO(kochi): This should go away soon. http://crbug.com/142293
368 static DocumentEntry* CreateFromFileResource(const FileResource& file);
369
370 // Creates document entry from ChangeResource.
371 // Todo(Kochi): This should go away soon. http://crbug.com/142293
372 static DocumentEntry* CreateFromChangeResource(const ChangeResource& change);
373
374 // Returns name of entry node.
375 static std::string GetEntryNodeName();
376
377 // Registers the mapping between JSON field names and the members in
378 // this class.
379 static void RegisterJSONConverter(
380 base::JSONValueConverter<DocumentEntry>* converter);
381
382 // Helper function for parsing bool fields based on presence of
383 // their value nodes.
384 static bool HasFieldPresent(const base::Value* value, bool* result);
385
386 // Returns true if |file| has one of the hosted document extensions.
387 static bool HasHostedDocumentExtension(const FilePath& file);
388
389 // Document entry resource id.
390 const std::string& resource_id() const { return resource_id_; }
391
392 // Document entry id.
393 const std::string& id() const { return id_; }
394
395 // Document entry kind.
396 DriveEntryKind kind() const { return kind_; }
397
398 // Document entry title.
399 const string16& title() const { return title_; }
400
401 // Document entry published time.
402 base::Time published_time() const { return published_time_; }
403
404 // List of document feed labels.
405 const std::vector<string16>& labels() const { return labels_; }
406
407 // Document entry content URL.
408 const GURL& content_url() const { return content_.url(); }
409
410 // Document entry MIME type.
411 const std::string& content_mime_type() const { return content_.mime_type(); }
412
413 // List of document feed links.
414 const ScopedVector<FeedLink>& feed_links() const { return feed_links_; }
415
416 // Document feed file name (exists only for kinds FILE and PDF).
417 const string16& filename() const { return filename_; }
418
419 // Document feed suggested file name (exists only for kinds FILE and PDF).
420 const string16& suggested_filename() const { return suggested_filename_; }
421
422 // Document feed file content MD5 (exists only for kinds FILE and PDF).
423 const std::string& file_md5() const { return file_md5_; }
424
425 // Document feed file size (exists only for kinds FILE and PDF).
426 int64 file_size() const { return file_size_; }
427
428 // True if the file or directory is deleted (applicable to change feeds only).
429 bool deleted() const { return deleted_ || removed_; }
430
431 // Text version of document entry kind. Returns an empty string for
432 // unknown entry kind.
433 std::string GetEntryKindText() const;
434
435 // Returns preferred file extension for hosted documents. If entry is not
436 // a hosted document, this call returns an empty string.
437 std::string GetHostedDocumentExtension() const;
438
439 // True if document entry is remotely hosted.
440 bool is_hosted_document() const {
441 return ClassifyEntryKind(kind_) & KIND_OF_HOSTED_DOCUMENT;
442 }
443 // True if document entry hosted by Google Documents.
444 bool is_google_document() const {
445 return ClassifyEntryKind(kind_) & KIND_OF_GOOGLE_DOCUMENT;
446 }
447 // True if document entry is hosted by an external application.
448 bool is_external_document() const {
449 return ClassifyEntryKind(kind_) & KIND_OF_EXTERNAL_DOCUMENT;
450 }
451 // True if document entry is a folder (collection).
452 bool is_folder() const { return ClassifyEntryKind(kind_) & KIND_OF_FOLDER; }
453 // True if document entry is regular file.
454 bool is_file() const { return ClassifyEntryKind(kind_) & KIND_OF_FILE; }
455 // True if document entry can't be mapped to the file system.
456 bool is_special() const {
457 return !is_file() && !is_folder() && !is_hosted_document();
458 }
459
460 // The following constructs are exposed for unit tests.
461
462 // Classes of EntryKind. Used for ClassifyEntryKind().
463 enum EntryKindClass {
464 KIND_OF_NONE = 0,
465 KIND_OF_HOSTED_DOCUMENT = 1,
466 KIND_OF_GOOGLE_DOCUMENT = 1 << 1,
467 KIND_OF_EXTERNAL_DOCUMENT = 1 << 2,
468 KIND_OF_FOLDER = 1 << 3,
469 KIND_OF_FILE = 1 << 4,
470 };
471
472 // Classifies the EntryKind. The returned value is a bitmask of
473 // EntryKindClass. For example, DOCUMENT is classified as
474 // KIND_OF_HOSTED_DOCUMENT and KIND_OF_GOOGLE_DOCUMENT, hence the returned
475 // value is KIND_OF_HOSTED_DOCUMENT | KIND_OF_GOOGLE_DOCUMENT.
476 static int ClassifyEntryKind(DriveEntryKind kind);
477
478 private:
479 friend class base::internal::RepeatedMessageConverter<DocumentEntry>;
480 friend class DocumentFeed;
481 friend class ResumeUploadOperation;
482
483 DocumentEntry();
484
485 // Fills the remaining fields where JSONValueConverter cannot catch.
486 void FillRemainingFields();
487
488 // Converts categories.term into DriveEntryKind enum.
489 static DriveEntryKind GetEntryKindFromTerm(const std::string& term);
490 // Converts |kind| into its text identifier equivalent.
491 static const char* GetEntryKindDescription(DriveEntryKind kind);
492
493 std::string resource_id_;
494 std::string id_;
495 DriveEntryKind kind_;
496 string16 title_;
497 base::Time published_time_;
498 std::vector<string16> labels_;
499 Content content_;
500 ScopedVector<FeedLink> feed_links_;
501 // Optional fields for files only.
502 string16 filename_;
503 string16 suggested_filename_;
504 std::string file_md5_;
505 int64 file_size_;
506 bool deleted_;
507 bool removed_;
508
509 DISALLOW_COPY_AND_ASSIGN(DocumentEntry);
510 };
511
512 // Document feed represents a list of entries. The feed is paginated and
513 // the rest of the feed can be fetched by retrieving the remaining parts of the
514 // feed from URLs provided by GetNextFeedURL() method.
515 class DocumentFeed : public FeedEntry {
516 public:
517 virtual ~DocumentFeed();
518
519 // Extracts "feed" dictionary from the JSON value, and parse the contents,
520 // using CreateFrom(). Returns NULL on failure. The input JSON data, coming
521 // from the gdata server, looks like:
522 //
523 // {
524 // "encoding": "UTF-8",
525 // "feed": { ... }, // This function will extract this and parse.
526 // "version": "1.0"
527 // }
528 static scoped_ptr<DocumentFeed> ExtractAndParse(const base::Value& value);
529
530 // Creates feed from parsed JSON Value. You should call this
531 // instead of instantiating JSONValueConverter by yourself because
532 // this method does some post-process for some fields. See
533 // FillRemainingFields comment and implementation in DocumentEntry
534 // class for the details.
535 static scoped_ptr<DocumentFeed> CreateFrom(const base::Value& value);
536 // Variant of CreateFrom() above, creates feed from parsed ChangeList.
537 // TODO(kochi): This should go away soon. http://crbug.com/142293
538 static scoped_ptr<DocumentFeed> CreateFromChangeList(
539 const ChangeList& changelist);
540
541 // Registers the mapping between JSON field names and the members in
542 // this class.
543 static void RegisterJSONConverter(
544 base::JSONValueConverter<DocumentFeed>* converter);
545
546 // Returns true and passes|url| of the next feed if the current entry list
547 // does not completed this feed.
548 bool GetNextFeedURL(GURL* url);
549
550 // List of document entries.
551 const ScopedVector<DocumentEntry>& entries() const { return entries_; }
552
553 // Releases entries_ into |entries|. This is a transfer of ownership, so the
554 // caller is responsible for deleting the elements of |entries|.
555 void ReleaseEntries(std::vector<DocumentEntry*>* entries);
556
557 // Start index of the document entry list.
558 int start_index() const { return start_index_; }
559
560 // Number of items per feed of the document entry list.
561 int items_per_page() const { return items_per_page_; }
562
563 // The largest changestamp. Next time the documents should be fetched
564 // from this changestamp.
565 int64 largest_changestamp() const { return largest_changestamp_; }
566
567 // Document entry list title.
568 const std::string& title() { return title_; }
569
570 private:
571 DocumentFeed();
572
573 // Parses and initializes data members from content of |value|.
574 // Return false if parsing fails.
575 bool Parse(const base::Value& value);
576
577 ScopedVector<DocumentEntry> entries_;
578 int start_index_;
579 int items_per_page_;
580 std::string title_;
581 int64 largest_changestamp_;
582
583 DISALLOW_COPY_AND_ASSIGN(DocumentFeed);
584 };
585
586 // Metadata representing installed Google Drive application.
587 class InstalledApp {
588 public:
589 typedef std::vector<std::pair<int, GURL> > IconList;
590
591 InstalledApp();
592 virtual ~InstalledApp();
593
594 // WebApp name.
595 const string16& app_name() const { return app_name_; }
596
597 // Drive app id
598 const std::string& app_id() const { return app_id_; }
599
600 // Object (file) type name that is generated by this WebApp.
601 const string16& object_type() const { return object_type_; }
602
603 // True if WebApp supports creation of new file instances.
604 bool supports_create() const { return supports_create_; }
605
606 // List of primary mime types supported by this WebApp. Primary status should
607 // trigger this WebApp becoming the default handler of file instances that
608 // have these mime types.
609 const ScopedVector<std::string>& primary_mimetypes() const {
610 return primary_mimetypes_;
611 }
612
613 // List of secondary mime types supported by this WebApp. Secondary status
614 // should make this WebApp show up in "Open with..." pop-up menu of the
615 // default action menu for file with matching mime types.
616 const ScopedVector<std::string>& secondary_mimetypes() const {
617 return secondary_mimetypes_;
618 }
619
620 // List of primary file extensions supported by this WebApp. Primary status
621 // should trigger this WebApp becoming the default handler of file instances
622 // that match these extensions.
623 const ScopedVector<std::string>& primary_extensions() const {
624 return primary_extensions_;
625 }
626
627 // List of secondary file extensions supported by this WebApp. Secondary
628 // status should make this WebApp show up in "Open with..." pop-up menu of the
629 // default action menu for file with matching extensions.
630 const ScopedVector<std::string>& secondary_extensions() const {
631 return secondary_extensions_;
632 }
633
634 // List of entry links.
635 const ScopedVector<Link>& links() const { return links_; }
636
637 // Returns a list of icons associated with this installed application.
638 const ScopedVector<AppIcon>& app_icons() const {
639 return app_icons_;
640 }
641
642 // Convenience function for getting the icon URLs for a particular |category|
643 // of icon. Icons are returned in a sorted list, from smallest to largest.
644 IconList GetIconsForCategory(AppIcon::IconCategory category) const;
645
646 // Retrieves product URL from the link collection.
647 GURL GetProductUrl() const;
648
649 // Registers the mapping between JSON field names and the members in
650 // this class.
651 static void RegisterJSONConverter(
652 base::JSONValueConverter<InstalledApp>* converter);
653
654 private:
655 // Extracts "$t" value from the dictionary |value| and returns it in |result|.
656 // If the string value can't be found, it returns false.
657 static bool GetValueString(const base::Value* value,
658 std::string* result);
659
660 std::string app_id_;
661 string16 app_name_;
662 string16 object_type_;
663 bool supports_create_;
664 ScopedVector<std::string> primary_mimetypes_;
665 ScopedVector<std::string> secondary_mimetypes_;
666 ScopedVector<std::string> primary_extensions_;
667 ScopedVector<std::string> secondary_extensions_;
668 ScopedVector<Link> links_;
669 ScopedVector<AppIcon> app_icons_;
670 };
671
672 // Account metadata feed represents the metadata object attached to the user's
673 // account.
674 class AccountMetadataFeed {
675 public:
676 virtual ~AccountMetadataFeed();
677
678 // Creates feed from parsed JSON Value. You should call this
679 // instead of instantiating JSONValueConverter by yourself because
680 // this method does some post-process for some fields. See
681 // FillRemainingFields comment and implementation in DocumentEntry
682 // class for the details.
683 static scoped_ptr<AccountMetadataFeed> CreateFrom(const base::Value& value);
684
685 int64 quota_bytes_total() const {
686 return quota_bytes_total_;
687 }
688
689 int64 quota_bytes_used() const {
690 return quota_bytes_used_;
691 }
692
693 int64 largest_changestamp() const {
694 return largest_changestamp_;
695 }
696
697 const ScopedVector<InstalledApp>& installed_apps() const {
698 return installed_apps_;
699 }
700
701 // Registers the mapping between JSON field names and the members in
702 // this class.
703 static void RegisterJSONConverter(
704 base::JSONValueConverter<AccountMetadataFeed>* converter);
705
706 private:
707 AccountMetadataFeed();
708
709 // Parses and initializes data members from content of |value|.
710 // Return false if parsing fails.
711 bool Parse(const base::Value& value);
712
713 int64 quota_bytes_total_;
714 int64 quota_bytes_used_;
715 int64 largest_changestamp_;
716 ScopedVector<InstalledApp> installed_apps_;
717
718 DISALLOW_COPY_AND_ASSIGN(AccountMetadataFeed);
719 };
720
721
722 } // namespace gdata
723
724 #endif // CHROME_BROWSER_CHROMEOS_GDATA_GDATA_WAPI_PARSER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698