Commit 6bdf0936 authored by kochi@chromium.org's avatar kochi@chromium.org

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
parent f4726822
// 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
// 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_
// 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
......@@ -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',
......
......@@ -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',
......
{
"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
}
{
"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"
}
]
}
]
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment