diff options
author | kochi@chromium.org <kochi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-27 01:43:55 +0000 |
---|---|---|
committer | kochi@chromium.org <kochi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-27 01:43:55 +0000 |
commit | 6bdf093650147311383b38f0ad26d6d0f091b21f (patch) | |
tree | eb3c753ed1cf40870ea67f74de03853807a9901c | |
parent | f4726822d76caba76e080632ea2490c44065d86a (diff) | |
download | chromium_src-6bdf093650147311383b38f0ad26d6d0f091b21f.zip chromium_src-6bdf093650147311383b38f0ad26d6d0f091b21f.tar.gz chromium_src-6bdf093650147311383b38f0ad26d6d0f091b21f.tar.bz2 |
Add Drive API parser for About/Apps json
BUG=chromium:127728
TEST=unit_test --gtest_filter="DriveApiParser.*"
Review URL: https://chromiumcodereview.appspot.com/10810070
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148692 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/chromeos/gdata/drive_api_parser.cc | 282 | ||||
-rw-r--r-- | chrome/browser/chromeos/gdata/drive_api_parser.h | 262 | ||||
-rw-r--r-- | chrome/browser/chromeos/gdata/drive_api_parser_unittest.cc | 158 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/test/data/chromeos/drive/about.json | 251 | ||||
-rw-r--r-- | chrome/test/data/chromeos/drive/applist.json | 94 |
7 files changed, 1050 insertions, 0 deletions
diff --git a/chrome/browser/chromeos/gdata/drive_api_parser.cc b/chrome/browser/chromeos/gdata/drive_api_parser.cc new file mode 100644 index 0000000..6f1cf75 --- /dev/null +++ b/chrome/browser/chromeos/gdata/drive_api_parser.cc @@ -0,0 +1,282 @@ +// 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/drive_api_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/values.h" +#include "chrome/browser/chromeos/gdata/gdata_util.h" + +using base::Value; +using base::DictionaryValue; +using base::ListValue; + +namespace { + +// 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; +} + +// Drive v2 API JSON names. + +// Common +const char kKind[] = "kind"; + +// About Resource: +const char kAboutKind[] = "drive#about"; +const char kRootFolderId[] = "rootFolderId"; +const char kQuotaBytesTotal[] = "quotaBytesTotal"; +const char kQuotaBytesUsed[] = "quotaBytesUsed"; +const char kLargestChangeId[] = "largestChangeId"; + +// App Icon: +const char kCategory[] = "category"; +const char kSize[] = "size"; +const char kIconUrl[] = "iconUrl"; + +// Apps Resource: +const char kAppKind[] = "drive#app"; +const char kId[] = "id"; +const char kETag[] = "etag"; +const char kName[] = "name"; +const char kObjectType[] = "objectType"; +const char kSupportsCreate[] = "supportsCreate"; +const char kSupportsImport[] = "supportsImport"; +const char kInstalled[] = "installed"; +const char kAuthorized[] = "authorized"; +const char kProductUrl[] = "productUrl"; +const char kPrimaryMimeTypes[] = "primaryMimeTypes"; +const char kSecondaryMimeTypes[] = "secondaryMimeTypes"; +const char kPrimaryFileExtensions[] = "primaryFileExtensions"; +const char kSecondaryFileExtensions[] = "secondaryFileExtensions"; +const char kIcons[] = "icons"; + +// Apps List: +const char kAppListKind[] = "drive#appList"; +const char kItems[] = "items"; + + +// Maps category name to enum IconCategory. +struct AppIconCategoryMap { + gdata::DriveAppIcon::IconCategory category; + const char* category_name; +}; + +const AppIconCategoryMap kAppIconCategoryMap[] = { + { gdata::DriveAppIcon::DOCUMENT, "document" }, + { gdata::DriveAppIcon::APPLICATION, "application" }, + { gdata::DriveAppIcon::SHARED_DOCUMENT, "documentShared" }, +}; + +// Checks if the JSON is expected kind. In Drive API, JSON data structure has +// |kind| property which denotes the type of the structure (e.g. "drive#file"). +bool IsResourceKindExpected(const base::Value& value, + const std::string& expected_kind) { + const base::DictionaryValue* as_dict = NULL; + std::string kind; + return value.GetAsDictionary(&as_dict) && + as_dict->HasKey(kKind) && + as_dict->GetString(kKind, &kind) && + kind == expected_kind; +} + +} // namespace + +// TODO(kochi): Rename to namespace drive. http://crbug.com/136371 +namespace gdata { + +//////////////////////////////////////////////////////////////////////////////// +// AboutResource implementation + +AboutResource::AboutResource() + : quota_bytes_total_(0), + quota_bytes_used_(0), + largest_change_id_(0) {} + +AboutResource::~AboutResource() {} + +// static +scoped_ptr<AboutResource> AboutResource::CreateFrom(const base::Value& value) { + scoped_ptr<AboutResource> resource(new AboutResource()); + if (!IsResourceKindExpected(value, kAboutKind) || !resource->Parse(value)) { + LOG(ERROR) << "Unable to create: Invalid About resource JSON!"; + return scoped_ptr<AboutResource>(NULL); + } + return resource.Pass(); +} + +// static +void AboutResource::RegisterJSONConverter( + base::JSONValueConverter<AboutResource>* converter) { + converter->RegisterStringField(kRootFolderId, + &AboutResource::root_folder_id_); + converter->RegisterCustomField<int64>(kQuotaBytesTotal, + &AboutResource::quota_bytes_total_, + &base::StringToInt64); + converter->RegisterCustomField<int64>(kQuotaBytesUsed, + &AboutResource::quota_bytes_used_, + &base::StringToInt64); + converter->RegisterCustomField<int64>(kLargestChangeId, + &AboutResource::largest_change_id_, + &base::StringToInt64); +} + +bool AboutResource::Parse(const base::Value& value) { + base::JSONValueConverter<AboutResource> converter; + if (!converter.Convert(value, this)) { + LOG(ERROR) << "Unable to parse: Invalid About resource JSON!"; + return false; + } + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// DriveAppIcon implementation + +DriveAppIcon::DriveAppIcon() {} + +DriveAppIcon::~DriveAppIcon() {} + +// static +void DriveAppIcon::RegisterJSONConverter( + base::JSONValueConverter<DriveAppIcon>* converter) { + converter->RegisterCustomField<IconCategory>( + kCategory, + &DriveAppIcon::category_, + &DriveAppIcon::GetIconCategory); + converter->RegisterIntField(kSize, &DriveAppIcon::icon_side_length_); + converter->RegisterCustomField<GURL>(kIconUrl, + &DriveAppIcon::icon_url_, + GetGURLFromString); +} + +// static +scoped_ptr<DriveAppIcon> DriveAppIcon::CreateFrom(const base::Value& value) { + scoped_ptr<DriveAppIcon> resource(new DriveAppIcon()); + if (!resource->Parse(value)) { + LOG(ERROR) << "Unable to create: Invalid DriveAppIcon JSON!"; + return scoped_ptr<DriveAppIcon>(NULL); + } + return resource.Pass(); +} + +bool DriveAppIcon::Parse(const base::Value& value) { + base::JSONValueConverter<DriveAppIcon> converter; + if (!converter.Convert(value, this)) { + LOG(ERROR) << "Unable to parse: Invalid DriveAppIcon"; + return false; + } + return true; +} + +// static +bool DriveAppIcon::GetIconCategory(const base::StringPiece& category, + DriveAppIcon::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; +} + +//////////////////////////////////////////////////////////////////////////////// +// AppResource implementation + +AppResource::AppResource() {} + +AppResource::~AppResource() {} + +// static +void AppResource::RegisterJSONConverter( + base::JSONValueConverter<AppResource>* converter) { + converter->RegisterStringField(kId, &AppResource::id_); + converter->RegisterStringField(kName, &AppResource::name_); + converter->RegisterStringField(kObjectType, &AppResource::object_type_); + converter->RegisterBoolField(kSupportsCreate, &AppResource::supports_create_); + converter->RegisterBoolField(kSupportsImport, &AppResource::supports_import_); + converter->RegisterBoolField(kInstalled, &AppResource::installed_); + converter->RegisterBoolField(kAuthorized, &AppResource::authorized_); + converter->RegisterCustomField<GURL>(kProductUrl, + &AppResource::product_url_, + GetGURLFromString); + converter->RegisterRepeatedString(kPrimaryMimeTypes, + &AppResource::primary_mimetypes_); + converter->RegisterRepeatedString(kSecondaryMimeTypes, + &AppResource::secondary_mimetypes_); + converter->RegisterRepeatedString(kPrimaryFileExtensions, + &AppResource::primary_file_extensions_); + converter->RegisterRepeatedString(kSecondaryFileExtensions, + &AppResource::secondary_file_extensions_); + converter->RegisterRepeatedMessage(kIcons, &AppResource::icons_); +} + +// static +scoped_ptr<AppResource> AppResource::CreateFrom(const base::Value& value) { + scoped_ptr<AppResource> resource(new AppResource()); + if (!IsResourceKindExpected(value, kAppKind) || !resource->Parse(value)) { + LOG(ERROR) << "Unable to create: Invalid AppResource JSON!"; + return scoped_ptr<AppResource>(NULL); + } + return resource.Pass(); +} + +bool AppResource::Parse(const base::Value& value) { + base::JSONValueConverter<AppResource> converter; + if (!converter.Convert(value, this)) { + LOG(ERROR) << "Unable to parse: Invalid AppResource"; + return false; + } + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// AppList implementation + +AppList::AppList() {} + +AppList::~AppList() {} + +// static +void AppList::RegisterJSONConverter( + base::JSONValueConverter<AppList>* converter) { + converter->RegisterStringField(kETag, &AppList::etag_); + converter->RegisterRepeatedMessage<AppResource>(kItems, + &AppList::items_); +} + +// static +scoped_ptr<AppList> AppList::CreateFrom(const base::Value& value) { + scoped_ptr<AppList> resource(new AppList()); + if (!IsResourceKindExpected(value, kAppListKind) || !resource->Parse(value)) { + LOG(ERROR) << "Unable to create: Invalid AppList JSON!"; + return scoped_ptr<AppList>(NULL); + } + return resource.Pass(); +} + +bool AppList::Parse(const base::Value& value) { + base::JSONValueConverter<AppList> converter; + if (!converter.Convert(value, this)) { + LOG(ERROR) << "Unable to parse: Invalid AppList"; + return false; + } + return true; +} + +} // namespace gdata diff --git a/chrome/browser/chromeos/gdata/drive_api_parser.h b/chrome/browser/chromeos/gdata/drive_api_parser.h new file mode 100644 index 0000000..097f4b8 --- /dev/null +++ b/chrome/browser/chromeos/gdata/drive_api_parser.h @@ -0,0 +1,262 @@ +// 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. + +#ifndef CHROME_BROWSER_CHROMEOS_GDATA_DRIVE_API_PARSER_H_ +#define CHROME_BROWSER_CHROMEOS_GDATA_DRIVE_API_PARSER_H_ + +#include <string> +#include <vector> + +#include "base/compiler_specific.h" +#include "base/gtest_prod_util.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "base/string_piece.h" +#include "base/time.h" +#include "googleurl/src/gurl.h" + +namespace base { +class Value; +template <class StructType> +class JSONValueConverter; + +namespace internal { +template <class NestedType> +class RepeatedMessageConverter; +} // namespace internal +} // namespace base + +// TODO(kochi): Rename to namespace drive. http://crbug.com/136371 +namespace gdata { + +// About resource represents the account information about the current user. +// https://developers.google.com/drive/v2/reference/about +class AboutResource { + public: + ~AboutResource(); + + // Registers the mapping between JSON field names and the members in this + // class. + static void RegisterJSONConverter( + base::JSONValueConverter<AboutResource>* converter); + + // Creates about resource from parsed JSON. + static scoped_ptr<AboutResource> CreateFrom(const base::Value& value); + + // Returns root folder ID. + const std::string& root_folder_id() const { return root_folder_id_; } + // Returns total number of quta bytes. + int64 quota_bytes_total() const { return quota_bytes_total_; } + // Returns the number of quota bytes used. + int64 quota_bytes_used() const { return quota_bytes_used_; } + // Returns the largest change ID number. + int64 largest_change_id() const { return largest_change_id_; } + + private: + friend class DriveAPIParserTest; + FRIEND_TEST_ALL_PREFIXES(DriveAPIParserTest, AboutResourceParser); + AboutResource(); + + // Parses and initializes data members from content of |value|. + // Return false if parsing fails. + bool Parse(const base::Value& value); + + std::string root_folder_id_; + int64 quota_bytes_total_; + int64 quota_bytes_used_; + int64 largest_change_id_; + + DISALLOW_COPY_AND_ASSIGN(AboutResource); +}; + +// DriveAppIcon represents an icon for Drive Application. +// https://developers.google.com/drive/v2/reference/apps/list +class DriveAppIcon { + public: + enum IconCategory { + UNKNOWN, // Uninitialized state + DOCUMENT, // Document icon for various MIME types + APPLICATION, // Application icon for various MIME types + SHARED_DOCUMENT, // Icon for documents that are shared from other users. + }; + + ~DriveAppIcon(); + + // Registers the mapping between JSON field names and the members in this + // class. + static void RegisterJSONConverter( + base::JSONValueConverter<DriveAppIcon>* converter); + + // Creates drive app icon instance from parsed JSON. + static scoped_ptr<DriveAppIcon> CreateFrom(const base::Value& value); + + // Category of the icon. + IconCategory category() const { return category_; } + + // Size in pixels of one side of the icon (icons are always square). + const int icon_side_length() const { return icon_side_length_; } + + // Returns URL for this icon. + const GURL& icon_url() const { return icon_url_; } + + private: + // Parses and initializes data members from content of |value|. + // Return false if parsing fails. + bool Parse(const base::Value& value); + + // Extracts the icon category from the given string. Returns false and does + // not change |result| when |scheme| has an unrecognizable value. + static bool GetIconCategory(const base::StringPiece& category, + IconCategory* result); + + friend class base::internal::RepeatedMessageConverter<DriveAppIcon>; + friend class AppResource; + DriveAppIcon(); + + IconCategory category_; + int icon_side_length_; + GURL icon_url_; + + DISALLOW_COPY_AND_ASSIGN(DriveAppIcon); +}; + +// AppResource represents a Drive Application. +// https://developers.google.com/drive/v2/reference/apps/list +class AppResource { + public: + ~AppResource(); + + // Registers the mapping between JSON field names and the members in this + // class. + static void RegisterJSONConverter( + base::JSONValueConverter<AppResource>* converter); + + // Creates app resource from parsed JSON. + static scoped_ptr<AppResource> CreateFrom(const base::Value& value); + + // Returns application ID, which is 12-digit decimals (e.g. "123456780123"). + const std::string& id() const { return id_; } + + // Returns application name. + const std::string& name() const { return name_; } + + // Returns the name of the type of object this application creates. + // This can be any string. TODO(kochi): figure out how to use this value. + const std::string& object_type() const { return object_type_; } + + // Returns whether this application suuports creating new objects. + bool supports_create() const { return supports_create_; } + + // Returns whether this application supports importing Google Docs. + bool supports_import() const { return supports_import_; } + + // Returns whether this application is installed. + bool is_installed() const { return installed_; } + + // Returns whether this application is authorized to access data on the + // user's Drive. + bool is_authorized() const { return authorized_; } + + // Returns the product URL, e.g. at Chrmoe Web Store. + const GURL& product_url() const { return product_url_; } + + // List of primary mime types supported by this WebApp. Primary status should + // trigger this WebApp becoming the default handler of file instances that + // have these mime types. + const ScopedVector<std::string>& primary_mimetypes() const { + return primary_mimetypes_; + } + + // List of secondary mime types supported by this WebApp. Secondary status + // should make this WebApp show up in "Open with..." pop-up menu of the + // default action menu for file with matching mime types. + const ScopedVector<std::string>& secondary_mimetypes() const { + return secondary_mimetypes_; + } + + // List of primary file extensions supported by this WebApp. Primary status + // should trigger this WebApp becoming the default handler of file instances + // that match these extensions. + const ScopedVector<std::string>& primary_file_extensions() const { + return primary_file_extensions_; + } + + // List of secondary file extensions supported by this WebApp. Secondary + // status should make this WebApp show up in "Open with..." pop-up menu of the + // default action menu for file with matching extensions. + const ScopedVector<std::string>& secondary_file_extensions() const { + return secondary_file_extensions_; + } + + // Returns Icons for this application. An application can have multiple + // icons for different purpose (application, document, shared document) + // in several sizes. + const ScopedVector<DriveAppIcon>& icons() const { + return icons_; + } + + private: + friend class base::internal::RepeatedMessageConverter<AppResource>; + friend class AppList; + AppResource(); + + // Parses and initializes data members from content of |value|. + // Return false if parsing fails. + bool Parse(const base::Value& value); + + std::string id_; + std::string name_; + std::string object_type_; + bool supports_create_; + bool supports_import_; + bool installed_; + bool authorized_; + GURL product_url_; + ScopedVector<std::string> primary_mimetypes_; + ScopedVector<std::string> secondary_mimetypes_; + ScopedVector<std::string> primary_file_extensions_; + ScopedVector<std::string> secondary_file_extensions_; + ScopedVector<DriveAppIcon> icons_; + + DISALLOW_COPY_AND_ASSIGN(AppResource); +}; + +// AppList represents a list of Drive Applications. +// https://developers.google.com/drive/v2/reference/apps/list +class AppList { + public: + ~AppList(); + + // Registers the mapping between JSON field names and the members in this + // class. + static void RegisterJSONConverter( + base::JSONValueConverter<AppList>* converter); + + // Creates app list from parsed JSON. + static scoped_ptr<AppList> CreateFrom(const base::Value& value); + + // ETag for this resource. + const std::string& etag() const { return etag_; } + + // Returns a vector of applications. + const ScopedVector<AppResource>& items() const { return items_; } + + private: + friend class DriveAPIParserTest; + FRIEND_TEST_ALL_PREFIXES(DriveAPIParserTest, AppListParser); + AppList(); + + // Parses and initializes data members from content of |value|. + // Return false if parsing fails. + bool Parse(const base::Value& value); + + std::string etag_; + ScopedVector<AppResource> items_; + + DISALLOW_COPY_AND_ASSIGN(AppList); +}; + +} // namespace gdata + +#endif // CHROME_BROWSER_CHROMEOS_GDATA_DRIVE_API_PARSER_H_ diff --git a/chrome/browser/chromeos/gdata/drive_api_parser_unittest.cc b/chrome/browser/chromeos/gdata/drive_api_parser_unittest.cc new file mode 100644 index 0000000..aafbcfe --- /dev/null +++ b/chrome/browser/chromeos/gdata/drive_api_parser_unittest.cc @@ -0,0 +1,158 @@ +// 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 "base/file_path.h" +#include "base/file_util.h" +#include "base/json/json_file_value_serializer.h" +#include "base/path_service.h" +#include "base/string16.h" +#include "base/time.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/chromeos/gdata/drive_api_parser.h" +#include "chrome/common/chrome_paths.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::Value; +using base::DictionaryValue; +using base::ListValue; + +#define IF_EXPECT_EQ(arg1, arg2) \ + EXPECT_EQ(arg1, arg2); \ + if (arg1 == arg2) + +#define IF_EXPECT_TRUE(arg) \ + EXPECT_TRUE(arg); \ + if (arg) + +namespace gdata { + +class DriveAPIParserTest : public testing::Test { + protected: + static Value* LoadJSONFile(const std::string& filename) { + FilePath path; + std::string error; + // Test files for this unit test are located in + // src/chrome/test/data/chromeos/drive/* + PathService::Get(chrome::DIR_TEST_DATA, &path); + path = path.AppendASCII("chromeos") + .AppendASCII("drive") + .AppendASCII(filename.c_str()); + EXPECT_TRUE(file_util::PathExists(path)) << + "Couldn't find " << path.value(); + + JSONFileValueSerializer serializer(path); + Value* value = serializer.Deserialize(NULL, &error); + EXPECT_TRUE(value) << "Parse error " << path.value() << ": " << error; + return value; + } +}; + +// Test about resource parsing. +TEST_F(DriveAPIParserTest, AboutResourceParser) { + std::string error; + scoped_ptr<Value> document(LoadJSONFile("about.json")); + ASSERT_TRUE(document.get()); + + ASSERT_EQ(Value::TYPE_DICTIONARY, document->GetType()); + scoped_ptr<AboutResource> resource(new AboutResource()); + EXPECT_TRUE(resource->Parse(*document)); + + EXPECT_EQ("0AIv7G8yEYAWHUk9123", resource->root_folder_id()); + EXPECT_EQ(5368709120LL, resource->quota_bytes_total()); + EXPECT_EQ(1073741824LL, resource->quota_bytes_used()); + EXPECT_EQ(8177LL, resource->largest_change_id()); +} + +// Test app list parsing. +TEST_F(DriveAPIParserTest, AppListParser) { + std::string error; + scoped_ptr<Value> document(LoadJSONFile("applist.json")); + ASSERT_TRUE(document.get()); + + ASSERT_EQ(Value::TYPE_DICTIONARY, document->GetType()); + scoped_ptr<AppList> applist(new AppList); + EXPECT_TRUE(applist->Parse(*document)); + + EXPECT_EQ("\"Jm4BaSnCWNND-noZsHINRqj4ABC/tuqRBw0lvjUdPtc_2msA1tN4XYZ\"", + applist->etag()); + IF_EXPECT_EQ(2U, applist->items().size()) { + // Check Drive app 1 + const AppResource& app1 = *applist->items()[0]; + EXPECT_EQ("123456788192", app1.id()); + EXPECT_EQ("Drive app 1", app1.name()); + EXPECT_EQ("", app1.object_type()); + EXPECT_EQ(true, app1.supports_create()); + EXPECT_EQ(true, app1.supports_import()); + EXPECT_EQ(true, app1.is_installed()); + EXPECT_EQ(false, app1.is_authorized()); + EXPECT_EQ("https://chrome.google.com/webstore/detail/" + "abcdefghabcdefghabcdefghabcdefgh", + app1.product_url().spec()); + + IF_EXPECT_EQ(1U, app1.primary_mimetypes().size()) { + EXPECT_EQ("application/vnd.google-apps.drive-sdk.123456788192", + *app1.primary_mimetypes()[0]); + } + + IF_EXPECT_EQ(2U, app1.secondary_mimetypes().size()) { + EXPECT_EQ("text/html", *app1.secondary_mimetypes()[0]); + EXPECT_EQ("text/plain", *app1.secondary_mimetypes()[1]); + } + + IF_EXPECT_EQ(2U, app1.primary_file_extensions().size()) { + EXPECT_EQ("exe", *app1.primary_file_extensions()[0]); + EXPECT_EQ("com", *app1.primary_file_extensions()[1]); + } + + EXPECT_EQ(0U, app1.secondary_file_extensions().size()); + + IF_EXPECT_EQ(6U, app1.icons().size()) { + const DriveAppIcon& icon1 = *app1.icons()[0]; + EXPECT_EQ(DriveAppIcon::APPLICATION, icon1.category()); + EXPECT_EQ(10, icon1.icon_side_length()); + EXPECT_EQ("http://www.example.com/10.png", icon1.icon_url().spec()); + + const DriveAppIcon& icon6 = *app1.icons()[5]; + EXPECT_EQ(DriveAppIcon::SHARED_DOCUMENT, icon6.category()); + EXPECT_EQ(16, icon6.icon_side_length()); + EXPECT_EQ("http://www.example.com/ds16.png", icon6.icon_url().spec()); + } + + // Check Drive app 2 + const AppResource& app2 = *applist->items()[1]; + EXPECT_EQ("876543210000", app2.id()); + EXPECT_EQ("Drive app 2", app2.name()); + EXPECT_EQ("", app2.object_type()); + EXPECT_EQ(false, app2.supports_create()); + EXPECT_EQ(false, app2.supports_import()); + EXPECT_EQ(true, app2.is_installed()); + EXPECT_EQ(false, app2.is_authorized()); + EXPECT_EQ("https://chrome.google.com/webstore/detail/" + "hgfedcbahgfedcbahgfedcbahgfedcba", + app2.product_url().spec()); + + IF_EXPECT_EQ(3U, app2.primary_mimetypes().size()) { + EXPECT_EQ("image/jpeg", + *app2.primary_mimetypes()[0]); + EXPECT_EQ("image/png", + *app2.primary_mimetypes()[1]); + EXPECT_EQ("application/vnd.google-apps.drive-sdk.876543210000", + *app2.primary_mimetypes()[2]); + } + + EXPECT_EQ(0U, app2.secondary_mimetypes().size()); + EXPECT_EQ(0U, app2.primary_file_extensions().size()); + EXPECT_EQ(0U, app2.secondary_file_extensions().size()); + + IF_EXPECT_EQ(3U, app2.icons().size()) { + const DriveAppIcon& icon2 = *app2.icons()[1]; + EXPECT_EQ(DriveAppIcon::DOCUMENT, icon2.category()); + EXPECT_EQ(10, icon2.icon_side_length()); + EXPECT_EQ("http://www.example.com/d10.png", icon2.icon_url().spec()); + } + } +} + +} // namespace gdata diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index b1e1a98..cc22350 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -536,6 +536,8 @@ 'browser/chromeos/external_metrics.h', 'browser/chromeos/external_protocol_dialog.cc', 'browser/chromeos/external_protocol_dialog.h', + 'browser/chromeos/gdata/drive_api_parser.cc', + 'browser/chromeos/gdata/drive_api_parser.h', 'browser/chromeos/gdata/drive_task_executor.cc', 'browser/chromeos/gdata/drive_task_executor.h', 'browser/chromeos/gdata/drive_webapps_registry.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 3211e67..42468e9 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1096,6 +1096,7 @@ 'browser/chromeos/device_settings_provider_unittest.cc', 'browser/chromeos/extensions/file_browser_notifications_unittest.cc', 'browser/chromeos/external_metrics_unittest.cc', + 'browser/chromeos/gdata/drive_api_parser_unittest.cc', 'browser/chromeos/gdata/drive_webapps_registry_unittest.cc', 'browser/chromeos/gdata/gdata_cache_metadata_unittest.cc', 'browser/chromeos/gdata/gdata_cache_unittest.cc', diff --git a/chrome/test/data/chromeos/drive/about.json b/chrome/test/data/chromeos/drive/about.json new file mode 100644 index 0000000..c0f52ba --- /dev/null +++ b/chrome/test/data/chromeos/drive/about.json @@ -0,0 +1,251 @@ +{ + "kind": "drive#about", + "etag": "\"ia2FSHMEjvcFQvtI43H5NSXKABC/2QujpLrTbaz3UJ2wpt1HSuAZXYZ\"", + "selfLink": "https://www.googleapis.com/drive/v2/about", + "name": "Test User", + "quotaBytesTotal": "5368709120", + "quotaBytesUsed": "1073741824", + "quotaBytesUsedInTrash": "0", + "largestChangeId": "8177", + "rootFolderId": "0AIv7G8yEYAWHUk9123", + "domainSharingPolicy": "allowedWithWarning", + "permissionId": "12141426201712069789", + "importFormats": [ + { + "source": "application/msword", + "targets": [ + "application/vnd.google-apps.document" + ] + }, + { + "source": "text/plain", + "targets": [ + "application/vnd.google-apps.document" + ] + }, + { + "source": "text/tab-separated-values", + "targets": [ + "application/vnd.google-apps.spreadsheet" + ] + }, + { + "source": "application/vnd.ms-excel", + "targets": [ + "application/vnd.google-apps.spreadsheet" + ] + }, + { + "source": "application/vnd.sun.xml.writer", + "targets": [ + "application/vnd.google-apps.document" + ] + }, + { + "source": "image/bmp", + "targets": [ + "application/vnd.google-apps.document" + ] + }, + { + "source": "application/rtf", + "targets": [ + "application/vnd.google-apps.document" + ] + }, + { + "source": "image/gif", + "targets": [ + "application/vnd.google-apps.document" + ] + }, + { + "source": "text/csv", + "targets": [ + "application/vnd.google-apps.spreadsheet" + ] + }, + { + "source": "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "targets": [ + "application/vnd.google-apps.presentation" + ] + }, + { + "source": "application/x-msmetafile", + "targets": [ + "application/vnd.google-apps.drawing" + ] + }, + { + "source": "application/vnd.oasis.opendocument.text", + "targets": [ + "application/vnd.google-apps.document" + ] + }, + { + "source": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "targets": [ + "application/vnd.google-apps.spreadsheet" + ] + }, + { + "source": "application/vnd.ms-powerpoint", + "targets": [ + "application/vnd.google-apps.presentation" + ] + }, + { + "source": "application/x-vnd.oasis.opendocument.spreadsheet", + "targets": [ + "application/vnd.google-apps.spreadsheet" + ] + }, + { + "source": "application/pdf", + "targets": [ + "application/vnd.google-apps.document" + ] + }, + { + "source": "image/jpeg", + "targets": [ + "application/vnd.google-apps.document" + ] + }, + { + "source": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "targets": [ + "application/vnd.google-apps.document" + ] + }, + { + "source": "image/png", + "targets": [ + "application/vnd.google-apps.document" + ] + }, + { + "source": "text/html", + "targets": [ + "application/vnd.google-apps.document" + ] + } + ], + "exportFormats": [ + { + "source": "application/vnd.google-apps.form", + "targets": [ + "application/pdf", + "application/x-vnd.oasis.opendocument.spreadsheet", + "application/vnd.ms-excel" + ] + }, + { + "source": "application/vnd.google-apps.presentation", + "targets": [ + "application/pdf", + "application/vnd.openxmlformats-officedocument.presentationml.presentation" + ] + }, + { + "source": "application/vnd.google-apps.spreadsheet", + "targets": [ + "application/pdf", + "application/x-vnd.oasis.opendocument.spreadsheet", + "application/vnd.ms-excel" + ] + }, + { + "source": "application/vnd.google-apps.document", + "targets": [ + "application/vnd.oasis.opendocument.text", + "application/msword", + "text/html", + "application/rtf", + "text/plain", + "application/pdf" + ] + }, + { + "source": "application/vnd.google-apps.drawing", + "targets": [ + "image/svg+xml", + "image/jpeg", + "image/png", + "application/pdf" + ] + } + ], + "additionalRoleInfo": [ + { + "type": "application/vnd.google-apps.document", + "roleSets": [ + { + "primaryRole": "reader", + "additionalRoles": [ + "commenter" + ] + } + ] + }, + { + "type": "application/vnd.google-apps.drawing", + "roleSets": [ + { + "primaryRole": "reader", + "additionalRoles": [ + "commenter" + ] + } + ] + }, + { + "type": "application/vnd.google-apps.presentation", + "roleSets": [ + { + "primaryRole": "reader", + "additionalRoles": [ + "commenter" + ] + } + ] + } + ], + "features": [ + { + "featureName": "ocr" + }, + { + "featureName": "translation", + "featureRate": 2.0 + } + ], + "maxUploadSizes": [ + { + "type": "application/vnd.google-apps.drawing", + "size": "2097152" + }, + { + "type": "*", + "size": "10737418240" + }, + { + "type": "application/vnd.google-apps.presentation", + "size": "52428800" + }, + { + "type": "application/vnd.google-apps.document", + "size": "2097152" + }, + { + "type": "application/vnd.google-apps.spreadsheet", + "size": "20971520" + }, + { + "type": "application/pdf", + "size": "10737418240" + } + ], + "isCurrentAppInstalled": false +} diff --git a/chrome/test/data/chromeos/drive/applist.json b/chrome/test/data/chromeos/drive/applist.json new file mode 100644 index 0000000..5614b43 --- /dev/null +++ b/chrome/test/data/chromeos/drive/applist.json @@ -0,0 +1,94 @@ +{ + "kind": "drive#appList", + "etag": "\"Jm4BaSnCWNND-noZsHINRqj4ABC/tuqRBw0lvjUdPtc_2msA1tN4XYZ\"", + "selfLink": "https://www.googleapis.com/drive/v2/apps", + "items": [ + { + "kind": "drive#app", + "id": "123456788192", + "name": "Drive app 1", + "objectType": "", + "supportsCreate": true, + "supportsImport": true, + "installed": true, + "authorized": false, + "productUrl": "https://chrome.google.com/webstore/detail/abcdefghabcdefghabcdefghabcdefgh", + "primaryMimeTypes": [ + "application/vnd.google-apps.drive-sdk.123456788192" + ], + "secondaryMimeTypes": [ + "text/html", + "text/plain" + ], + "primaryFileExtensions": [ + "exe", + "com" + ], + "icons": [ + { + "category": "application", + "size": 10, + "iconUrl": "http://www.example.com/10.png" + }, + { + "category": "application", + "size": 16, + "iconUrl": "http://www.example.com/16.png" + }, + { + "category": "document", + "size": 10, + "iconUrl": "http://www.example.com/d10.png" + }, + { + "category": "document", + "size": 16, + "iconUrl": "http://www.example.com/d16.png" + }, + { + "category": "documentShared", + "size": 10, + "iconUrl": "http://www.example.com/ds10.png" + }, + { + "category": "documentShared", + "size": 16, + "iconUrl": "http://www.example.com/ds16.png" + } + ] + }, + { + "kind": "drive#app", + "id": "876543210000", + "name": "Drive app 2", + "objectType": "", + "supportsCreate": false, + "supportsImport": false, + "installed": true, + "authorized": false, + "productUrl": "https://chrome.google.com/webstore/detail/hgfedcbahgfedcbahgfedcbahgfedcba", + "primaryMimeTypes": [ + "image/jpeg", + "image/png", + "application/vnd.google-apps.drive-sdk.876543210000" + ], + "icons": [ + { + "category": "application", + "size": 10, + "iconUrl": "http://www.example.com/10.png" + }, + { + "category": "document", + "size": 10, + "iconUrl": "http://www.example.com/d10.png" + }, + { + "category": "documentShared", + "size": 10, + "iconUrl": "http://www.example.com/ds10.png" + } + ] + } + ] +} |