| Index: chrome/browser/chromeos/gdata/gdata_parser.cc
|
| diff --git a/chrome/browser/chromeos/gdata/gdata_parser.cc b/chrome/browser/chromeos/gdata/gdata_parser.cc
|
| deleted file mode 100644
|
| index 1d8e38cca6a325a26a1dce4668958b9fa438ce17..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/chromeos/gdata/gdata_parser.cc
|
| +++ /dev/null
|
| @@ -1,1056 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/chromeos/gdata/gdata_parser.h"
|
| -
|
| -#include <algorithm>
|
| -
|
| -#include "base/basictypes.h"
|
| -#include "base/file_path.h"
|
| -#include "base/json/json_value_converter.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/string_number_conversions.h"
|
| -#include "base/string_piece.h"
|
| -#include "base/string_util.h"
|
| -#include "base/utf_string_conversions.h"
|
| -#include "base/values.h"
|
| -#include "third_party/libxml/chromium/libxml_utils.h"
|
| -
|
| -using base::Value;
|
| -using base::DictionaryValue;
|
| -using base::ListValue;
|
| -
|
| -namespace gdata {
|
| -
|
| -namespace {
|
| -
|
| -// Term values for kSchemeKind category:
|
| -const char kSchemeKind[] = "http://schemas.google.com/g/2005#kind";
|
| -const char kTermPrefix[] = "http://schemas.google.com/docs/2007#";
|
| -const char kFileTerm[] = "file";
|
| -const char kFolderTerm[] = "folder";
|
| -const char kItemTerm[] = "item";
|
| -const char kPdfTerm[] = "pdf";
|
| -const char kDocumentTerm[] = "document";
|
| -const char kSpreadSheetTerm[] = "spreadsheet";
|
| -const char kPresentationTerm[] = "presentation";
|
| -
|
| -const char kSchemeLabels[] = "http://schemas.google.com/g/2005/labels";
|
| -
|
| -// Node names.
|
| -const char kAuthorNode[] = "author";
|
| -const char kCategoryNode[] = "category";
|
| -const char kContentNode[] = "content";
|
| -const char kEditedNode[] = "edited";
|
| -const char kEmailNode[] = "email";
|
| -const char kEntryNode[] = "entry";
|
| -const char kFeedLinkNode[] = "feedLink";
|
| -const char kFilenameNode[] = "filename";
|
| -const char kIDNode[] = "id";
|
| -const char kLastModifiedByNode[] = "lastModifiedBy";
|
| -const char kLinkNode[] = "link";
|
| -const char kMd5ChecksumNode[] = "md5Checksum";
|
| -const char kModifiedByMeDateNode[] = "modifiedByMeDate";
|
| -const char kNameNode[] = "name";
|
| -const char kPublishedNode[] = "published";
|
| -const char kQuotaBytesUsedNode[] = "quotaBytesUsed";
|
| -const char kResourceIdNode[] = "resourceId";
|
| -const char kSizeNode[] = "size";
|
| -const char kSuggestedFilenameNode[] = "suggestedFilename";
|
| -const char kTitleNode[] = "title";
|
| -const char kUpdatedNode[] = "updated";
|
| -const char kWritersCanInviteNode[] = "writersCanInvite";
|
| -
|
| -// Field names.
|
| -const char kAuthorField[] = "author";
|
| -const char kCategoryField[] = "category";
|
| -const char kContentField[] = "content";
|
| -const char kDeletedField[] = "gd$deleted";
|
| -const char kETagField[] = "gd$etag";
|
| -const char kEmailField[] = "email.$t";
|
| -const char kEntryField[] = "entry";
|
| -const char kFeedField[] = "feed";
|
| -const char kFeedLinkField[] = "gd$feedLink";
|
| -const char kFileNameField[] = "docs$filename.$t";
|
| -const char kHrefField[] = "href";
|
| -const char kIDField[] = "id.$t";
|
| -const char kInstalledAppField[] = "docs$installedApp";
|
| -const char kInstalledAppNameField[] = "docs$installedAppName";
|
| -const char kInstalledAppIdField[] = "docs$installedAppId";
|
| -const char kInstalledAppIconField[] = "docs$installedAppIcon";
|
| -const char kInstalledAppIconCategoryField[] = "docs$installedAppIconCategory";
|
| -const char kInstalledAppIconSizeField[] = "docs$installedAppIconSize";
|
| -const char kInstalledAppObjectTypeField[] = "docs$installedAppObjectType";
|
| -const char kInstalledAppPrimaryFileExtensionField[] =
|
| - "docs$installedAppPrimaryFileExtension";
|
| -const char kInstalledAppPrimaryMimeTypeField[] =
|
| - "docs$installedAppPrimaryMimeType";
|
| -const char kInstalledAppSecondaryFileExtensionField[] =
|
| - "docs$installedAppSecondaryFileExtension";
|
| -const char kInstalledAppSecondaryMimeTypeField[] =
|
| - "docs$installedAppSecondaryMimeType";
|
| -const char kInstalledAppSupportsCreateField[] =
|
| - "docs$installedAppSupportsCreate";
|
| -const char kItemsPerPageField[] = "openSearch$itemsPerPage.$t";
|
| -const char kLabelField[] = "label";
|
| -const char kLargestChangestampField[] = "docs$largestChangestamp.value";
|
| -const char kLinkField[] = "link";
|
| -const char kMD5Field[] = "docs$md5Checksum.$t";
|
| -const char kNameField[] = "name.$t";
|
| -const char kPublishedField[] = "published.$t";
|
| -const char kQuotaBytesTotalField[] = "gd$quotaBytesTotal.$t";
|
| -const char kQuotaBytesUsedField[] = "gd$quotaBytesUsed.$t";
|
| -const char kRelField[] = "rel";
|
| -const char kRemovedField[] = "gd$removed";
|
| -const char kResourceIdField[] = "gd$resourceId.$t";
|
| -const char kSchemeField[] = "scheme";
|
| -const char kSizeField[] = "docs$size.$t";
|
| -const char kSrcField[] = "src";
|
| -const char kStartIndexField[] = "openSearch$startIndex.$t";
|
| -const char kSuggestedFileNameField[] = "docs$suggestedFilename.$t";
|
| -const char kTField[] = "$t";
|
| -const char kTermField[] = "term";
|
| -const char kTitleField[] = "title";
|
| -const char kTitleTField[] = "title.$t";
|
| -const char kTypeField[] = "type";
|
| -const char kUpdatedField[] = "updated.$t";
|
| -
|
| -// Attribute names.
|
| -// Attributes are not namespace-blind as node names in XmlReader.
|
| -const char kETagAttr[] = "gd:etag";
|
| -const char kEmailAttr[] = "email";
|
| -const char kHrefAttr[] = "href";
|
| -const char kLabelAttr[] = "label";
|
| -const char kNameAttr[] = "name";
|
| -const char kRelAttr[] = "rel";
|
| -const char kSchemeAttr[] = "scheme";
|
| -const char kSrcAttr[] = "src";
|
| -const char kTermAttr[] = "term";
|
| -const char kTypeAttr[] = "type";
|
| -const char kValueAttr[] = "value";
|
| -
|
| -// Link Prefixes
|
| -const char kOpenWithPrefix[] = "http://schemas.google.com/docs/2007#open-with-";
|
| -const size_t kOpenWithPrefixSize = arraysize(kOpenWithPrefix) - 1;
|
| -
|
| -struct EntryKindMap {
|
| - DocumentEntry::EntryKind kind;
|
| - const char* entry;
|
| - const char* extension;
|
| -};
|
| -
|
| -const EntryKindMap kEntryKindMap[] = {
|
| - { DocumentEntry::ITEM, "item", NULL},
|
| - { DocumentEntry::DOCUMENT, "document", ".gdoc"},
|
| - { DocumentEntry::SPREADSHEET, "spreadsheet", ".gsheet"},
|
| - { DocumentEntry::PRESENTATION, "presentation", ".gslides" },
|
| - { DocumentEntry::DRAWING, "drawing", ".gdraw"},
|
| - { DocumentEntry::TABLE, "table", ".gtable"},
|
| - { DocumentEntry::EXTERNAL_APP, "externalapp", ".glink"},
|
| - { DocumentEntry::SITE, "site", NULL},
|
| - { DocumentEntry::FOLDER, "folder", NULL},
|
| - { DocumentEntry::FILE, "file", NULL},
|
| - { DocumentEntry::PDF, "pdf", NULL},
|
| -};
|
| -
|
| -struct LinkTypeMap {
|
| - Link::LinkType type;
|
| - const char* rel;
|
| -};
|
| -
|
| -const LinkTypeMap kLinkTypeMap[] = {
|
| - { Link::SELF,
|
| - "self" },
|
| - { Link::NEXT,
|
| - "next" },
|
| - { Link::PARENT,
|
| - "http://schemas.google.com/docs/2007#parent" },
|
| - { Link::ALTERNATE,
|
| - "alternate"},
|
| - { Link::EDIT,
|
| - "edit" },
|
| - { Link::EDIT_MEDIA,
|
| - "edit-media" },
|
| - { Link::ALT_EDIT_MEDIA,
|
| - "http://schemas.google.com/docs/2007#alt-edit-media" },
|
| - { Link::ALT_POST,
|
| - "http://schemas.google.com/docs/2007#alt-post" },
|
| - { Link::FEED,
|
| - "http://schemas.google.com/g/2005#feed"},
|
| - { Link::POST,
|
| - "http://schemas.google.com/g/2005#post"},
|
| - { Link::BATCH,
|
| - "http://schemas.google.com/g/2005#batch"},
|
| - { Link::THUMBNAIL,
|
| - "http://schemas.google.com/docs/2007/thumbnail"},
|
| - { Link::RESUMABLE_EDIT_MEDIA,
|
| - "http://schemas.google.com/g/2005#resumable-edit-media"},
|
| - { Link::RESUMABLE_CREATE_MEDIA,
|
| - "http://schemas.google.com/g/2005#resumable-create-media"},
|
| - { Link::TABLES_FEED,
|
| - "http://schemas.google.com/spreadsheets/2006#tablesfeed"},
|
| - { Link::WORKSHEET_FEED,
|
| - "http://schemas.google.com/spreadsheets/2006#worksheetsfeed"},
|
| - { Link::EMBED,
|
| - "http://schemas.google.com/docs/2007#embed"},
|
| - { Link::PRODUCT,
|
| - "http://schemas.google.com/docs/2007#product"},
|
| - { Link::ICON,
|
| - "http://schemas.google.com/docs/2007#icon"},
|
| -};
|
| -
|
| -struct FeedLinkTypeMap {
|
| - FeedLink::FeedLinkType type;
|
| - const char* rel;
|
| -};
|
| -
|
| -const FeedLinkTypeMap kFeedLinkTypeMap[] = {
|
| - { FeedLink::ACL, "http://schemas.google.com/acl/2007#accessControlList" },
|
| - { FeedLink::REVISIONS, "http://schemas.google.com/docs/2007/revisions" },
|
| -};
|
| -
|
| -struct CategoryTypeMap {
|
| - Category::CategoryType type;
|
| - const char* scheme;
|
| -};
|
| -
|
| -const CategoryTypeMap kCategoryTypeMap[] = {
|
| - { Category::KIND, "http://schemas.google.com/g/2005#kind" },
|
| - { Category::LABEL, "http://schemas.google.com/g/2005/labels" },
|
| -};
|
| -
|
| -struct AppIconCategoryMap {
|
| - AppIcon::IconCategory category;
|
| - const char* category_name;
|
| -};
|
| -
|
| -const AppIconCategoryMap kAppIconCategoryMap[] = {
|
| - { AppIcon::DOCUMENT, "document" },
|
| - { AppIcon::APPLICATION, "application" },
|
| - { AppIcon::SHARED_DOCUMENT, "documentShared" },
|
| -};
|
| -
|
| -// 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(const base::StringPiece& url_string, GURL* result) {
|
| - *result = GURL(url_string.as_string());
|
| - return true;
|
| -}
|
| -
|
| -// Converts boolean string values like "true" into bool.
|
| -bool GetBoolFromString(const base::StringPiece& value, bool* result) {
|
| - *result = (value == "true");
|
| - return true;
|
| -}
|
| -
|
| -bool SortBySize(const InstalledApp::IconList::value_type& a,
|
| - const InstalledApp::IconList::value_type& b) {
|
| - return a.first < b.first;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// Author implementation
|
| -
|
| -Author::Author() {
|
| -}
|
| -
|
| -// static
|
| -void Author::RegisterJSONConverter(
|
| - base::JSONValueConverter<Author>* converter) {
|
| - converter->RegisterStringField(kNameField, &Author::name_);
|
| - converter->RegisterStringField(kEmailField, &Author::email_);
|
| -}
|
| -
|
| -Author* Author::CreateFromXml(XmlReader* xml_reader) {
|
| - if (xml_reader->NodeName() != kAuthorNode)
|
| - return NULL;
|
| -
|
| - if (!xml_reader->Read())
|
| - return NULL;
|
| -
|
| - const int depth = xml_reader->Depth();
|
| - Author* author = new Author();
|
| - bool skip_read = false;
|
| - do {
|
| - skip_read = false;
|
| - DVLOG(1) << "Parsing author node " << xml_reader->NodeName()
|
| - << ", depth = " << depth;
|
| - if (xml_reader->NodeName() == kNameNode) {
|
| - std::string name;
|
| - if (xml_reader->ReadElementContent(&name))
|
| - author->name_ = UTF8ToUTF16(name);
|
| - skip_read = true;
|
| - } else if (xml_reader->NodeName() == kEmailNode) {
|
| - xml_reader->ReadElementContent(&author->email_);
|
| - skip_read = true;
|
| - }
|
| - } while (depth == xml_reader->Depth() && (skip_read || xml_reader->Next()));
|
| - return author;
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// Link implementation
|
| -
|
| -Link::Link() : type_(Link::UNKNOWN) {
|
| -}
|
| -
|
| -Link::~Link() {
|
| -}
|
| -
|
| -// static
|
| -bool Link::GetAppID(const base::StringPiece& rel, std::string* app_id) {
|
| - DCHECK(app_id);
|
| - // Fast return path if the link clearly isn't an OPEN_WITH link.
|
| - if (rel.size() < kOpenWithPrefixSize) {
|
| - app_id->clear();
|
| - return true;
|
| - }
|
| -
|
| - const std::string kOpenWithPrefixStr(kOpenWithPrefix);
|
| - if (StartsWithASCII(rel.as_string(), kOpenWithPrefixStr, false)) {
|
| - *app_id = rel.as_string().substr(kOpenWithPrefixStr.size());
|
| - return true;
|
| - }
|
| -
|
| - app_id->clear();
|
| - return true;
|
| -}
|
| -
|
| -// static.
|
| -bool Link::GetLinkType(const base::StringPiece& rel, Link::LinkType* type) {
|
| - DCHECK(type);
|
| - for (size_t i = 0; i < arraysize(kLinkTypeMap); i++) {
|
| - if (rel == kLinkTypeMap[i].rel) {
|
| - *type = kLinkTypeMap[i].type;
|
| - return true;
|
| - }
|
| - }
|
| -
|
| - // OPEN_WITH links have extra information at the end of the rel that is unique
|
| - // for each one, so we can't just check the usual map. This check is slightly
|
| - // redundant to provide a quick skip if it's obviously not an OPEN_WITH url.
|
| - if (rel.size() >= kOpenWithPrefixSize &&
|
| - StartsWithASCII(rel.as_string(), kOpenWithPrefix, false)) {
|
| - *type = OPEN_WITH;
|
| - return true;
|
| - }
|
| -
|
| - // Let unknown link types through, just report it; if the link type is needed
|
| - // in the future, add it into LinkType and kLinkTypeMap.
|
| - DVLOG(1) << "Ignoring unknown link type for rel " << rel;
|
| - *type = UNKNOWN;
|
| - return true;
|
| -}
|
| -
|
| -// static
|
| -void Link::RegisterJSONConverter(base::JSONValueConverter<Link>* converter) {
|
| - converter->RegisterCustomField<Link::LinkType>(kRelField,
|
| - &Link::type_,
|
| - &Link::GetLinkType);
|
| - // We have to register kRelField twice because we extract two different pieces
|
| - // of data from the same rel field.
|
| - converter->RegisterCustomField<std::string>(kRelField,
|
| - &Link::app_id_,
|
| - &Link::GetAppID);
|
| - converter->RegisterCustomField(kHrefField, &Link::href_, &GetGURLFromString);
|
| - converter->RegisterStringField(kTitleField, &Link::title_);
|
| - converter->RegisterStringField(kTypeField, &Link::mime_type_);
|
| -}
|
| -
|
| -// static.
|
| -Link* Link::CreateFromXml(XmlReader* xml_reader) {
|
| - if (xml_reader->NodeName() != kLinkNode)
|
| - return NULL;
|
| -
|
| - Link* link = new Link();
|
| - xml_reader->NodeAttribute(kTypeAttr, &link->mime_type_);
|
| -
|
| - std::string href;
|
| - if (xml_reader->NodeAttribute(kHrefAttr, &href))
|
| - link->href_ = GURL(href);
|
| -
|
| - std::string rel;
|
| - if (xml_reader->NodeAttribute(kRelAttr, &rel)) {
|
| - GetLinkType(rel, &link->type_);
|
| - if (link->type_ == OPEN_WITH)
|
| - GetAppID(rel, &link->app_id_);
|
| - }
|
| -
|
| - return link;
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// FeedLink implementation
|
| -
|
| -FeedLink::FeedLink() : type_(FeedLink::UNKNOWN) {
|
| -}
|
| -
|
| -// static.
|
| -bool FeedLink::GetFeedLinkType(
|
| - const base::StringPiece& rel, FeedLink::FeedLinkType* result) {
|
| - for (size_t i = 0; i < arraysize(kFeedLinkTypeMap); i++) {
|
| - if (rel == kFeedLinkTypeMap[i].rel) {
|
| - *result = kFeedLinkTypeMap[i].type;
|
| - return true;
|
| - }
|
| - }
|
| - DVLOG(1) << "Unknown feed link type for rel " << rel;
|
| - return false;
|
| -}
|
| -
|
| -// static
|
| -void FeedLink::RegisterJSONConverter(
|
| - base::JSONValueConverter<FeedLink>* converter) {
|
| - converter->RegisterCustomField<FeedLink::FeedLinkType>(
|
| - kRelField, &FeedLink::type_, &FeedLink::GetFeedLinkType);
|
| - converter->RegisterCustomField(
|
| - kHrefField, &FeedLink::href_, &GetGURLFromString);
|
| -}
|
| -
|
| -// static
|
| -FeedLink* FeedLink::CreateFromXml(XmlReader* xml_reader) {
|
| - if (xml_reader->NodeName() != kFeedLinkNode)
|
| - return NULL;
|
| -
|
| - FeedLink* link = new FeedLink();
|
| - std::string href;
|
| - if (xml_reader->NodeAttribute(kHrefAttr, &href))
|
| - link->href_ = GURL(href);
|
| -
|
| - std::string rel;
|
| - if (xml_reader->NodeAttribute(kRelAttr, &rel))
|
| - GetFeedLinkType(rel, &link->type_);
|
| -
|
| - return link;
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// Category implementation
|
| -
|
| -Category::Category() : type_(UNKNOWN) {
|
| -}
|
| -
|
| -// Converts category.scheme into CategoryType enum.
|
| -bool Category::GetCategoryTypeFromScheme(
|
| - const base::StringPiece& scheme, Category::CategoryType* result) {
|
| - for (size_t i = 0; i < arraysize(kCategoryTypeMap); i++) {
|
| - if (scheme == kCategoryTypeMap[i].scheme) {
|
| - *result = kCategoryTypeMap[i].type;
|
| - return true;
|
| - }
|
| - }
|
| - DVLOG(1) << "Unknown feed link type for scheme " << scheme;
|
| - return false;
|
| -}
|
| -
|
| -// static
|
| -void Category::RegisterJSONConverter(
|
| - base::JSONValueConverter<Category>* converter) {
|
| - converter->RegisterStringField(kLabelField, &Category::label_);
|
| - converter->RegisterCustomField<Category::CategoryType>(
|
| - kSchemeField, &Category::type_, &Category::GetCategoryTypeFromScheme);
|
| - converter->RegisterStringField(kTermField, &Category::term_);
|
| -}
|
| -
|
| -// static
|
| -Category* Category::CreateFromXml(XmlReader* xml_reader) {
|
| - if (xml_reader->NodeName() != kCategoryNode)
|
| - return NULL;
|
| -
|
| - Category* category = new Category();
|
| - xml_reader->NodeAttribute(kTermAttr, &category->term_);
|
| -
|
| - std::string scheme;
|
| - if (xml_reader->NodeAttribute(kSchemeAttr, &scheme))
|
| - GetCategoryTypeFromScheme(scheme, &category->type_);
|
| -
|
| - std::string label;
|
| - if (xml_reader->NodeAttribute(kLabelAttr, &label))
|
| - category->label_ = UTF8ToUTF16(label);
|
| -
|
| - return category;
|
| -}
|
| -
|
| -const Link* FeedEntry::GetLinkByType(Link::LinkType type) const {
|
| - for (size_t i = 0; i < links_.size(); ++i) {
|
| - if (links_[i]->type() == type)
|
| - return links_[i];
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// Content implementation
|
| -
|
| -Content::Content() {
|
| -}
|
| -
|
| -// static
|
| -void Content::RegisterJSONConverter(
|
| - base::JSONValueConverter<Content>* converter) {
|
| - converter->RegisterCustomField(kSrcField, &Content::url_, &GetGURLFromString);
|
| - converter->RegisterStringField(kTypeField, &Content::mime_type_);
|
| -}
|
| -
|
| -Content* Content::CreateFromXml(XmlReader* xml_reader) {
|
| - if (xml_reader->NodeName() != kContentNode)
|
| - return NULL;
|
| -
|
| - Content* content = new Content();
|
| - std::string src;
|
| - if (xml_reader->NodeAttribute(kSrcAttr, &src))
|
| - content->url_ = GURL(src);
|
| -
|
| - xml_reader->NodeAttribute(kTypeAttr, &content->mime_type_);
|
| - return content;
|
| -}
|
| -
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// AppIcon implementation
|
| -
|
| -AppIcon::AppIcon() : category_(AppIcon::UNKNOWN), icon_side_length_(0) {
|
| -}
|
| -
|
| -AppIcon::~AppIcon() {
|
| -}
|
| -
|
| -// static
|
| -void AppIcon::RegisterJSONConverter(
|
| - base::JSONValueConverter<AppIcon>* converter) {
|
| - converter->RegisterCustomField<AppIcon::IconCategory>(
|
| - kInstalledAppIconCategoryField,
|
| - &AppIcon::category_,
|
| - &AppIcon::GetIconCategory);
|
| - converter->RegisterCustomField<int>(kInstalledAppIconSizeField,
|
| - &AppIcon::icon_side_length_,
|
| - base::StringToInt);
|
| - converter->RegisterRepeatedMessage(kLinkField, &AppIcon::links_);
|
| -}
|
| -
|
| -GURL AppIcon::GetIconURL() const {
|
| - for (size_t i = 0; i < links_.size(); ++i) {
|
| - if (links_[i]->type() == Link::ICON)
|
| - return links_[i]->href();
|
| - }
|
| - return GURL();
|
| -}
|
| -
|
| -// static
|
| -bool AppIcon::GetIconCategory(const base::StringPiece& category,
|
| - AppIcon::IconCategory* result) {
|
| - for (size_t i = 0; i < arraysize(kAppIconCategoryMap); i++) {
|
| - if (category == kAppIconCategoryMap[i].category_name) {
|
| - *result = kAppIconCategoryMap[i].category;
|
| - return true;
|
| - }
|
| - }
|
| - DVLOG(1) << "Unknown icon category " << category;
|
| - return false;
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// FeedEntry implementation
|
| -
|
| -FeedEntry::FeedEntry() {
|
| -}
|
| -
|
| -FeedEntry::~FeedEntry() {
|
| -}
|
| -
|
| -// static
|
| -void FeedEntry::RegisterJSONConverter(
|
| - base::JSONValueConverter<FeedEntry>* converter) {
|
| - converter->RegisterStringField(kETagField, &FeedEntry::etag_);
|
| - converter->RegisterRepeatedMessage(kAuthorField, &FeedEntry::authors_);
|
| - converter->RegisterRepeatedMessage(kLinkField, &FeedEntry::links_);
|
| - converter->RegisterRepeatedMessage(kCategoryField, &FeedEntry::categories_);
|
| - converter->RegisterCustomField<base::Time>(
|
| - kUpdatedField,
|
| - &FeedEntry::updated_time_,
|
| - &FeedEntry::GetTimeFromString);
|
| -}
|
| -
|
| -// static
|
| -bool FeedEntry::GetTimeFromString(const base::StringPiece& raw_value,
|
| - base::Time* time) {
|
| - const char kTimeParsingDelimiters[] = "-:.TZ";
|
| - std::vector<base::StringPiece> parts;
|
| - if (Tokenize(raw_value, kTimeParsingDelimiters, &parts) != 7)
|
| - return false;
|
| -
|
| - base::Time::Exploded exploded;
|
| - if (!base::StringToInt(parts[0], &exploded.year) ||
|
| - !base::StringToInt(parts[1], &exploded.month) ||
|
| - !base::StringToInt(parts[2], &exploded.day_of_month) ||
|
| - !base::StringToInt(parts[3], &exploded.hour) ||
|
| - !base::StringToInt(parts[4], &exploded.minute) ||
|
| - !base::StringToInt(parts[5], &exploded.second) ||
|
| - !base::StringToInt(parts[6], &exploded.millisecond)) {
|
| - return false;
|
| - }
|
| -
|
| - exploded.day_of_week = 0;
|
| - if (!exploded.HasValidValues())
|
| - return false;
|
| -
|
| - *time = base::Time::FromLocalExploded(exploded);
|
| - return true;
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// DocumentEntry implementation
|
| -
|
| -DocumentEntry::DocumentEntry()
|
| - : kind_(DocumentEntry::UNKNOWN),
|
| - file_size_(0),
|
| - deleted_(false),
|
| - removed_(false) {
|
| -}
|
| -
|
| -DocumentEntry::~DocumentEntry() {
|
| -}
|
| -
|
| -bool DocumentEntry::HasFieldPresent(const base::Value* value,
|
| - bool* result) {
|
| - *result = (value != NULL);
|
| - return true;
|
| -}
|
| -
|
| -// static
|
| -void DocumentEntry::RegisterJSONConverter(
|
| - base::JSONValueConverter<DocumentEntry>* converter) {
|
| - // inheritant the parent registrations.
|
| - FeedEntry::RegisterJSONConverter(
|
| - reinterpret_cast<base::JSONValueConverter<FeedEntry>*>(converter));
|
| - converter->RegisterStringField(
|
| - kResourceIdField, &DocumentEntry::resource_id_);
|
| - converter->RegisterStringField(kIDField, &DocumentEntry::id_);
|
| - converter->RegisterStringField(kTitleTField, &DocumentEntry::title_);
|
| - converter->RegisterCustomField<base::Time>(
|
| - kPublishedField, &DocumentEntry::published_time_,
|
| - &FeedEntry::GetTimeFromString);
|
| - converter->RegisterRepeatedMessage(
|
| - kFeedLinkField, &DocumentEntry::feed_links_);
|
| - converter->RegisterNestedField(kContentField, &DocumentEntry::content_);
|
| -
|
| - // File properties. If the document type is not a normal file, then
|
| - // that's no problem because those feed must not have these fields
|
| - // themselves, which does not report errors.
|
| - converter->RegisterStringField(kFileNameField, &DocumentEntry::filename_);
|
| - converter->RegisterStringField(kMD5Field, &DocumentEntry::file_md5_);
|
| - converter->RegisterCustomField<int64>(
|
| - kSizeField, &DocumentEntry::file_size_, &base::StringToInt64);
|
| - converter->RegisterStringField(
|
| - kSuggestedFileNameField, &DocumentEntry::suggested_filename_);
|
| - // Deleted are treated as 'trashed' items on web client side. Removed files
|
| - // are gone for good. We treat both cases as 'deleted' for this client.
|
| - converter->RegisterCustomValueField<bool>(
|
| - kDeletedField, &DocumentEntry::deleted_, &DocumentEntry::HasFieldPresent);
|
| - converter->RegisterCustomValueField<bool>(
|
| - kRemovedField, &DocumentEntry::removed_, &DocumentEntry::HasFieldPresent);
|
| -}
|
| -
|
| -std::string DocumentEntry::GetHostedDocumentExtension() const {
|
| - for (size_t i = 0; i < arraysize(kEntryKindMap); i++) {
|
| - if (kEntryKindMap[i].kind == kind_) {
|
| - if (kEntryKindMap[i].extension)
|
| - return std::string(kEntryKindMap[i].extension);
|
| - else
|
| - return std::string();
|
| - }
|
| - }
|
| - return std::string();
|
| -}
|
| -
|
| -// static
|
| -bool DocumentEntry::HasHostedDocumentExtension(const FilePath& file) {
|
| - FilePath::StringType file_extension = file.Extension();
|
| - for (size_t i = 0; i < arraysize(kEntryKindMap); ++i) {
|
| - const char* document_extension = kEntryKindMap[i].extension;
|
| - if (document_extension && file_extension == document_extension)
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -// static
|
| -std::vector<int> DocumentEntry::GetAllEntryKinds() {
|
| - std::vector<int> entry_kinds;
|
| - entry_kinds.push_back(UNKNOWN);
|
| - for (size_t i = 0; i < arraysize(kEntryKindMap); ++i)
|
| - entry_kinds.push_back(kEntryKindMap[i].kind);
|
| - return entry_kinds;
|
| -}
|
| -
|
| -// static
|
| -DocumentEntry::EntryKind DocumentEntry::GetEntryKindFromTerm(
|
| - const std::string& term) {
|
| - if (!StartsWithASCII(term, kTermPrefix, false)) {
|
| - DVLOG(1) << "Unexpected term prefix term " << term;
|
| - return DocumentEntry::UNKNOWN;
|
| - }
|
| -
|
| - std::string type = term.substr(strlen(kTermPrefix));
|
| - for (size_t i = 0; i < arraysize(kEntryKindMap); i++) {
|
| - if (type == kEntryKindMap[i].entry)
|
| - return kEntryKindMap[i].kind;
|
| - }
|
| - DVLOG(1) << "Unknown entry type for term " << term << ", type " << type;
|
| - return DocumentEntry::UNKNOWN;
|
| -}
|
| -
|
| -void DocumentEntry::FillRemainingFields() {
|
| - // Set |kind_| and |labels_| based on the |categories_| in the class.
|
| - // JSONValueConverter does not have the ability to catch an element in a list
|
| - // based on a predicate. Thus we need to iterate over |categories_| and
|
| - // find the elements to set these fields as a post-process.
|
| - for (size_t i = 0; i < categories_.size(); ++i) {
|
| - const Category* category = categories_[i];
|
| - if (category->type() == Category::KIND)
|
| - kind_ = GetEntryKindFromTerm(category->term());
|
| - else if (category->type() == Category::LABEL)
|
| - labels_.push_back(category->label());
|
| - }
|
| -}
|
| -
|
| -// static
|
| -DocumentEntry* DocumentEntry::ExtractAndParse(
|
| - const base::Value& value) {
|
| - const base::DictionaryValue* as_dict = NULL;
|
| - base::DictionaryValue* entry_dict = NULL;
|
| - if (value.GetAsDictionary(&as_dict) &&
|
| - as_dict->GetDictionary(kEntryField, &entry_dict)) {
|
| - return DocumentEntry::CreateFrom(entry_dict);
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -// static
|
| -DocumentEntry* DocumentEntry::CreateFrom(const base::Value* value) {
|
| - base::JSONValueConverter<DocumentEntry> converter;
|
| - scoped_ptr<DocumentEntry> entry(new DocumentEntry());
|
| - if (!converter.Convert(*value, entry.get())) {
|
| - DVLOG(1) << "Invalid document entry!";
|
| - return NULL;
|
| - }
|
| -
|
| - entry->FillRemainingFields();
|
| - return entry.release();
|
| -}
|
| -
|
| -// static.
|
| -DocumentEntry* DocumentEntry::CreateFromXml(XmlReader* xml_reader) {
|
| - if (xml_reader->NodeName() != kEntryNode)
|
| - return NULL;
|
| -
|
| - DocumentEntry* entry = new DocumentEntry();
|
| - xml_reader->NodeAttribute(kETagAttr, &entry->etag_);
|
| -
|
| - if (!xml_reader->Read())
|
| - return entry;
|
| -
|
| - bool skip_read = false;
|
| - do {
|
| - DVLOG(1) << "Parsing node " << xml_reader->NodeName();
|
| - skip_read = false;
|
| -
|
| - if (xml_reader->NodeName() == kAuthorNode) {
|
| - scoped_ptr<Author> author(Author::CreateFromXml(xml_reader));
|
| - if (author.get())
|
| - entry->authors_.push_back(author.release());
|
| - }
|
| -
|
| - if (xml_reader->NodeName() == kContentNode) {
|
| - scoped_ptr<Content> content(Content::CreateFromXml(xml_reader));
|
| - if (content.get())
|
| - entry->content_ = *content.get();
|
| - } else if (xml_reader->NodeName() == kLinkNode) {
|
| - scoped_ptr<Link> link(Link::CreateFromXml(xml_reader));
|
| - if (link.get())
|
| - entry->links_.push_back(link.release());
|
| - } else if (xml_reader->NodeName() == kFeedLinkNode) {
|
| - scoped_ptr<FeedLink> link(FeedLink::CreateFromXml(xml_reader));
|
| - if (link.get())
|
| - entry->feed_links_.push_back(link.release());
|
| - } else if (xml_reader->NodeName() == kCategoryNode) {
|
| - scoped_ptr<Category> category(Category::CreateFromXml(xml_reader));
|
| - if (category.get())
|
| - entry->categories_.push_back(category.release());
|
| - } else if (xml_reader->NodeName() == kUpdatedNode) {
|
| - std::string time;
|
| - if (xml_reader->ReadElementContent(&time))
|
| - GetTimeFromString(time, &entry->updated_time_);
|
| - skip_read = true;
|
| - } else if (xml_reader->NodeName() == kPublishedNode) {
|
| - std::string time;
|
| - if (xml_reader->ReadElementContent(&time))
|
| - GetTimeFromString(time, &entry->published_time_);
|
| - skip_read = true;
|
| - } else if (xml_reader->NodeName() == kIDNode) {
|
| - xml_reader->ReadElementContent(&entry->id_);
|
| - skip_read = true;
|
| - } else if (xml_reader->NodeName() == kResourceIdNode) {
|
| - xml_reader->ReadElementContent(&entry->resource_id_);
|
| - skip_read = true;
|
| - } else if (xml_reader->NodeName() == kTitleNode) {
|
| - std::string title;
|
| - if (xml_reader->ReadElementContent(&title))
|
| - entry->title_ = UTF8ToUTF16(title);
|
| - skip_read = true;
|
| - } else if (xml_reader->NodeName() == kFilenameNode) {
|
| - std::string file_name;
|
| - if (xml_reader->ReadElementContent(&file_name))
|
| - entry->filename_ = UTF8ToUTF16(file_name);
|
| - skip_read = true;
|
| - } else if (xml_reader->NodeName() == kSuggestedFilenameNode) {
|
| - std::string suggested_filename;
|
| - if (xml_reader->ReadElementContent(&suggested_filename))
|
| - entry->suggested_filename_ = UTF8ToUTF16(suggested_filename);
|
| - skip_read = true;
|
| - } else if (xml_reader->NodeName() == kMd5ChecksumNode) {
|
| - xml_reader->ReadElementContent(&entry->file_md5_);
|
| - skip_read = true;
|
| - } else if (xml_reader->NodeName() == kSizeNode) {
|
| - std::string size;
|
| - if (xml_reader->ReadElementContent(&size))
|
| - base::StringToInt64(size, &entry->file_size_);
|
| - skip_read = true;
|
| - } else {
|
| - DVLOG(1) << "Unknown node " << xml_reader->NodeName();
|
| - }
|
| - } while (skip_read || xml_reader->Next());
|
| -
|
| - entry->FillRemainingFields();
|
| - return entry;
|
| -}
|
| -
|
| -// static
|
| -std::string DocumentEntry::GetEntryNodeName() {
|
| - return kEntryNode;
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// DocumentFeed implementation
|
| -
|
| -DocumentFeed::DocumentFeed()
|
| - : start_index_(0),
|
| - items_per_page_(0),
|
| - largest_changestamp_(0) {
|
| -}
|
| -
|
| -DocumentFeed::~DocumentFeed() {
|
| -}
|
| -
|
| -// static
|
| -void DocumentFeed::RegisterJSONConverter(
|
| - base::JSONValueConverter<DocumentFeed>* converter) {
|
| - // inheritance
|
| - FeedEntry::RegisterJSONConverter(
|
| - reinterpret_cast<base::JSONValueConverter<FeedEntry>*>(converter));
|
| - // TODO(zelidrag): Once we figure out where these will be used, we should
|
| - // check for valid start_index_ and items_per_page_ values.
|
| - converter->RegisterCustomField<int>(
|
| - kStartIndexField, &DocumentFeed::start_index_, &base::StringToInt);
|
| - converter->RegisterCustomField<int>(
|
| - kItemsPerPageField, &DocumentFeed::items_per_page_, &base::StringToInt);
|
| - converter->RegisterStringField(kTitleTField, &DocumentFeed::title_);
|
| - converter->RegisterRepeatedMessage(kEntryField, &DocumentFeed::entries_);
|
| - converter->RegisterCustomField<int>(
|
| - kLargestChangestampField, &DocumentFeed::largest_changestamp_,
|
| - &base::StringToInt);
|
| -}
|
| -
|
| -bool DocumentFeed::Parse(const base::Value& value) {
|
| - base::JSONValueConverter<DocumentFeed> converter;
|
| - if (!converter.Convert(value, this)) {
|
| - DVLOG(1) << "Invalid document feed!";
|
| - return false;
|
| - }
|
| -
|
| - ScopedVector<DocumentEntry>::iterator iter = entries_.begin();
|
| - while (iter != entries_.end()) {
|
| - DocumentEntry* entry = (*iter);
|
| - entry->FillRemainingFields();
|
| - ++iter;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -// static
|
| -scoped_ptr<DocumentFeed> DocumentFeed::ExtractAndParse(
|
| - const base::Value& value) {
|
| - const base::DictionaryValue* as_dict = NULL;
|
| - base::DictionaryValue* feed_dict = NULL;
|
| - if (value.GetAsDictionary(&as_dict) &&
|
| - as_dict->GetDictionary(kFeedField, &feed_dict)) {
|
| - return DocumentFeed::CreateFrom(*feed_dict);
|
| - }
|
| - return scoped_ptr<DocumentFeed>(NULL);
|
| -}
|
| -
|
| -// static
|
| -scoped_ptr<DocumentFeed> DocumentFeed::CreateFrom(const base::Value& value) {
|
| - scoped_ptr<DocumentFeed> feed(new DocumentFeed());
|
| - if (!feed->Parse(value)) {
|
| - DVLOG(1) << "Invalid document feed!";
|
| - return scoped_ptr<DocumentFeed>(NULL);
|
| - }
|
| -
|
| - return feed.Pass();
|
| -}
|
| -
|
| -bool DocumentFeed::GetNextFeedURL(GURL* url) {
|
| - DCHECK(url);
|
| - for (size_t i = 0; i < links_.size(); ++i) {
|
| - if (links_[i]->type() == Link::NEXT) {
|
| - *url = links_[i]->href();
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// InstalledApp implementation
|
| -
|
| -InstalledApp::InstalledApp() : supports_create_(false) {
|
| -}
|
| -
|
| -InstalledApp::~InstalledApp() {
|
| -}
|
| -
|
| -InstalledApp::IconList InstalledApp::GetIconsForCategory(
|
| - AppIcon::IconCategory category) const {
|
| - IconList result;
|
| -
|
| - for (ScopedVector<AppIcon>::const_iterator icon_iter = app_icons_.begin();
|
| - icon_iter != app_icons_.end(); ++icon_iter) {
|
| - if ((*icon_iter)->category() != category)
|
| - continue;
|
| - GURL icon_url = (*icon_iter)->GetIconURL();
|
| - if (icon_url.is_empty())
|
| - continue;
|
| - result.push_back(std::make_pair((*icon_iter)->icon_side_length(),
|
| - icon_url));
|
| - }
|
| -
|
| - // Return a sorted list, smallest to largest.
|
| - std::sort(result.begin(), result.end(), SortBySize);
|
| - return result;
|
| -}
|
| -
|
| -GURL InstalledApp::GetProductUrl() const {
|
| - for (ScopedVector<Link>::const_iterator it = links_.begin();
|
| - it != links_.end(); ++it) {
|
| - const Link* link = *it;
|
| - if (link->type() == Link::PRODUCT)
|
| - return link->href();
|
| - }
|
| - return GURL();
|
| -}
|
| -
|
| -// static
|
| -bool InstalledApp::GetValueString(const base::Value* value,
|
| - std::string* result) {
|
| - const base::DictionaryValue* dict = NULL;
|
| - if (!value->GetAsDictionary(&dict))
|
| - return false;
|
| -
|
| - if (!dict->GetString(kTField, result))
|
| - return false;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// static
|
| -void InstalledApp::RegisterJSONConverter(
|
| - base::JSONValueConverter<InstalledApp>* converter) {
|
| - converter->RegisterRepeatedMessage(kInstalledAppIconField,
|
| - &InstalledApp::app_icons_);
|
| - converter->RegisterStringField(kInstalledAppIdField,
|
| - &InstalledApp::app_id_);
|
| - converter->RegisterStringField(kInstalledAppNameField,
|
| - &InstalledApp::app_name_);
|
| - converter->RegisterStringField(kInstalledAppObjectTypeField,
|
| - &InstalledApp::object_type_);
|
| - converter->RegisterCustomField<bool>(kInstalledAppSupportsCreateField,
|
| - &InstalledApp::supports_create_,
|
| - &GetBoolFromString);
|
| - converter->RegisterRepeatedCustomValue(kInstalledAppPrimaryMimeTypeField,
|
| - &InstalledApp::primary_mimetypes_,
|
| - &GetValueString);
|
| - converter->RegisterRepeatedCustomValue(kInstalledAppSecondaryMimeTypeField,
|
| - &InstalledApp::secondary_mimetypes_,
|
| - &GetValueString);
|
| - converter->RegisterRepeatedCustomValue(kInstalledAppPrimaryFileExtensionField,
|
| - &InstalledApp::primary_extensions_,
|
| - &GetValueString);
|
| - converter->RegisterRepeatedCustomValue(
|
| - kInstalledAppSecondaryFileExtensionField,
|
| - &InstalledApp::secondary_extensions_,
|
| - &GetValueString);
|
| - converter->RegisterRepeatedMessage(kLinkField, &InstalledApp::links_);
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// AccountMetadataFeed implementation
|
| -
|
| -AccountMetadataFeed::AccountMetadataFeed()
|
| - : quota_bytes_total_(0),
|
| - quota_bytes_used_(0),
|
| - largest_changestamp_(0) {
|
| -}
|
| -
|
| -AccountMetadataFeed::~AccountMetadataFeed() {
|
| -}
|
| -
|
| -// static
|
| -void AccountMetadataFeed::RegisterJSONConverter(
|
| - base::JSONValueConverter<AccountMetadataFeed>* converter) {
|
| - converter->RegisterCustomField<int64>(
|
| - kQuotaBytesTotalField,
|
| - &AccountMetadataFeed::quota_bytes_total_,
|
| - &base::StringToInt64);
|
| - converter->RegisterCustomField<int64>(
|
| - kQuotaBytesUsedField,
|
| - &AccountMetadataFeed::quota_bytes_used_,
|
| - &base::StringToInt64);
|
| - converter->RegisterCustomField<int>(
|
| - kLargestChangestampField,
|
| - &AccountMetadataFeed::largest_changestamp_,
|
| - &base::StringToInt);
|
| - converter->RegisterRepeatedMessage(kInstalledAppField,
|
| - &AccountMetadataFeed::installed_apps_);
|
| -}
|
| -
|
| -// static
|
| -scoped_ptr<AccountMetadataFeed> AccountMetadataFeed::CreateFrom(
|
| - const base::Value& value) {
|
| - scoped_ptr<AccountMetadataFeed> feed(new AccountMetadataFeed());
|
| - const base::DictionaryValue* dictionary = NULL;
|
| - base::Value* entry = NULL;
|
| - if (!value.GetAsDictionary(&dictionary) ||
|
| - !dictionary->Get(kEntryField, &entry) ||
|
| - !feed->Parse(*entry)) {
|
| - LOG(ERROR) << "Unable to create: Invalid account metadata feed!";
|
| - return scoped_ptr<AccountMetadataFeed>(NULL);
|
| - }
|
| -
|
| - return feed.Pass();
|
| -}
|
| -
|
| -bool AccountMetadataFeed::Parse(const base::Value& value) {
|
| - base::JSONValueConverter<AccountMetadataFeed> converter;
|
| - if (!converter.Convert(value, this)) {
|
| - LOG(ERROR) << "Unable to parse: Invalid account metadata feed!";
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -} // namespace gdata
|
|
|