diff options
author | Mike Wittman <wittman@chromium.org> | 2014-10-01 14:56:57 -0700 |
---|---|---|
committer | Mike Wittman <wittman@chromium.org> | 2014-10-01 21:59:55 +0000 |
commit | 72520cfbda25e457da26113b568c76171d716a3f (patch) | |
tree | ada572d1f49255980811a20eb452a7f7e6423d6b | |
parent | 438a0d63964342acd2b50f12cb69fa4ae93254c0 (diff) | |
download | chromium_src-72520cfbda25e457da26113b568c76171d716a3f.zip chromium_src-72520cfbda25e457da26113b568c76171d716a3f.tar.gz chromium_src-72520cfbda25e457da26113b568c76171d716a3f.tar.bz2 |
Add enhanced bookmarks sync datatype
Adds a new sync datatype to handle the enhanced bookmarks
representation.
BUG=415822
R=mpearson@chromium.org, sky@chromium.org, zea@chromium.org
Review URL: https://codereview.chromium.org/583863002
Cr-Commit-Position: refs/heads/master@{#297718}
26 files changed, 559 insertions, 7 deletions
diff --git a/chrome/browser/bookmarks/enhanced_bookmarks_features.cc b/chrome/browser/bookmarks/enhanced_bookmarks_features.cc index a7bca68..d519600 100644 --- a/chrome/browser/bookmarks/enhanced_bookmarks_features.cc +++ b/chrome/browser/bookmarks/enhanced_bookmarks_features.cc @@ -259,3 +259,10 @@ bool IsEnableSyncArticlesSet() { return false; } + +bool IsEnhancedBookmarksSyncEnabled() { + // Gate by command line flag during development. Ultimately this should check + // whether the user is using the enhanced bookmarks extension. + return CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableEnhancedBookmarksSync); +} diff --git a/chrome/browser/bookmarks/enhanced_bookmarks_features.h b/chrome/browser/bookmarks/enhanced_bookmarks_features.h index a0c09c4..8b88d47 100644 --- a/chrome/browser/bookmarks/enhanced_bookmarks_features.h +++ b/chrome/browser/bookmarks/enhanced_bookmarks_features.h @@ -77,4 +77,7 @@ bool IsEnableDomDistillerSet(); // Returns true when flag enable-sync-articles is set or enabled from Finch. bool IsEnableSyncArticlesSet(); +// Returns true if sync of enhanced bookmarks is enabled. +bool IsEnhancedBookmarksSyncEnabled(); + #endif // CHROME_BROWSER_BOOKMARKS_ENHANCED_BOOKMARKS_FEATURES_H_ diff --git a/chrome/browser/sync/profile_sync_components_factory_impl.cc b/chrome/browser/sync/profile_sync_components_factory_impl.cc index a85b2a1..345845c 100644 --- a/chrome/browser/sync/profile_sync_components_factory_impl.cc +++ b/chrome/browser/sync/profile_sync_components_factory_impl.cc @@ -289,6 +289,15 @@ void ProfileSyncComponentsFactoryImpl::RegisterCommonDataTypes( this, profile_)); #endif + + // Enhanced bookmark sync is disabled by default. Register only if explicitly + // enabled. + if (IsEnhancedBookmarksSyncEnabled()) { + pss->RegisterDataTypeController(new UIDataTypeController( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), + base::Bind(&ChromeReportUnrecoverableError), + syncer::ENHANCED_BOOKMARKS, this)); + } } void ProfileSyncComponentsFactoryImpl::RegisterDesktopDataTypes( @@ -557,6 +566,11 @@ base::WeakPtr<syncer::SyncableService> ProfileSyncComponentsFactoryImpl:: return base::WeakPtr<syncer::SyncableService>(); #endif } + case syncer::ENHANCED_BOOKMARKS: { + // TODO(wittman): Return enhanced bookmarks SyncableService once + // implemented. + return base::WeakPtr<syncer::SyncableService>(); + } default: // The following datatypes still need to be transitioned to the // syncer::SyncableService API: diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index eb76001..3acb432 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc @@ -1719,7 +1719,7 @@ void ProfileSyncService::UpdateSelectedTypesHistogram( sync_driver::user_selectable_type::PROXY_TABS }; - COMPILE_ASSERT(32 == syncer::MODEL_TYPE_COUNT, UpdateCustomConfigHistogram); + COMPILE_ASSERT(33 == syncer::MODEL_TYPE_COUNT, UpdateCustomConfigHistogram); if (!sync_everything) { const syncer::ModelTypeSet current_types = GetPreferredDataTypes(); diff --git a/chrome/browser/ui/webui/sync_setup_handler.cc b/chrome/browser/ui/webui/sync_setup_handler.cc index 0218d61..f5f1b1d 100644 --- a/chrome/browser/ui/webui/sync_setup_handler.cc +++ b/chrome/browser/ui/webui/sync_setup_handler.cc @@ -106,7 +106,7 @@ const char* kDataTypeNames[] = { "tabs" }; -COMPILE_ASSERT(32 == syncer::MODEL_TYPE_COUNT, +COMPILE_ASSERT(33 == syncer::MODEL_TYPE_COUNT, update_kDataTypeNames_to_match_UserSelectableTypes); typedef std::map<syncer::ModelType, const char*> ModelTypeNameMap; diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 35d3d8b..9d35d23 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -433,6 +433,9 @@ const char kEnableDomainReliability[] = "enable-domain-reliability"; // Enable Enhanced Bookmarks. const char kEnhancedBookmarksExperiment[] = "enhanced-bookmarks-experiment"; +// Enable Enhanced Bookmarks sync. +const char kEnableEnhancedBookmarksSync[] = "enable-enhanced-bookmarks-sync"; + // Enables experimentation with ephemeral apps, which are launched without // installing in Chrome. const char kEnableEphemeralApps[] = "enable-ephemeral-apps"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index f8d3531..9bde5f5 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -127,7 +127,7 @@ extern const char kEnableDeviceDiscoveryNotifications[]; extern const char kEnableDomDistiller[]; extern const char kEnhancedBookmarksExperiment[]; extern const char kEnableDomainReliability[]; -extern const char kEnableEnhancedBookmarks[]; +extern const char kEnableEnhancedBookmarksSync[]; extern const char kEnableEphemeralApps[]; extern const char kEnableExperimentalHotwording[]; extern const char kEnableExtensionActivityLogging[]; diff --git a/components/sync_driver/model_association_manager.cc b/components/sync_driver/model_association_manager.cc index 6706c4c..2fa90ab 100644 --- a/components/sync_driver/model_association_manager.cc +++ b/components/sync_driver/model_association_manager.cc @@ -39,6 +39,7 @@ static const syncer::ModelType kStartOrder[] = { // UI thread data types. syncer::BOOKMARKS, + syncer::ENHANCED_BOOKMARKS, syncer::SUPERVISED_USERS, // Syncing supervised users on initial login // might block creating a new supervised user, // so we want to do it early. diff --git a/components/sync_driver/pref_names.cc b/components/sync_driver/pref_names.cc index 5ecf5c8..bf3de10 100644 --- a/components/sync_driver/pref_names.cc +++ b/components/sync_driver/pref_names.cc @@ -40,6 +40,7 @@ const char kSyncAutofill[] = "sync.autofill"; const char kSyncBookmarks[] = "sync.bookmarks"; const char kSyncDeviceInfo[] = "sync.device_info"; const char kSyncDictionary[] = "sync.dictionary"; +const char kSyncEnhancedBookmarks[] = "sync.enhanced_bookmarks"; const char kSyncExtensionSettings[] = "sync.extension_settings"; const char kSyncExtensions[] = "sync.extensions"; const char kSyncFaviconImages[] = "sync.favicon_images"; diff --git a/components/sync_driver/pref_names.h b/components/sync_driver/pref_names.h index 54710fb..a386504 100644 --- a/components/sync_driver/pref_names.h +++ b/components/sync_driver/pref_names.h @@ -28,6 +28,7 @@ extern const char kSyncAutofill[]; extern const char kSyncBookmarks[]; extern const char kSyncDeviceInfo[]; extern const char kSyncDictionary[]; +extern const char kSyncEnhancedBookmarks[]; extern const char kSyncExtensionSettings[]; extern const char kSyncExtensions[]; extern const char kSyncFaviconImages[]; diff --git a/components/sync_driver/sync_prefs.cc b/components/sync_driver/sync_prefs.cc index cc7914d..c28ec27 100644 --- a/components/sync_driver/sync_prefs.cc +++ b/components/sync_driver/sync_prefs.cc @@ -301,6 +301,8 @@ const char* SyncPrefs::GetPrefNameForDataType(syncer::ModelType data_type) { return prefs::kSyncThemes; case syncer::TYPED_URLS: return prefs::kSyncTypedUrls; + case syncer::ENHANCED_BOOKMARKS: + return prefs::kSyncEnhancedBookmarks; case syncer::EXTENSION_SETTINGS: return prefs::kSyncExtensionSettings; case syncer::EXTENSIONS: diff --git a/sync/internal_api/public/base/model_type.h b/sync/internal_api/public/base/model_type.h index 61bcbd0..305c385 100644 --- a/sync/internal_api/public/base/model_type.h +++ b/sync/internal_api/public/base/model_type.h @@ -110,6 +110,8 @@ enum ModelType { ARTICLES, // App List items APP_LIST, + // Enhanced bookmarks clips or folios. + ENHANCED_BOOKMARKS, // ---- Proxy types ---- // Proxy types are excluded from the sync protocol, but are still considered diff --git a/sync/protocol/BUILD.gn b/sync/protocol/BUILD.gn index d6e233b..88685d8 100644 --- a/sync/protocol/BUILD.gn +++ b/sync/protocol/BUILD.gn @@ -19,6 +19,7 @@ proto_library("protocol") { "device_info_specifics.proto", "dictionary_specifics.proto", "encryption.proto", + "enhanced_bookmark_specifics.proto", "experiments_specifics.proto", "extension_setting_specifics.proto", "extension_specifics.proto", diff --git a/sync/protocol/enhanced_bookmark_specifics.proto b/sync/protocol/enhanced_bookmark_specifics.proto new file mode 100644 index 0000000..8da5467 --- /dev/null +++ b/sync/protocol/enhanced_bookmark_specifics.proto @@ -0,0 +1,124 @@ +// 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. +// +// Sync protocol datatype extension for enhanced bookmarks. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; +option retain_unknown_fields = true; + +package sync_pb; + +import "bookmark_specifics.proto"; + +message ChromeSyncFolioInfo { + // Client-generated id. This is opaque to Chrome and unique across all + // EnhancedBookmarkSpecifics for a given user. + optional string folio_id = 1; + // Computed as per enhanced_bookmarks::ItemPosition. + optional string position = 2; + + // The size the clip should be displayed in Folio view (i.e. which images + // should be large in hero layout). + enum DisplaySize { + SMALL = 0; + MEDIUM = 1; + }; + optional DisplaySize display_size = 3 [default = SMALL]; +} + +message ChromeSyncImageData { + message ImageInfo { + // The (normalized) URL this image can be found at. + optional string url = 1; + + // The dimensions in pixels. + optional int32 width = 2; + optional int32 height = 3; + } + + // Information about the original image. + optional ImageInfo original_info = 2; + + // Information about the hosted thumbnail. + optional ImageInfo thumbnail_info = 3; + + // The expiration timestamp of the served thumbnail, in microseconds since + // the Linux epoch. The thumbnail is only guaranteed until this time, + // afterwards the URL may be broken. + optional int64 expiration_timestamp_us = 4; +} + +message ChromeSyncClip { + // Client-generated id. This is opaque to Chrome and unique across all + // EnhancedBookmarkSpecifics for a given user. + optional string id = 1; + optional string note = 2; + repeated ChromeSyncFolioInfo folio_info = 3; + optional string url = 4; + optional string title = 5; + optional string snippet = 6; + optional ChromeSyncImageData image = 7; + // Corresponds to BookmarkNode::date_added() and is the internal value from + // base::Time, in microseconds since the Windows epoch. + optional int64 created_timestamp_us = 8; + + // True if url points to a site that may serve malware. Allows warnings to be + // displayed to user. + optional bool is_malware = 9; + + // Reasons for failed fetches. + enum FetchErrorReason { + UNKNOWN = 0; + LIKELY_404 = 1; + UNREACHABLE = 2; + } + + // Reason that fetching this page failed. This field is populated only if + // the most recent fetch attempt failed. + optional FetchErrorReason fetch_error_reason = 10; + + // Bookmark manager or mobile client extension version, for logging and + // debugging purposes. + optional string client_version = 11; + + message LegacyBookmarkData { + optional bytes favicon = 1; + optional string icon_url = 2; + } + + optional LegacyBookmarkData bookmark_data = 12; + + repeated MetaInfo meta_info = 13; +} + +message ChromeSyncFolio { + // Client-generated id. + optional string id = 1; + // If set, is the Folio id that corresponds to a Chrome bookmarks folder. As a + // special case, the root folder is assigned an empty string. + optional string parent_id = 2; + optional string title = 3; + optional string description = 4; + optional bool is_public = 5; + // Corresponds to BookmarkNode::date_added() and is the internal value from + // base::Time, in microseconds since the Windows epoch. + optional int64 created_timestamp_us = 6; + // Set if parent_id is set. The position of this folio in its + // parent folio. This is the analog of ChromeSyncFolioInfo.position in clips. + optional string position = 7; + // Bookmark manager or mobile client extension version, for logging and + // debugging purposes. + optional string client_version = 13; + + repeated MetaInfo meta_info = 14; +} + +// Properties of enhanced bookmark sync objects. +message EnhancedBookmarkSpecifics { + // Exactly one of clip or folio is set. + optional ChromeSyncClip clip = 1; + optional ChromeSyncFolio folio = 2; +} diff --git a/sync/protocol/proto_enum_conversions.cc b/sync/protocol/proto_enum_conversions.cc index 4c43983..d8c1f0b 100644 --- a/sync/protocol/proto_enum_conversions.cc +++ b/sync/protocol/proto_enum_conversions.cc @@ -263,6 +263,30 @@ const char* GetBlockedStateString( return ""; } +const char* GetDisplaySizeString( + sync_pb::ChromeSyncFolioInfo::DisplaySize display_size) { + ASSERT_ENUM_BOUNDS(sync_pb::ChromeSyncFolioInfo, DisplaySize, SMALL, MEDIUM); + switch (display_size) { + ENUM_CASE(sync_pb::ChromeSyncFolioInfo, SMALL); + ENUM_CASE(sync_pb::ChromeSyncFolioInfo, MEDIUM); + } + NOTREACHED(); + return ""; +} + +const char* GetFetchErrorReasonString( + sync_pb::ChromeSyncClip::FetchErrorReason fetch_error_reason) { + ASSERT_ENUM_BOUNDS( + sync_pb::ChromeSyncClip, FetchErrorReason, UNKNOWN, UNREACHABLE); + switch (fetch_error_reason) { + ENUM_CASE(sync_pb::ChromeSyncClip, UNKNOWN); + ENUM_CASE(sync_pb::ChromeSyncClip, LIKELY_404); + ENUM_CASE(sync_pb::ChromeSyncClip, UNREACHABLE); + } + NOTREACHED(); + return ""; +} + #undef ASSERT_ENUM_BOUNDS #undef ENUM_CASE diff --git a/sync/protocol/proto_enum_conversions.h b/sync/protocol/proto_enum_conversions.h index 57a7b5c..b73cff4 100644 --- a/sync/protocol/proto_enum_conversions.h +++ b/sync/protocol/proto_enum_conversions.h @@ -11,6 +11,7 @@ #include "sync/protocol/app_list_specifics.pb.h" #include "sync/protocol/app_specifics.pb.h" #include "sync/protocol/client_debug_info.pb.h" +#include "sync/protocol/enhanced_bookmark_specifics.pb.h" #include "sync/protocol/session_specifics.pb.h" #include "sync/protocol/sync.pb.h" @@ -65,6 +66,12 @@ const char* SingletonDebugEventTypeString( const char* GetBlockedStateString(sync_pb::TabNavigation::BlockedState state); +const char* GetDisplaySizeString( + sync_pb::ChromeSyncFolioInfo::DisplaySize display_size); + +const char* GetFetchErrorReasonString( + sync_pb::ChromeSyncClip::FetchErrorReason fetch_error_reason); + } // namespace syncer #endif // SYNC_PROTOCOL_PROTO_ENUM_CONVERSIONS_H_ diff --git a/sync/protocol/proto_value_conversions.cc b/sync/protocol/proto_value_conversions.cc index bb37081..3d281c0 100644 --- a/sync/protocol/proto_value_conversions.cc +++ b/sync/protocol/proto_value_conversions.cc @@ -513,6 +513,81 @@ base::DictionaryValue* DictionarySpecificsToValue( return value; } +base::DictionaryValue* FolioInfoToValue( + const sync_pb::ChromeSyncFolioInfo& proto) { + base::DictionaryValue* value = new base::DictionaryValue(); + SET_STR(folio_id); + SET_STR(position); + SET_ENUM(display_size, GetDisplaySizeString); + return value; +} + +base::DictionaryValue* ImageInfoToValue( + const sync_pb::ChromeSyncImageData::ImageInfo& proto) { + base::DictionaryValue* value = new base::DictionaryValue(); + SET_STR(url); + SET_INT32(width); + SET_INT32(height); + return value; +} + +base::DictionaryValue* ImageDataToValue( + const sync_pb::ChromeSyncImageData& proto) { + base::DictionaryValue* value = new base::DictionaryValue(); + SET(original_info, ImageInfoToValue); + SET(thumbnail_info, ImageInfoToValue); + SET_INT64(expiration_timestamp_us); + return value; +} + +base::DictionaryValue* LegacyBookmarkDataToValue( + const sync_pb::ChromeSyncClip::LegacyBookmarkData& proto) { + base::DictionaryValue* value = new base::DictionaryValue(); + SET_BYTES(favicon); + SET_STR(icon_url); + return value; +} + +base::DictionaryValue* ClipToValue(const sync_pb::ChromeSyncClip& proto) { + base::DictionaryValue* value = new base::DictionaryValue(); + SET_STR(id); + SET_STR(note); + SET_REP(folio_info, &FolioInfoToValue); + SET_STR(url); + SET_STR(title); + SET_STR(snippet); + SET(image, ImageDataToValue); + SET_INT64(created_timestamp_us); + SET_BOOL(is_malware); + SET_ENUM(fetch_error_reason, GetFetchErrorReasonString); + SET_STR(client_version); + SET(bookmark_data, LegacyBookmarkDataToValue); + SET_REP(meta_info, &MetaInfoToValue); + return value; +} + +base::DictionaryValue* FolioToValue(const sync_pb::ChromeSyncFolio& proto) { + base::DictionaryValue* value = new base::DictionaryValue(); + SET_STR(id); + SET_STR(parent_id); + SET_STR(title); + SET_STR(description); + SET_BOOL(is_public); + SET_INT64(created_timestamp_us); + SET_STR(position); + SET_STR(client_version); + SET_REP(meta_info, &MetaInfoToValue); + return value; +} + +base::DictionaryValue* EnhancedBookmarkSpecificsToValue( + const sync_pb::EnhancedBookmarkSpecifics& proto) { + base::DictionaryValue* value = new base::DictionaryValue(); + SET(clip, ClipToValue); + SET(folio, FolioToValue); + return value; +} + namespace { base::DictionaryValue* FaviconSyncFlagsToValue( @@ -797,6 +872,7 @@ base::DictionaryValue* EntitySpecificsToValue( SET_FIELD(bookmark, BookmarkSpecificsToValue); SET_FIELD(device_info, DeviceInfoSpecificsToValue); SET_FIELD(dictionary, DictionarySpecificsToValue); + SET_FIELD(enhanced_bookmark, EnhancedBookmarkSpecificsToValue); SET_FIELD(experiments, ExperimentsSpecificsToValue); SET_FIELD(extension, ExtensionSpecificsToValue); SET_FIELD(extension_setting, ExtensionSettingSpecificsToValue); diff --git a/sync/protocol/proto_value_conversions.h b/sync/protocol/proto_value_conversions.h index 2a3c1ae..cde44de 100644 --- a/sync/protocol/proto_value_conversions.h +++ b/sync/protocol/proto_value_conversions.h @@ -36,6 +36,7 @@ class DeviceInfoSpecifics; class DeviceInformation; class DictionarySpecifics; class EncryptedData; +class EnhancedBookmarkSpecifics; class EntitySpecifics; class EverythingDirective; class ExperimentsSpecifics; @@ -211,6 +212,9 @@ SYNC_EXPORT_PRIVATE base::DictionaryValue* DeviceInfoSpecificsToValue( SYNC_EXPORT_PRIVATE base::DictionaryValue* DictionarySpecificsToValue( const sync_pb::DictionarySpecifics& dictionary_specifics); +SYNC_EXPORT_PRIVATE base::DictionaryValue* EnhancedBookmarkSpecificsToValue( + const sync_pb::EnhancedBookmarkSpecifics& enhanced_bookmark_specifics); + SYNC_EXPORT_PRIVATE base::DictionaryValue* ExperimentsSpecificsToValue( const sync_pb::ExperimentsSpecifics& proto); diff --git a/sync/protocol/proto_value_conversions_unittest.cc b/sync/protocol/proto_value_conversions_unittest.cc index 664a6ab..cace83b 100644 --- a/sync/protocol/proto_value_conversions_unittest.cc +++ b/sync/protocol/proto_value_conversions_unittest.cc @@ -6,6 +6,7 @@ #include "sync/protocol/proto_value_conversions.h" +#include "base/base64.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/time/time.h" @@ -18,6 +19,7 @@ #include "sync/protocol/bookmark_specifics.pb.h" #include "sync/protocol/device_info_specifics.pb.h" #include "sync/protocol/encryption.pb.h" +#include "sync/protocol/enhanced_bookmark_specifics.pb.h" #include "sync/protocol/experiments_specifics.pb.h" #include "sync/protocol/extension_setting_specifics.pb.h" #include "sync/protocol/extension_specifics.pb.h" @@ -35,6 +37,7 @@ #include "sync/protocol/sync.pb.h" #include "sync/protocol/theme_specifics.pb.h" #include "sync/protocol/typed_url_specifics.pb.h" +#include "sync/util/time.h" #include "testing/gtest/include/gtest/gtest.h" namespace syncer { @@ -55,7 +58,7 @@ TEST_F(ProtoValueConversionsTest, ProtoChangeCheck) { // If this number changes, that means we added or removed a data // type. Don't forget to add a unit test for {New // type}SpecificsToValue below. - EXPECT_EQ(32, MODEL_TYPE_COUNT); + EXPECT_EQ(33, MODEL_TYPE_COUNT); // We'd also like to check if we changed any field in our messages. // However, that's hard to do: sizeof could work, but it's @@ -184,6 +187,246 @@ TEST_F(ProtoValueConversionsTest, DeviceInfoSpecificsToValue) { TestSpecificsToValue(DeviceInfoSpecificsToValue); } +TEST_F(ProtoValueConversionsTest, EnhancedBookmarkSpecificsToValue) { + TestSpecificsToValue(EnhancedBookmarkSpecificsToValue); +} + +TEST_F(ProtoValueConversionsTest, EnhancedBookmarkSpecificsClipData) { + sync_pb::EnhancedBookmarkSpecifics specifics; + sync_pb::ChromeSyncClip* clip = specifics.mutable_clip(); + clip->set_id("id1"); + clip->set_note("note1"); + + sync_pb::ChromeSyncFolioInfo* folio_info1 = clip->add_folio_info(); + folio_info1->set_folio_id("folio id1"); + folio_info1->set_position("position1"); + folio_info1->set_display_size(sync_pb::ChromeSyncFolioInfo::SMALL); + sync_pb::ChromeSyncFolioInfo* folio_info2 = clip->add_folio_info(); + folio_info2->set_folio_id("folio id2"); + folio_info2->set_position("position2"); + folio_info2->set_display_size(sync_pb::ChromeSyncFolioInfo::MEDIUM); + + clip->set_url("http://www.google.com/"); + clip->set_title("title1"); + clip->set_snippet("snippet1"); + + sync_pb::ChromeSyncImageData* image = + clip->mutable_image(); + sync_pb::ChromeSyncImageData::ImageInfo* original_info = + image->mutable_original_info(); + original_info->set_url("http://example.com/original"); + original_info->set_width(1); + original_info->set_height(2); + sync_pb::ChromeSyncImageData::ImageInfo* thumbnail_info = + image->mutable_thumbnail_info(); + thumbnail_info->set_url("http://example.com/thumbnail"); + thumbnail_info->set_width(3); + thumbnail_info->set_height(4); + const base::Time expiration_time(base::Time::Now()); + image->set_expiration_timestamp_us(syncer::TimeToProtoTime(expiration_time)); + + const base::Time created_time(base::Time::Now()); + clip->set_created_timestamp_us(created_time.ToInternalValue()); + clip->set_is_malware(true); + clip->set_fetch_error_reason(sync_pb::ChromeSyncClip::LIKELY_404); + clip->set_client_version("10"); + + sync_pb::ChromeSyncClip::LegacyBookmarkData* bookmark_data = + clip->mutable_bookmark_data(); + bookmark_data->set_favicon("favicon data"); + bookmark_data->set_icon_url("http://www.google.com/favicon.ico"); + + sync_pb::MetaInfo* meta_1 = clip->add_meta_info(); + meta_1->set_key("key1"); + meta_1->set_value("value1"); + sync_pb::MetaInfo* meta_2 = clip->add_meta_info(); + meta_2->set_key("key2"); + meta_2->set_value("value2"); + + scoped_ptr<base::DictionaryValue> value( + EnhancedBookmarkSpecificsToValue(specifics)); + EXPECT_FALSE(value->empty()); + base::DictionaryValue* clip_value = nullptr; + ASSERT_TRUE(value->GetDictionary("clip", &clip_value)); + EXPECT_FALSE(clip_value->empty()); + std::string id; + EXPECT_TRUE(clip_value->GetString("id", &id)); + EXPECT_EQ("id1", id); + std::string note; + EXPECT_TRUE(clip_value->GetString("note", ¬e)); + EXPECT_EQ("note1", note); + + base::ListValue* folio_info_list; + ASSERT_TRUE(clip_value->GetList("folio_info", &folio_info_list)); + EXPECT_EQ(2u, folio_info_list->GetSize()); + base::DictionaryValue* folio_info; + ASSERT_TRUE(folio_info_list->GetDictionary(0, &folio_info)); + std::string folio_id; + std::string position; + std::string display_size; + EXPECT_TRUE(folio_info->GetString("folio_id", &folio_id)); + EXPECT_TRUE(folio_info->GetString("position", &position)); + EXPECT_TRUE(folio_info->GetString("display_size", &display_size)); + EXPECT_EQ("folio id1", folio_id); + EXPECT_EQ("position1", position); + EXPECT_EQ("SMALL", display_size); + ASSERT_TRUE(folio_info_list->GetDictionary(1, &folio_info)); + EXPECT_TRUE(folio_info->GetString("folio_id", &folio_id)); + EXPECT_TRUE(folio_info->GetString("position", &position)); + EXPECT_TRUE(folio_info->GetString("display_size", &display_size)); + EXPECT_EQ("folio id2", folio_id); + EXPECT_EQ("position2", position); + EXPECT_EQ("MEDIUM", display_size); + + std::string url; + EXPECT_TRUE(clip_value->GetString("url", &url)); + EXPECT_EQ("http://www.google.com/", url); + std::string title; + EXPECT_TRUE(clip_value->GetString("title", &title)); + EXPECT_EQ("title1", title); + std::string snippet; + EXPECT_TRUE(clip_value->GetString("snippet", &snippet)); + EXPECT_EQ("snippet1", snippet); + + base::DictionaryValue* image_value = nullptr; + ASSERT_TRUE(clip_value->GetDictionary("image", &image_value)); + base::DictionaryValue* image_info_value = nullptr; + ASSERT_TRUE(image_value->GetDictionary("original_info", + &image_info_value)); + EXPECT_TRUE(image_info_value->GetString("url", &url)); + EXPECT_EQ("http://example.com/original", url); + std::string width; + std::string height; + EXPECT_TRUE(image_info_value->GetString("width", &width)); + EXPECT_EQ("1", width); + EXPECT_TRUE(image_info_value->GetString("height", &height)); + EXPECT_EQ("2", height); + ASSERT_TRUE(image_value->GetDictionary("thumbnail_info", + &image_info_value)); + EXPECT_TRUE(image_info_value->GetString("url", &url)); + EXPECT_EQ("http://example.com/thumbnail", url); + EXPECT_TRUE(image_info_value->GetString("width", &width)); + EXPECT_EQ("3", width); + EXPECT_TRUE(image_info_value->GetString("height", &height)); + EXPECT_EQ("4", height); + std::string encoded_time_str; + EXPECT_TRUE(image_value->GetString("expiration_timestamp_us", + &encoded_time_str)); + int64 encoded_time; + EXPECT_TRUE(base::StringToInt64(encoded_time_str, &encoded_time)); + EXPECT_EQ(syncer::TimeToProtoTime(expiration_time), encoded_time); + + EXPECT_TRUE(clip_value->GetString("created_timestamp_us", &encoded_time_str)); + EXPECT_EQ(base::Int64ToString(created_time.ToInternalValue()), + encoded_time_str); + bool is_malware = false; + EXPECT_TRUE(clip_value->GetBoolean("is_malware", &is_malware)); + EXPECT_TRUE(is_malware); + std::string fetch_error_reason; + EXPECT_TRUE(clip_value->GetString("fetch_error_reason", &fetch_error_reason)); + EXPECT_EQ("LIKELY_404", fetch_error_reason); + std::string client_version; + EXPECT_TRUE(clip_value->GetString("client_version", &client_version)); + EXPECT_EQ("10", client_version); + base::DictionaryValue* bookmark_data_value = nullptr; + ASSERT_TRUE(clip_value->GetDictionary("bookmark_data", &bookmark_data_value)); + std::string favicon_base64; + EXPECT_TRUE(bookmark_data_value->GetString("favicon", &favicon_base64)); + std::string favicon; + EXPECT_TRUE(base::Base64Decode(favicon_base64, &favicon)); + EXPECT_EQ("favicon data", favicon); + std::string icon_url; + EXPECT_TRUE(bookmark_data_value->GetString("icon_url", &icon_url)); + EXPECT_EQ("http://www.google.com/favicon.ico", icon_url); + + base::ListValue* meta_info_list; + ASSERT_TRUE(clip_value->GetList("meta_info", &meta_info_list)); + EXPECT_EQ(2u, meta_info_list->GetSize()); + base::DictionaryValue* meta_info; + std::string meta_key; + std::string meta_value; + ASSERT_TRUE(meta_info_list->GetDictionary(0, &meta_info)); + EXPECT_TRUE(meta_info->GetString("key", &meta_key)); + EXPECT_TRUE(meta_info->GetString("value", &meta_value)); + EXPECT_EQ("key1", meta_key); + EXPECT_EQ("value1", meta_value); + ASSERT_TRUE(meta_info_list->GetDictionary(1, &meta_info)); + EXPECT_TRUE(meta_info->GetString("key", &meta_key)); + EXPECT_TRUE(meta_info->GetString("value", &meta_value)); + EXPECT_EQ("key2", meta_key); + EXPECT_EQ("value2", meta_value); +} + +TEST_F(ProtoValueConversionsTest, EnhancedBookmarkSpecificsFolioData) { + sync_pb::EnhancedBookmarkSpecifics specifics; + sync_pb::ChromeSyncFolio* folio = specifics.mutable_folio(); + folio->set_id("id1"); + folio->set_parent_id("parent id1"); + folio->set_title("title1"); + folio->set_description("description1"); + folio->set_is_public(true); + const base::Time created_time(base::Time::Now()); + folio->set_created_timestamp_us(created_time.ToInternalValue()); + folio->set_position("position1"); + folio->set_client_version("10"); + sync_pb::MetaInfo* meta_1 = folio->add_meta_info(); + meta_1->set_key("key1"); + meta_1->set_value("value1"); + sync_pb::MetaInfo* meta_2 = folio->add_meta_info(); + meta_2->set_key("key2"); + meta_2->set_value("value2"); + + scoped_ptr<base::DictionaryValue> value( + EnhancedBookmarkSpecificsToValue(specifics)); + EXPECT_FALSE(value->empty()); + base::DictionaryValue* folio_value = nullptr; + ASSERT_TRUE(value->GetDictionary("folio", &folio_value)); + EXPECT_FALSE(folio_value->empty()); + std::string id; + EXPECT_TRUE(folio_value->GetString("id", &id)); + EXPECT_EQ("id1", id); + std::string parent_id; + EXPECT_TRUE(folio_value->GetString("parent_id", &id)); + EXPECT_EQ("parent id1", id); + std::string title; + EXPECT_TRUE(folio_value->GetString("title", &title)); + EXPECT_EQ("title1", title); + std::string description; + EXPECT_TRUE(folio_value->GetString("description", &description)); + EXPECT_EQ("description1", description); + bool is_public = false; + EXPECT_TRUE(folio_value->GetBoolean("is_public", &is_public)); + EXPECT_TRUE(is_public); + std::string encoded_time_str; + EXPECT_TRUE(folio_value->GetString("created_timestamp_us", + &encoded_time_str)); + EXPECT_EQ(base::Int64ToString(created_time.ToInternalValue()), + encoded_time_str); + std::string position; + EXPECT_TRUE(folio_value->GetString("position", &position)); + EXPECT_EQ("position1", position); + std::string client_version; + EXPECT_TRUE(folio_value->GetString("client_version", &client_version)); + EXPECT_EQ("10", client_version); + + base::ListValue* meta_info_list; + ASSERT_TRUE(folio_value->GetList("meta_info", &meta_info_list)); + EXPECT_EQ(2u, meta_info_list->GetSize()); + base::DictionaryValue* meta_info; + std::string meta_key; + std::string meta_value; + ASSERT_TRUE(meta_info_list->GetDictionary(0, &meta_info)); + EXPECT_TRUE(meta_info->GetString("key", &meta_key)); + EXPECT_TRUE(meta_info->GetString("value", &meta_value)); + EXPECT_EQ("key1", meta_key); + EXPECT_EQ("value1", meta_value); + ASSERT_TRUE(meta_info_list->GetDictionary(1, &meta_info)); + EXPECT_TRUE(meta_info->GetString("key", &meta_key)); + EXPECT_TRUE(meta_info->GetString("value", &meta_value)); + EXPECT_EQ("key2", meta_key); + EXPECT_EQ("value2", meta_value); +} + TEST_F(ProtoValueConversionsTest, ExperimentsSpecificsToValue) { TestSpecificsToValue(ExperimentsSpecificsToValue); } @@ -282,6 +525,7 @@ TEST_F(ProtoValueConversionsTest, EntitySpecificsToValue) { SET_FIELD(bookmark); SET_FIELD(device_info); SET_FIELD(dictionary); + SET_FIELD(enhanced_bookmark); SET_FIELD(experiments); SET_FIELD(extension); SET_FIELD(extension_setting); diff --git a/sync/protocol/sync.proto b/sync/protocol/sync.proto index 8f27850..0bf4054 100644 --- a/sync/protocol/sync.proto +++ b/sync/protocol/sync.proto @@ -27,6 +27,7 @@ import "client_debug_info.proto"; import "device_info_specifics.proto"; import "dictionary_specifics.proto"; import "encryption.proto"; +import "enhanced_bookmark_specifics.proto"; import "experiments_specifics.proto"; import "extension_setting_specifics.proto"; import "extension_specifics.proto"; @@ -129,6 +130,7 @@ message EntitySpecifics { 202026; optional ArticleSpecifics article = 223759; optional AppListSpecifics app_list = 229170; + optional EnhancedBookmarkSpecifics enhanced_bookmark = 294694; } message SyncEntity { diff --git a/sync/sync.gyp b/sync/sync.gyp index f01ea81..6372fb70 100644 --- a/sync/sync.gyp +++ b/sync/sync.gyp @@ -473,6 +473,7 @@ 'protocol/device_info_specifics.proto', 'protocol/dictionary_specifics.proto', 'protocol/encryption.proto', + 'protocol/enhanced_bookmark_specifics.proto', 'protocol/experiments_specifics.proto', 'protocol/extension_setting_specifics.proto', 'protocol/extension_specifics.proto', diff --git a/sync/syncable/model_type.cc b/sync/syncable/model_type.cc index 59be6f2..ddde204 100644 --- a/sync/syncable/model_type.cc +++ b/sync/syncable/model_type.cc @@ -119,6 +119,9 @@ void AddDefaultFieldValue(ModelType datatype, case ARTICLES: specifics->mutable_article(); break; + case ENHANCED_BOOKMARKS: + specifics->mutable_enhanced_bookmark(); + break; default: NOTREACHED() << "No known extension for model type."; } @@ -196,6 +199,8 @@ int GetSpecificsFieldNumberFromModelType(ModelType model_type) { return sync_pb::EntitySpecifics::kManagedUserSharedSettingFieldNumber; case ARTICLES: return sync_pb::EntitySpecifics::kArticleFieldNumber; + case ENHANCED_BOOKMARKS: + return sync_pb::EntitySpecifics::kEnhancedBookmarkFieldNumber; default: NOTREACHED() << "No known extension for model type."; return 0; @@ -324,6 +329,9 @@ ModelType GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics& specifics) { if (specifics.has_article()) return ARTICLES; + if (specifics.has_enhanced_bookmark()) + return ENHANCED_BOOKMARKS; + return UNSPECIFIED; } @@ -366,6 +374,8 @@ bool IsUserSelectableType(ModelType model_type) { ModelTypeSet EncryptableUserTypes() { ModelTypeSet encryptable_user_types = UserTypes(); + // Encrypted bookmarks are handled through standard bookmark sync. + encryptable_user_types.Remove(ENHANCED_BOOKMARKS); // We never encrypt history delete directives. encryptable_user_types.Remove(HISTORY_DELETE_DIRECTIVES); // Synced notifications are not encrypted since the server must see changes. @@ -524,6 +534,8 @@ const char* ModelTypeToString(ModelType model_type) { return "Managed User Shared Settings"; case ARTICLES: return "Articles"; + case ENHANCED_BOOKMARKS: + return "Enhanced Bookmarks"; case PROXY_TABS: return "Tabs"; default: @@ -603,6 +615,8 @@ int ModelTypeToHistogramInt(ModelType model_type) { return 30; case SYNCED_NOTIFICATION_APP_INFO: return 31; + case ENHANCED_BOOKMARKS: + return 32; // Silence a compiler warning. case MODEL_TYPE_COUNT: return 0; @@ -698,6 +712,8 @@ ModelType ModelTypeFromString(const std::string& model_type_string) { return ARTICLES; else if (model_type_string == "Tabs") return PROXY_TABS; + else if (model_type_string == "Enhanced Bookmarks") + return ENHANCED_BOOKMARKS; else NOTREACHED() << "No known model type corresponding to " << model_type_string << "."; @@ -822,6 +838,8 @@ std::string ModelTypeToRootTag(ModelType type) { return "google_chrome_articles"; case PROXY_TABS: return std::string(); + case ENHANCED_BOOKMARKS: + return "google_chrome_enhanced_bookmarks"; default: break; } @@ -864,6 +882,7 @@ const char kSupervisedUserNotificationType[] = "MANAGED_USER"; const char kSupervisedUserSharedSettingNotificationType[] = "MANAGED_USER_SHARED_SETTING"; const char kArticleNotificationType[] = "ARTICLE"; +const char kEnhancedBookmarkNotificationType[] = "ENHANCED_BOOKMARK"; } // namespace bool RealModelTypeToNotificationType(ModelType model_type, @@ -956,6 +975,9 @@ bool RealModelTypeToNotificationType(ModelType model_type, case ARTICLES: *notification_type = kArticleNotificationType; return true; + case ENHANCED_BOOKMARKS: + *notification_type = kEnhancedBookmarkNotificationType; + return true; default: break; } @@ -1053,6 +1075,9 @@ bool NotificationTypeToRealModelType(const std::string& notification_type, } else if (notification_type == kArticleNotificationType) { *model_type = ARTICLES; return true; + } else if (notification_type == kEnhancedBookmarkNotificationType) { + *model_type = ENHANCED_BOOKMARKS; + return true; } *model_type = UNSPECIFIED; return false; diff --git a/sync/syncable/nigori_util.cc b/sync/syncable/nigori_util.cc index 63dbcac..eaf9eca 100644 --- a/sync/syncable/nigori_util.cc +++ b/sync/syncable/nigori_util.cc @@ -243,7 +243,7 @@ void UpdateNigoriFromEncryptedTypes(ModelTypeSet encrypted_types, bool encrypt_everything, sync_pb::NigoriSpecifics* nigori) { nigori->set_encrypt_everything(encrypt_everything); - COMPILE_ASSERT(32 == MODEL_TYPE_COUNT, UpdateEncryptedTypes); + COMPILE_ASSERT(33 == MODEL_TYPE_COUNT, UpdateEncryptedTypes); nigori->set_encrypt_bookmarks( encrypted_types.Has(BOOKMARKS)); nigori->set_encrypt_preferences( @@ -279,7 +279,7 @@ ModelTypeSet GetEncryptedTypesFromNigori( return ModelTypeSet::All(); ModelTypeSet encrypted_types; - COMPILE_ASSERT(32 == MODEL_TYPE_COUNT, UpdateEncryptedTypes); + COMPILE_ASSERT(33 == MODEL_TYPE_COUNT, UpdateEncryptedTypes); if (nigori.encrypt_bookmarks()) encrypted_types.Put(BOOKMARKS); if (nigori.encrypt_preferences()) diff --git a/sync/tools/testserver/chromiumsync.py b/sync/tools/testserver/chromiumsync.py index 2930059..2dcee1b 100644 --- a/sync/tools/testserver/chromiumsync.py +++ b/sync/tools/testserver/chromiumsync.py @@ -33,6 +33,7 @@ import bookmark_specifics_pb2 import client_commands_pb2 import dictionary_specifics_pb2 import get_updates_caller_info_pb2 +import enhanced_bookmark_specifics_pb2 import extension_setting_specifics_pb2 import extension_specifics_pb2 import favicon_image_specifics_pb2 @@ -72,6 +73,7 @@ ALL_TYPES = ( BOOKMARK, DEVICE_INFO, DICTIONARY, + ENHANCED_BOOKMARK, EXPERIMENTS, EXTENSIONS, HISTORY_DELETE_DIRECTIVE, @@ -90,7 +92,7 @@ ALL_TYPES = ( TYPED_URL, EXTENSION_SETTINGS, FAVICON_IMAGES, - FAVICON_TRACKING) = range(30) + FAVICON_TRACKING) = range(31) # An enumeration on the frequency at which the server should send errors # to the client. This would be specified by the url that triggers the error. @@ -117,6 +119,7 @@ SYNC_TYPE_TO_DESCRIPTOR = { BOOKMARK: SYNC_TYPE_FIELDS['bookmark'], DEVICE_INFO: SYNC_TYPE_FIELDS['device_info'], DICTIONARY: SYNC_TYPE_FIELDS['dictionary'], + ENHANCED_BOOKMARK: SYNC_TYPE_FIELDS['enhanced_bookmark'], EXPERIMENTS: SYNC_TYPE_FIELDS['experiments'], EXTENSION_SETTINGS: SYNC_TYPE_FIELDS['extension_setting'], EXTENSIONS: SYNC_TYPE_FIELDS['extension'], @@ -509,6 +512,9 @@ class SyncDataModel(object): parent_tag=ROOT_ID, sync_type=AUTOFILL_PROFILE), PermanentItem('google_chrome_device_info', name='Device Info', parent_tag=ROOT_ID, sync_type=DEVICE_INFO), + PermanentItem('google_chrome_enhanced_bookmarks', + name='Enhanced_Bookmarks', + parent_tag=ROOT_ID, sync_type=ENHANCED_BOOKMARK), PermanentItem('google_chrome_experiments', name='Experiments', parent_tag=ROOT_ID, sync_type=EXPERIMENTS), PermanentItem('google_chrome_extension_settings', diff --git a/sync/util/data_type_histogram.h b/sync/util/data_type_histogram.h index b5e0eda..980d3cc 100644 --- a/sync/util/data_type_histogram.h +++ b/sync/util/data_type_histogram.h @@ -126,6 +126,9 @@ case ::syncer::PROXY_TABS: \ PER_DATA_TYPE_MACRO("Tabs"); \ break; \ + case ::syncer::ENHANCED_BOOKMARKS: \ + PER_DATA_TYPE_MACRO("EnhancedBookmarks"); \ + break; \ default: \ NOTREACHED() << "Unknown datatype " \ << ::syncer::ModelTypeToString(datatype); \ diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index f2740b9..88857ba 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -52052,6 +52052,7 @@ To add a new entry, add it with any value and run test to compute valid value. <int value="29" label="App list"/> <int value="30" label="Managed User Shared Settings"/> <int value="31" label="Synced Notification App Info"/> + <int value="32" label="Enhanced Bookmarks"/> </enum> <enum name="SyncNigoriMigrationResult" type="int"> |