diff options
Diffstat (limited to 'chrome/browser')
84 files changed, 104 insertions, 10272 deletions
diff --git a/chrome/browser/sync/DEPS b/chrome/browser/sync/DEPS index 847cc5b..f3fa22a 100644 --- a/chrome/browser/sync/DEPS +++ b/chrome/browser/sync/DEPS @@ -1,9 +1,10 @@ include_rules = [ # For files not in a subdirectory (what a mess!). - "+sync/js", "+sync/engine/model_changing_syncer_command.h", "+sync/engine/model_safe_worker.h", "+sync/engine/polling_constants.h", + "+sync/internal_api", + "+sync/js", "+sync/notifier/invalidation_version_tracker.h", "+sync/sessions/session_state.h", "+sync/syncable/model_type.h", diff --git a/chrome/browser/sync/abstract_profile_sync_service_test.cc b/chrome/browser/sync/abstract_profile_sync_service_test.cc index 992e07f..1b83424 100644 --- a/chrome/browser/sync/abstract_profile_sync_service_test.cc +++ b/chrome/browser/sync/abstract_profile_sync_service_test.cc @@ -7,8 +7,8 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/location.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/test_profile_sync_service.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/sync.pb.h" #include "sync/syncable/syncable.h" #include "sync/test/engine/test_id_factory.h" diff --git a/chrome/browser/sync/abstract_profile_sync_service_test.h b/chrome/browser/sync/abstract_profile_sync_service_test.h index 066e88a..4f96945 100644 --- a/chrome/browser/sync/abstract_profile_sync_service_test.h +++ b/chrome/browser/sync/abstract_profile_sync_service_test.h @@ -13,9 +13,9 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop.h" #include "chrome/browser/signin/token_service.h" -#include "chrome/browser/sync/internal_api/change_record.h" #include "chrome/browser/sync/profile_sync_components_factory_mock.h" #include "content/test/test_browser_thread.h" +#include "sync/internal_api/change_record.h" #include "sync/syncable/model_type.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/sync/api/DEPS b/chrome/browser/sync/api/DEPS index c7a8609..4a424713 100644 --- a/chrome/browser/sync/api/DEPS +++ b/chrome/browser/sync/api/DEPS @@ -2,7 +2,7 @@ include_rules = [ "-chrome", "+chrome/browser/sync/api", - "+chrome/browser/sync/internal_api/base_node.h", + "+sync/internal_api/base_node.h", "+sync/protocol", "+sync/syncable/model_type.h", "+sync/util/immutable.h", diff --git a/chrome/browser/sync/api/sync_data.cc b/chrome/browser/sync/api/sync_data.cc index 02ca7008..e3e3dcd 100644 --- a/chrome/browser/sync/api/sync_data.cc +++ b/chrome/browser/sync/api/sync_data.cc @@ -10,7 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/string_number_conversions.h" #include "base/values.h" -#include "chrome/browser/sync/internal_api/base_node.h" +#include "sync/internal_api/base_node.h" #include "sync/protocol/proto_value_conversions.h" #include "sync/protocol/sync.pb.h" #include "sync/syncable/model_type.h" diff --git a/chrome/browser/sync/backend_migrator.cc b/chrome/browser/sync/backend_migrator.cc index f17ee99..26e0b2a 100644 --- a/chrome/browser/sync/backend_migrator.cc +++ b/chrome/browser/sync/backend_migrator.cc @@ -7,12 +7,12 @@ #include "base/message_loop.h" #include "base/string_number_conversions.h" #include "base/tracked_objects.h" -#include "chrome/browser/sync/internal_api/configure_reason.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/common/chrome_notification_types.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" +#include "sync/internal_api/configure_reason.h" +#include "sync/internal_api/read_transaction.h" #include "sync/protocol/sync.pb.h" #include "sync/sessions/session_state.h" diff --git a/chrome/browser/sync/backend_migrator_unittest.cc b/chrome/browser/sync/backend_migrator_unittest.cc index 3dd8cbf..a9cfd34 100644 --- a/chrome/browser/sync/backend_migrator_unittest.cc +++ b/chrome/browser/sync/backend_migrator_unittest.cc @@ -7,10 +7,10 @@ #include "base/message_loop.h" #include "base/tracked_objects.h" #include "chrome/browser/sync/glue/data_type_manager_mock.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/profile_sync_service_mock.h" -#include "chrome/browser/sync/test/engine/test_user_share.h" #include "chrome/common/chrome_notification_types.h" +#include "sync/internal_api/test_user_share.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/sync.pb.h" #include "sync/sessions/session_state.h" #include "sync/syncable/model_type_test_util.h" diff --git a/chrome/browser/sync/glue/DEPS b/chrome/browser/sync/glue/DEPS index 0ad6258..260f38a 100644 --- a/chrome/browser/sync/glue/DEPS +++ b/chrome/browser/sync/glue/DEPS @@ -3,10 +3,9 @@ include_rules = [ "-sync/sessions", "-sync/syncable", + "+sync/internal_api", "+sync/util", - "+chrome/browser/sync/internal_api", - "+jingle/notifier/base", # Should these live in their own "includes" (e.g) directory(ies)? @@ -23,7 +22,6 @@ include_rules = [ # Mocks/tests. "+sync/engine/syncapi_mock.h", - "+chrome/browser/sync/notifier/mock_sync_notifier_observer.h", "+sync/syncable/model_type_test_util.h", "+sync/syncable/syncable_mock.h", diff --git a/chrome/browser/sync/glue/backend_data_type_configurer.h b/chrome/browser/sync/glue/backend_data_type_configurer.h index 2b77a3b..88dc4d7 100644 --- a/chrome/browser/sync/glue/backend_data_type_configurer.h +++ b/chrome/browser/sync/glue/backend_data_type_configurer.h @@ -7,7 +7,7 @@ #pragma once #include "base/callback.h" -#include "chrome/browser/sync/internal_api/configure_reason.h" +#include "sync/internal_api/configure_reason.h" #include "sync/syncable/model_type.h" namespace browser_sync { diff --git a/chrome/browser/sync/glue/bookmark_change_processor.cc b/chrome/browser/sync/glue/bookmark_change_processor.cc index ebf6c8d..8bf4d83 100644 --- a/chrome/browser/sync/glue/bookmark_change_processor.cc +++ b/chrome/browser/sync/glue/bookmark_change_processor.cc @@ -15,12 +15,12 @@ #include "chrome/browser/bookmarks/bookmark_utils.h" #include "chrome/browser/favicon/favicon_service.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sync/internal_api/change_record.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/profile_sync_service.h" #include "content/public/browser/browser_thread.h" +#include "sync/internal_api/change_record.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/syncable/syncable.h" // TODO(tim): Investigating bug 121587. #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/codec/png_codec.h" diff --git a/chrome/browser/sync/glue/bookmark_model_associator.cc b/chrome/browser/sync/glue/bookmark_model_associator.cc index 795eb58..a626265 100644 --- a/chrome/browser/sync/glue/bookmark_model_associator.cc +++ b/chrome/browser/sync/glue/bookmark_model_associator.cc @@ -16,11 +16,11 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/api/sync_error.h" #include "chrome/browser/sync/glue/bookmark_change_processor.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "content/public/browser/browser_thread.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/read_transaction.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/util/cryptographer.h" using content::BrowserThread; diff --git a/chrome/browser/sync/glue/change_processor.h b/chrome/browser/sync/glue/change_processor.h index 22e1cd1..8dd4349 100644 --- a/chrome/browser/sync/glue/change_processor.h +++ b/chrome/browser/sync/glue/change_processor.h @@ -8,7 +8,7 @@ #include "chrome/browser/sync/glue/data_type_error_handler.h" #include "chrome/browser/sync/glue/sync_backend_host.h" -#include "chrome/browser/sync/internal_api/change_record.h" +#include "sync/internal_api/change_record.h" class Profile; diff --git a/chrome/browser/sync/glue/data_type_manager.h b/chrome/browser/sync/glue/data_type_manager.h index f491900..5034b7e 100644 --- a/chrome/browser/sync/glue/data_type_manager.h +++ b/chrome/browser/sync/glue/data_type_manager.h @@ -13,7 +13,7 @@ #include "base/memory/scoped_ptr.h" #include "chrome/browser/sync/api/sync_error.h" #include "chrome/browser/sync/glue/data_type_controller.h" -#include "chrome/browser/sync/internal_api/configure_reason.h" +#include "sync/internal_api/configure_reason.h" #include "sync/syncable/model_type.h" namespace browser_sync { diff --git a/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc b/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc index 6459664..1c22526 100644 --- a/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc +++ b/chrome/browser/sync/glue/data_type_manager_impl_unittest.cc @@ -8,13 +8,13 @@ #include "base/message_loop.h" #include "chrome/browser/sync/glue/backend_data_type_configurer.h" #include "chrome/browser/sync/glue/data_type_controller.h" -#include "chrome/browser/sync/internal_api/configure_reason.h" #include "chrome/common/chrome_notification_types.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_service.h" #include "content/test/notification_observer_mock.h" #include "content/test/test_browser_thread.h" +#include "sync/internal_api/configure_reason.h" #include "sync/syncable/model_type.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/sync/glue/generic_change_processor.cc b/chrome/browser/sync/glue/generic_change_processor.cc index 017b1ed..89837ce 100644 --- a/chrome/browser/sync/glue/generic_change_processor.cc +++ b/chrome/browser/sync/glue/generic_change_processor.cc @@ -10,13 +10,13 @@ #include "chrome/browser/sync/api/sync_change.h" #include "chrome/browser/sync/api/sync_error.h" #include "chrome/browser/sync/api/syncable_service.h" -#include "chrome/browser/sync/internal_api/base_node.h" -#include "chrome/browser/sync/internal_api/change_record.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "content/public/browser/browser_thread.h" +#include "sync/internal_api/base_node.h" +#include "sync/internal_api/change_record.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/read_transaction.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/util/unrecoverable_error_handler.h" using content::BrowserThread; diff --git a/chrome/browser/sync/glue/http_bridge.h b/chrome/browser/sync/glue/http_bridge.h index 0eddab6..3e7e98e 100644 --- a/chrome/browser/sync/glue/http_bridge.h +++ b/chrome/browser/sync/glue/http_bridge.h @@ -14,12 +14,12 @@ #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" -#include "chrome/browser/sync/internal_api/http_post_provider_factory.h" -#include "chrome/browser/sync/internal_api/http_post_provider_interface.h" #include "content/public/common/url_fetcher_delegate.h" #include "googleurl/src/gurl.h" -#include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_getter.h" +#include "sync/internal_api/http_post_provider_factory.h" +#include "sync/internal_api/http_post_provider_interface.h" class MessageLoop; class HttpBridgeTest; diff --git a/chrome/browser/sync/glue/password_change_processor.cc b/chrome/browser/sync/glue/password_change_processor.cc index b453105..ad3572c 100644 --- a/chrome/browser/sync/glue/password_change_processor.cc +++ b/chrome/browser/sync/glue/password_change_processor.cc @@ -13,15 +13,15 @@ #include "chrome/browser/password_manager/password_store_change.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/glue/password_model_associator.h" -#include "chrome/browser/sync/internal_api/change_record.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_notification_types.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" +#include "sync/internal_api/change_record.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/password_specifics.pb.h" #include "webkit/forms/password_form.h" diff --git a/chrome/browser/sync/glue/password_model_associator.cc b/chrome/browser/sync/glue/password_model_associator.cc index 74c79be..75820eb 100644 --- a/chrome/browser/sync/glue/password_model_associator.cc +++ b/chrome/browser/sync/glue/password_model_associator.cc @@ -11,12 +11,12 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/password_manager/password_store.h" #include "chrome/browser/sync/api/sync_error.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/profile_sync_service.h" #include "net/base/escape.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/read_transaction.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/password_specifics.pb.h" #include "webkit/forms/password_form.h" diff --git a/chrome/browser/sync/glue/session_change_processor.cc b/chrome/browser/sync/glue/session_change_processor.cc index b4dd8bf..cf146c8 100644 --- a/chrome/browser/sync/glue/session_change_processor.cc +++ b/chrome/browser/sync/glue/session_change_processor.cc @@ -13,8 +13,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/api/sync_error.h" #include "chrome/browser/sync/glue/session_model_associator.h" -#include "chrome/browser/sync/internal_api/change_record.h" -#include "chrome/browser/sync/internal_api/read_node.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/ui/sync/tab_contents_wrapper_synced_tab_delegate.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" @@ -25,6 +23,8 @@ #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/web_contents.h" +#include "sync/internal_api/change_record.h" +#include "sync/internal_api/read_node.h" #include "sync/protocol/session_specifics.pb.h" #include "sync/syncable/model_type.h" #include "sync/syncable/model_type_payload_map.h" diff --git a/chrome/browser/sync/glue/session_model_associator.cc b/chrome/browser/sync/glue/session_model_associator.cc index bf5db1b..ed3b664 100644 --- a/chrome/browser/sync/glue/session_model_associator.cc +++ b/chrome/browser/sync/glue/session_model_associator.cc @@ -21,10 +21,6 @@ #include "chrome/browser/sync/glue/synced_session.h" #include "chrome/browser/sync/glue/synced_tab_delegate.h" #include "chrome/browser/sync/glue/synced_window_delegate.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_switches.h" @@ -33,10 +29,14 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/read_transaction.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/session_specifics.pb.h" -#include "sync/syncable/syncable.h" #include "sync/syncable/model_type.h" #include "sync/syncable/model_type_payload_map.h" +#include "sync/syncable/syncable.h" #include "sync/util/get_session_name.h" #if defined(OS_LINUX) #include "base/linux_util.h" diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc index 97aaa31..0d59793 100644 --- a/chrome/browser/sync/glue/sync_backend_host.cc +++ b/chrome/browser/sync/glue/sync_backend_host.cc @@ -27,8 +27,6 @@ #include "chrome/browser/sync/glue/chrome_encryptor.h" #include "chrome/browser/sync/glue/http_bridge.h" #include "chrome/browser/sync/glue/sync_backend_registrar.h" -#include "chrome/browser/sync/internal_api/base_transaction.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" #include "chrome/browser/sync/sync_prefs.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_switches.h" @@ -42,6 +40,8 @@ #include "net/base/host_port_pair.h" #include "net/url_request/url_request_context_getter.h" #include "sync/engine/model_safe_worker.h" +#include "sync/internal_api/base_transaction.h" +#include "sync/internal_api/read_transaction.h" #include "sync/notifier/sync_notifier.h" #include "sync/protocol/encryption.pb.h" #include "sync/protocol/sync.pb.h" diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h index d809230..3073d6d 100644 --- a/chrome/browser/sync/glue/sync_backend_host.h +++ b/chrome/browser/sync/glue/sync_backend_host.h @@ -18,11 +18,11 @@ #include "chrome/browser/sync/glue/backend_data_type_configurer.h" #include "chrome/browser/sync/glue/chrome_extensions_activity_monitor.h" #include "chrome/browser/sync/glue/chrome_sync_notification_bridge.h" -#include "chrome/browser/sync/internal_api/configure_reason.h" -#include "chrome/browser/sync/internal_api/sync_manager.h" #include "chrome/common/net/gaia/google_service_auth_error.h" #include "googleurl/src/gurl.h" #include "sync/engine/model_safe_worker.h" +#include "sync/internal_api/configure_reason.h" +#include "sync/internal_api/sync_manager.h" #include "sync/notifier/sync_notifier_factory.h" #include "sync/protocol/encryption.pb.h" #include "sync/protocol/sync_protocol_error.h" diff --git a/chrome/browser/sync/glue/sync_backend_registrar.h b/chrome/browser/sync/glue/sync_backend_registrar.h index 9e636af..20b4308 100644 --- a/chrome/browser/sync/glue/sync_backend_registrar.h +++ b/chrome/browser/sync/glue/sync_backend_registrar.h @@ -13,8 +13,8 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" -#include "chrome/browser/sync/internal_api/sync_manager.h" #include "sync/engine/model_safe_worker.h" +#include "sync/internal_api/sync_manager.h" #include "sync/syncable/model_type.h" class MessageLoop; diff --git a/chrome/browser/sync/glue/sync_backend_registrar_unittest.cc b/chrome/browser/sync/glue/sync_backend_registrar_unittest.cc index e5ec7d4..4f84e81 100644 --- a/chrome/browser/sync/glue/sync_backend_registrar_unittest.cc +++ b/chrome/browser/sync/glue/sync_backend_registrar_unittest.cc @@ -6,9 +6,9 @@ #include "chrome/browser/sync/glue/change_processor_mock.h" #include "chrome/browser/sync/glue/ui_model_worker.h" -#include "chrome/browser/sync/test/engine/test_user_share.h" #include "chrome/test/base/testing_profile.h" #include "content/test/test_browser_thread.h" +#include "sync/internal_api/test_user_share.h" #include "sync/syncable/model_type.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/sync/glue/theme_change_processor.cc b/chrome/browser/sync/glue/theme_change_processor.cc index af77b5b..fb58a97 100644 --- a/chrome/browser/sync/glue/theme_change_processor.cc +++ b/chrome/browser/sync/glue/theme_change_processor.cc @@ -9,16 +9,16 @@ #include "base/string_number_conversions.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/glue/theme_util.h" -#include "chrome/browser/sync/internal_api/change_record.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/themes/theme_service_factory.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/extensions/extension.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" +#include "sync/internal_api/change_record.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/theme_specifics.pb.h" #include "sync/util/unrecoverable_error_handler.h" diff --git a/chrome/browser/sync/glue/theme_model_associator.cc b/chrome/browser/sync/glue/theme_model_associator.cc index f48a829..99e0970 100644 --- a/chrome/browser/sync/glue/theme_model_associator.cc +++ b/chrome/browser/sync/glue/theme_model_associator.cc @@ -11,11 +11,11 @@ #include "chrome/browser/sync/api/sync_error.h" #include "chrome/browser/sync/glue/sync_backend_host.h" #include "chrome/browser/sync/glue/theme_util.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/profile_sync_service.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/read_transaction.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/theme_specifics.pb.h" namespace browser_sync { diff --git a/chrome/browser/sync/glue/typed_url_change_processor.cc b/chrome/browser/sync/glue/typed_url_change_processor.cc index 05cd86c..69933e0 100644 --- a/chrome/browser/sync/glue/typed_url_change_processor.cc +++ b/chrome/browser/sync/glue/typed_url_change_processor.cc @@ -11,13 +11,13 @@ #include "chrome/browser/history/history_notifications.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/glue/typed_url_model_associator.h" -#include "chrome/browser/sync/internal_api/change_record.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/common/chrome_notification_types.h" #include "content/public/browser/notification_service.h" +#include "sync/internal_api/change_record.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/typed_url_specifics.pb.h" using content::BrowserThread; diff --git a/chrome/browser/sync/glue/typed_url_model_associator.cc b/chrome/browser/sync/glue/typed_url_model_associator.cc index 80031c3..1dd8279 100644 --- a/chrome/browser/sync/glue/typed_url_model_associator.cc +++ b/chrome/browser/sync/glue/typed_url_model_associator.cc @@ -12,11 +12,11 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/history/history_backend.h" #include "chrome/browser/sync/api/sync_error.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/profile_sync_service.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/read_transaction.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/typed_url_specifics.pb.h" using content::BrowserThread; diff --git a/chrome/browser/sync/internal_api/DEPS b/chrome/browser/sync/internal_api/DEPS deleted file mode 100644 index 5f69c7a..0000000 --- a/chrome/browser/sync/internal_api/DEPS +++ /dev/null @@ -1,11 +0,0 @@ -include_rules = [ - "-chrome", - "-content", - "+chrome/test/base", - - "+chrome/browser/sync", - "-chrome/browser/sync/api", - "-chrome/browser/sync/glue", - - "+sync", -] diff --git a/chrome/browser/sync/internal_api/README b/chrome/browser/sync/internal_api/README deleted file mode 100644 index 32987bb..0000000 --- a/chrome/browser/sync/internal_api/README +++ /dev/null @@ -1,32 +0,0 @@ -This file defines the "sync API", an interface to the syncer -backend that exposes (1) the core functionality of maintaining a consistent -local snapshot of a hierarchical object set; (2) a means to transactionally -access and modify those objects; (3) a means to control client/server -synchronization tasks, namely: pushing local object modifications to a -server, pulling nonlocal object modifications from a server to this client, -and resolving conflicts that may arise between the two; and (4) an -abstraction of some external functionality that is to be provided by the -host environment. - -This interface is used as the entry point into the syncer backend -when the backend is compiled as a library and embedded in another -application. A goal for this interface layer is to depend on very few -external types, so that an application can use the sync backend -without introducing a dependency on specific types. A non-goal is to -have binary compatibility across versions or compilers; this allows the -interface to use C++ classes. An application wishing to use the sync API -should ideally compile the syncer backend and this API as part of the -application's own build, to avoid e.g. mismatches in calling convention, -structure padding, or name mangling that could arise if there were a -compiler mismatch. - -The schema of the objects in the sync domain is based on the model, which -is essentially a hierarchy of items and folders similar to a filesystem, -but with a few important differences. The sync API contains fields -such as URL to easily allow the embedding application to store web -browser bookmarks. Also, the sync API allows duplicate titles in a parent. -Consequently, it does not support looking up an object by title -and parent, since such a lookup is not uniquely determined. Lastly, -unlike a filesystem model, objects in the Sync API model have a strict -ordering within a parent; the position is manipulable by callers, and -children of a node can be enumerated in the order of their position. diff --git a/chrome/browser/sync/internal_api/all_status.cc b/chrome/browser/sync/internal_api/all_status.cc deleted file mode 100644 index c47dac4..0000000 --- a/chrome/browser/sync/internal_api/all_status.cc +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/all_status.h" - -#include <algorithm> - -#include "base/logging.h" -#include "base/port.h" -#include "sync/engine/net/server_connection_manager.h" -#include "sync/protocol/service_constants.h" -#include "sync/sessions/session_state.h" -#include "sync/syncable/model_type.h" - -namespace browser_sync { - -AllStatus::AllStatus() { - status_.initial_sync_ended = true; - status_.notifications_enabled = false; - status_.cryptographer_ready = false; - status_.crypto_has_pending_keys = false; -} - -AllStatus::~AllStatus() { -} - -sync_api::SyncManager::Status AllStatus::CreateBlankStatus() const { - // Status is initialized with the previous status value. Variables - // whose values accumulate (e.g. lifetime counters like updates_received) - // are not to be cleared here. - sync_api::SyncManager::Status status = status_; - status.unsynced_count = 0; - status.encryption_conflicts = 0; - status.hierarchy_conflicts = 0; - status.simple_conflicts = 0; - status.server_conflicts = 0; - status.committed_count = 0; - status.initial_sync_ended = false; - status.updates_available = 0; - return status; -} - -sync_api::SyncManager::Status AllStatus::CalcSyncing( - const SyncEngineEvent &event) const { - sync_api::SyncManager::Status status = CreateBlankStatus(); - const sessions::SyncSessionSnapshot* snapshot = event.snapshot; - status.unsynced_count = static_cast<int>(snapshot->unsynced_count); - status.encryption_conflicts = snapshot->num_encryption_conflicts; - status.hierarchy_conflicts = snapshot->num_hierarchy_conflicts; - status.simple_conflicts = snapshot->num_simple_conflicts; - status.server_conflicts = snapshot->num_server_conflicts; - status.committed_count = snapshot->syncer_status.num_successful_commits; - - if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_BEGIN) { - status.syncing = true; - } else if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) { - status.syncing = false; - } - - status.initial_sync_ended |= snapshot->is_share_usable; - - status.updates_available += snapshot->num_server_changes_remaining; - status.sync_protocol_error = snapshot->errors.sync_protocol_error; - - // Accumulate update count only once per session to avoid double-counting. - // TODO(ncarter): Make this realtime by having the syncer_status - // counter preserve its value across sessions. http://crbug.com/26339 - if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) { - status.updates_received += - snapshot->syncer_status.num_updates_downloaded_total; - status.tombstone_updates_received += - snapshot->syncer_status.num_tombstone_updates_downloaded_total; - status.reflected_updates_received += - snapshot->syncer_status.num_reflected_updates_downloaded_total; - status.num_local_overwrites_total += - snapshot->syncer_status.num_local_overwrites; - status.num_server_overwrites_total += - snapshot->syncer_status.num_server_overwrites; - if (snapshot->syncer_status.num_updates_downloaded_total == 0) { - ++status.empty_get_updates; - } else { - ++status.nonempty_get_updates; - } - if (snapshot->syncer_status.num_successful_commits == 0) { - ++status.sync_cycles_without_commits; - } else { - ++status.sync_cycles_with_commits; - } - if (snapshot->syncer_status.num_successful_commits == 0 && - snapshot->syncer_status.num_updates_downloaded_total == 0) { - ++status.useless_sync_cycles; - } else { - ++status.useful_sync_cycles; - } - } - return status; -} - -void AllStatus::OnSyncEngineEvent(const SyncEngineEvent& event) { - ScopedStatusLock lock(this); - switch (event.what_happened) { - case SyncEngineEvent::SYNC_CYCLE_BEGIN: - case SyncEngineEvent::STATUS_CHANGED: - case SyncEngineEvent::SYNC_CYCLE_ENDED: - status_ = CalcSyncing(event); - break; - case SyncEngineEvent::STOP_SYNCING_PERMANENTLY: - case SyncEngineEvent::UPDATED_TOKEN: - case SyncEngineEvent::CLEAR_SERVER_DATA_FAILED: - case SyncEngineEvent::CLEAR_SERVER_DATA_SUCCEEDED: - break; - case SyncEngineEvent::ACTIONABLE_ERROR: - status_ = CreateBlankStatus(); - status_.sync_protocol_error = event.snapshot->errors.sync_protocol_error; - break; - default: - LOG(ERROR) << "Unrecognized Syncer Event: " << event.what_happened; - break; - } -} - -sync_api::SyncManager::Status AllStatus::status() const { - base::AutoLock lock(mutex_); - return status_; -} - -void AllStatus::SetNotificationsEnabled(bool notifications_enabled) { - ScopedStatusLock lock(this); - status_.notifications_enabled = notifications_enabled; -} - -void AllStatus::IncrementNotificationsReceived() { - ScopedStatusLock lock(this); - ++status_.notifications_received; -} - -void AllStatus::SetEncryptedTypes(syncable::ModelTypeSet types) { - ScopedStatusLock lock(this); - status_.encrypted_types = types; -} - -void AllStatus::SetCryptographerReady(bool ready) { - ScopedStatusLock lock(this); - status_.cryptographer_ready = ready; -} - -void AllStatus::SetCryptoHasPendingKeys(bool has_pending_keys) { - ScopedStatusLock lock(this); - status_.crypto_has_pending_keys = has_pending_keys; -} - -void AllStatus::SetUniqueId(const std::string& guid) { - ScopedStatusLock lock(this); - status_.unique_id = guid; -} - -ScopedStatusLock::ScopedStatusLock(AllStatus* allstatus) - : allstatus_(allstatus) { - allstatus->mutex_.Acquire(); -} - -ScopedStatusLock::~ScopedStatusLock() { - allstatus_->mutex_.Release(); -} - -} // namespace browser_sync diff --git a/chrome/browser/sync/internal_api/all_status.h b/chrome/browser/sync/internal_api/all_status.h deleted file mode 100644 index 7cea022..0000000 --- a/chrome/browser/sync/internal_api/all_status.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// The AllStatus object watches various sync engine components and aggregates -// the status of all of them into one place. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_ALL_STATUS_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_ALL_STATUS_H_ -#pragma once - -#include <map> - -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/synchronization/lock.h" -#include "chrome/browser/sync/internal_api/sync_manager.h" -#include "sync/engine/syncer_types.h" -#include "sync/syncable/model_type.h" - -namespace browser_sync { - -class ScopedStatusLock; -struct ServerConnectionEvent; - -// TODO(rlarocque): -// Most of this data ends up on the about:sync page. But the page is only -// 'pinged' to update itself at the end of a sync cycle. A user could refresh -// manually, but unless their timing is excellent it's unlikely that a user will -// see any state in mid-sync cycle. We have no plans to change this. -// -// What we do intend to do is improve the UI so that changes following a sync -// cycle are more visible. Without such a change, the status summary for a -// healthy syncer will constantly display as "READY" and never provide any -// indication of a sync cycle being performed. See crbug.com/108100. - -class AllStatus : public SyncEngineEventListener { - friend class ScopedStatusLock; - public: - AllStatus(); - virtual ~AllStatus(); - - virtual void OnSyncEngineEvent(const SyncEngineEvent& event) OVERRIDE; - - sync_api::SyncManager::Status status() const; - - void SetNotificationsEnabled(bool notifications_enabled); - - void IncrementNotifiableCommits(); - - void IncrementNotificationsReceived(); - - void SetEncryptedTypes(syncable::ModelTypeSet types); - void SetCryptographerReady(bool ready); - void SetCryptoHasPendingKeys(bool has_pending_keys); - - void SetUniqueId(const std::string& guid); - - protected: - // Examines syncer to calculate syncing and the unsynced count, - // and returns a Status with new values. - sync_api::SyncManager::Status CalcSyncing(const SyncEngineEvent& event) const; - sync_api::SyncManager::Status CreateBlankStatus() const; - - sync_api::SyncManager::Status status_; - - mutable base::Lock mutex_; // Protects all data members. - DISALLOW_COPY_AND_ASSIGN(AllStatus); -}; - -class ScopedStatusLock { - public: - explicit ScopedStatusLock(AllStatus* allstatus); - ~ScopedStatusLock(); - protected: - AllStatus* allstatus_; -}; - -} // namespace browser_sync - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_ALL_STATUS_H_ diff --git a/chrome/browser/sync/internal_api/base_node.cc b/chrome/browser/sync/internal_api/base_node.cc deleted file mode 100644 index bd766be..0000000 --- a/chrome/browser/sync/internal_api/base_node.cc +++ /dev/null @@ -1,346 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/base_node.h" - -#include "base/base64.h" -#include "base/sha1.h" -#include "base/string_number_conversions.h" -#include "base/utf_string_conversions.h" -#include "base/values.h" -#include "chrome/browser/sync/internal_api/syncapi_internal.h" -#include "chrome/browser/sync/internal_api/base_transaction.h" -#include "sync/protocol/app_specifics.pb.h" -#include "sync/protocol/autofill_specifics.pb.h" -#include "sync/protocol/bookmark_specifics.pb.h" -#include "sync/protocol/extension_specifics.pb.h" -#include "sync/protocol/nigori_specifics.pb.h" -#include "sync/protocol/password_specifics.pb.h" -#include "sync/protocol/session_specifics.pb.h" -#include "sync/protocol/theme_specifics.pb.h" -#include "sync/protocol/typed_url_specifics.pb.h" -#include "sync/syncable/syncable.h" -#include "sync/syncable/syncable_id.h" -#include "sync/util/time.h" - -using syncable::SPECIFICS; -using sync_pb::AutofillProfileSpecifics; - -namespace sync_api { - -// Helper function to look up the int64 metahandle of an object given the ID -// string. -static int64 IdToMetahandle(syncable::BaseTransaction* trans, - const syncable::Id& id) { - syncable::Entry entry(trans, syncable::GET_BY_ID, id); - if (!entry.good()) - return kInvalidId; - return entry.Get(syncable::META_HANDLE); -} - -static bool EndsWithSpace(const std::string& string) { - return !string.empty() && *string.rbegin() == ' '; -} - -// In the reverse direction, if a server name matches the pattern of a -// server-illegal name followed by one or more spaces, remove the trailing -// space. -static void ServerNameToSyncAPIName(const std::string& server_name, - std::string* out) { - CHECK(out); - int length_to_copy = server_name.length(); - if (IsNameServerIllegalAfterTrimming(server_name) && - EndsWithSpace(server_name)) { - --length_to_copy; - } - *out = std::string(server_name.c_str(), length_to_copy); -} - -BaseNode::BaseNode() : password_data_(new sync_pb::PasswordSpecificsData) {} - -BaseNode::~BaseNode() {} - -std::string BaseNode::GenerateSyncableHash( - syncable::ModelType model_type, const std::string& client_tag) { - // Blank PB with just the field in it has termination symbol, - // handy for delimiter. - sync_pb::EntitySpecifics serialized_type; - syncable::AddDefaultFieldValue(model_type, &serialized_type); - std::string hash_input; - serialized_type.AppendToString(&hash_input); - hash_input.append(client_tag); - - std::string encode_output; - CHECK(base::Base64Encode(base::SHA1HashString(hash_input), &encode_output)); - return encode_output; -} - -bool BaseNode::DecryptIfNecessary() { - if (!GetEntry()->Get(syncable::UNIQUE_SERVER_TAG).empty()) - return true; // Ignore unique folders. - const sync_pb::EntitySpecifics& specifics = - GetEntry()->Get(syncable::SPECIFICS); - if (specifics.has_password()) { - // Passwords have their own legacy encryption structure. - scoped_ptr<sync_pb::PasswordSpecificsData> data(DecryptPasswordSpecifics( - specifics, GetTransaction()->GetCryptographer())); - if (!data.get()) { - LOG(ERROR) << "Failed to decrypt password specifics."; - return false; - } - password_data_.swap(data); - return true; - } - - // We assume any node with the encrypted field set has encrypted data and if - // not we have no work to do, with the exception of bookmarks. For bookmarks - // we must make sure the bookmarks data has the title field supplied. If not, - // we fill the unencrypted_data_ with a copy of the bookmark specifics that - // follows the new bookmarks format. - if (!specifics.has_encrypted()) { - if (GetModelType() == syncable::BOOKMARKS && - !specifics.bookmark().has_title() && - !GetTitle().empty()) { // Last check ensures this isn't a new node. - // We need to fill in the title. - std::string title = GetTitle(); - std::string server_legal_title; - SyncAPINameToServerName(title, &server_legal_title); - DVLOG(1) << "Reading from legacy bookmark, manually returning title " - << title; - unencrypted_data_.CopyFrom(specifics); - unencrypted_data_.mutable_bookmark()->set_title( - server_legal_title); - } - return true; - } - - const sync_pb::EncryptedData& encrypted = specifics.encrypted(); - std::string plaintext_data = GetTransaction()->GetCryptographer()-> - DecryptToString(encrypted); - if (plaintext_data.length() == 0 || - !unencrypted_data_.ParseFromString(plaintext_data)) { - LOG(ERROR) << "Failed to decrypt encrypted node of type " << - syncable::ModelTypeToString(GetModelType()) << "."; - return false; - } - DVLOG(2) << "Decrypted specifics of type " - << syncable::ModelTypeToString(GetModelType()) - << " with content: " << plaintext_data; - return true; -} - -const sync_pb::EntitySpecifics& BaseNode::GetUnencryptedSpecifics( - const syncable::Entry* entry) const { - const sync_pb::EntitySpecifics& specifics = entry->Get(SPECIFICS); - if (specifics.has_encrypted()) { - DCHECK_NE(syncable::GetModelTypeFromSpecifics(unencrypted_data_), - syncable::UNSPECIFIED); - return unencrypted_data_; - } else { - // Due to the change in bookmarks format, we need to check to see if this is - // a legacy bookmarks (and has no title field in the proto). If it is, we - // return the unencrypted_data_, which was filled in with the title by - // DecryptIfNecessary(). - if (GetModelType() == syncable::BOOKMARKS) { - const sync_pb::BookmarkSpecifics& bookmark_specifics = - specifics.bookmark(); - if (bookmark_specifics.has_title() || - GetTitle().empty() || // For the empty node case - !GetEntry()->Get(syncable::UNIQUE_SERVER_TAG).empty()) { - // It's possible we previously had to convert and set - // |unencrypted_data_| but then wrote our own data, so we allow - // |unencrypted_data_| to be non-empty. - return specifics; - } else { - DCHECK_EQ(syncable::GetModelTypeFromSpecifics(unencrypted_data_), - syncable::BOOKMARKS); - return unencrypted_data_; - } - } else { - DCHECK_EQ(syncable::GetModelTypeFromSpecifics(unencrypted_data_), - syncable::UNSPECIFIED); - return specifics; - } - } -} - -int64 BaseNode::GetParentId() const { - return IdToMetahandle(GetTransaction()->GetWrappedTrans(), - GetEntry()->Get(syncable::PARENT_ID)); -} - -int64 BaseNode::GetId() const { - return GetEntry()->Get(syncable::META_HANDLE); -} - -const base::Time& BaseNode::GetModificationTime() const { - return GetEntry()->Get(syncable::MTIME); -} - -bool BaseNode::GetIsFolder() const { - return GetEntry()->Get(syncable::IS_DIR); -} - -std::string BaseNode::GetTitle() const { - std::string result; - // TODO(zea): refactor bookmarks to not need this functionality. - if (syncable::BOOKMARKS == GetModelType() && - GetEntry()->Get(syncable::SPECIFICS).has_encrypted()) { - // Special case for legacy bookmarks dealing with encryption. - ServerNameToSyncAPIName(GetBookmarkSpecifics().title(), &result); - } else { - ServerNameToSyncAPIName(GetEntry()->Get(syncable::NON_UNIQUE_NAME), - &result); - } - return result; -} - -GURL BaseNode::GetURL() const { - return GURL(GetBookmarkSpecifics().url()); -} - -bool BaseNode::HasChildren() const { - syncable::Directory* dir = GetTransaction()->GetDirectory(); - syncable::BaseTransaction* trans = GetTransaction()->GetWrappedTrans(); - return dir->HasChildren(trans, GetEntry()->Get(syncable::ID)); -} - -int64 BaseNode::GetPredecessorId() const { - syncable::Id id_string = GetEntry()->Get(syncable::PREV_ID); - if (id_string.IsRoot()) - return kInvalidId; - return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string); -} - -int64 BaseNode::GetSuccessorId() const { - syncable::Id id_string = GetEntry()->Get(syncable::NEXT_ID); - if (id_string.IsRoot()) - return kInvalidId; - return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string); -} - -int64 BaseNode::GetFirstChildId() const { - syncable::Directory* dir = GetTransaction()->GetDirectory(); - syncable::BaseTransaction* trans = GetTransaction()->GetWrappedTrans(); - syncable::Id id_string; - // TODO(akalin): Propagate up the error further (see - // http://crbug.com/100907). - CHECK(dir->GetFirstChildId(trans, - GetEntry()->Get(syncable::ID), &id_string)); - if (id_string.IsRoot()) - return kInvalidId; - return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string); -} - -DictionaryValue* BaseNode::GetSummaryAsValue() const { - DictionaryValue* node_info = new DictionaryValue(); - node_info->SetString("id", base::Int64ToString(GetId())); - node_info->SetBoolean("isFolder", GetIsFolder()); - node_info->SetString("title", GetTitle()); - node_info->Set("type", ModelTypeToValue(GetModelType())); - return node_info; -} - -DictionaryValue* BaseNode::GetDetailsAsValue() const { - DictionaryValue* node_info = GetSummaryAsValue(); - node_info->SetString( - "modificationTime", - browser_sync::GetTimeDebugString(GetModificationTime())); - node_info->SetString("parentId", base::Int64ToString(GetParentId())); - // Specifics are already in the Entry value, so no need to duplicate - // it here. - node_info->SetString("externalId", - base::Int64ToString(GetExternalId())); - node_info->SetString("predecessorId", - base::Int64ToString(GetPredecessorId())); - node_info->SetString("successorId", - base::Int64ToString(GetSuccessorId())); - node_info->SetString("firstChildId", - base::Int64ToString(GetFirstChildId())); - node_info->Set("entry", GetEntry()->ToValue()); - return node_info; -} - -void BaseNode::GetFaviconBytes(std::vector<unsigned char>* output) const { - if (!output) - return; - const std::string& favicon = GetBookmarkSpecifics().favicon(); - output->assign(reinterpret_cast<const unsigned char*>(favicon.data()), - reinterpret_cast<const unsigned char*>(favicon.data() + - favicon.length())); -} - -int64 BaseNode::GetExternalId() const { - return GetEntry()->Get(syncable::LOCAL_EXTERNAL_ID); -} - -const sync_pb::AppSpecifics& BaseNode::GetAppSpecifics() const { - DCHECK_EQ(syncable::APPS, GetModelType()); - return GetEntitySpecifics().app(); -} - -const sync_pb::AutofillSpecifics& BaseNode::GetAutofillSpecifics() const { - DCHECK_EQ(syncable::AUTOFILL, GetModelType()); - return GetEntitySpecifics().autofill(); -} - -const AutofillProfileSpecifics& BaseNode::GetAutofillProfileSpecifics() const { - DCHECK_EQ(GetModelType(), syncable::AUTOFILL_PROFILE); - return GetEntitySpecifics().autofill_profile(); -} - -const sync_pb::BookmarkSpecifics& BaseNode::GetBookmarkSpecifics() const { - DCHECK_EQ(syncable::BOOKMARKS, GetModelType()); - return GetEntitySpecifics().bookmark(); -} - -const sync_pb::NigoriSpecifics& BaseNode::GetNigoriSpecifics() const { - DCHECK_EQ(syncable::NIGORI, GetModelType()); - return GetEntitySpecifics().nigori(); -} - -const sync_pb::PasswordSpecificsData& BaseNode::GetPasswordSpecifics() const { - DCHECK_EQ(syncable::PASSWORDS, GetModelType()); - return *password_data_; -} - -const sync_pb::ThemeSpecifics& BaseNode::GetThemeSpecifics() const { - DCHECK_EQ(syncable::THEMES, GetModelType()); - return GetEntitySpecifics().theme(); -} - -const sync_pb::TypedUrlSpecifics& BaseNode::GetTypedUrlSpecifics() const { - DCHECK_EQ(syncable::TYPED_URLS, GetModelType()); - return GetEntitySpecifics().typed_url(); -} - -const sync_pb::ExtensionSpecifics& BaseNode::GetExtensionSpecifics() const { - DCHECK_EQ(syncable::EXTENSIONS, GetModelType()); - return GetEntitySpecifics().extension(); -} - -const sync_pb::SessionSpecifics& BaseNode::GetSessionSpecifics() const { - DCHECK_EQ(syncable::SESSIONS, GetModelType()); - return GetEntitySpecifics().session(); -} - -const sync_pb::EntitySpecifics& BaseNode::GetEntitySpecifics() const { - return GetUnencryptedSpecifics(GetEntry()); -} - -syncable::ModelType BaseNode::GetModelType() const { - return GetEntry()->GetModelType(); -} - -void BaseNode::SetUnencryptedSpecifics( - const sync_pb::EntitySpecifics& specifics) { - syncable::ModelType type = syncable::GetModelTypeFromSpecifics(specifics); - DCHECK_NE(syncable::UNSPECIFIED, type); - if (GetModelType() != syncable::UNSPECIFIED) { - DCHECK_EQ(GetModelType(), type); - } - unencrypted_data_.CopyFrom(specifics); -} - -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/base_node.h b/chrome/browser/sync/internal_api/base_node.h deleted file mode 100644 index dbf720a..0000000 --- a/chrome/browser/sync/internal_api/base_node.h +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_BASE_NODE_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_BASE_NODE_H_ -#pragma once - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "googleurl/src/gurl.h" -#include "sync/protocol/sync.pb.h" -#include "sync/syncable/model_type.h" - -// Forward declarations of internal class types so that sync API objects -// may have opaque pointers to these types. -namespace base { -class DictionaryValue; -} - -namespace syncable { -class BaseTransaction; -class Entry; -} - -namespace sync_pb { -class AppSpecifics; -class AutofillSpecifics; -class AutofillProfileSpecifics; -class BookmarkSpecifics; -class EntitySpecifics; -class ExtensionSpecifics; -class SessionSpecifics; -class NigoriSpecifics; -class PreferenceSpecifics; -class PasswordSpecificsData; -class ThemeSpecifics; -class TypedUrlSpecifics; -} - -namespace sync_api { - -class BaseTransaction; - -// A valid BaseNode will never have an ID of zero. -static const int64 kInvalidId = 0; - -// BaseNode wraps syncable::Entry, and corresponds to a single object's state. -// This, like syncable::Entry, is intended for use on the stack. A valid -// transaction is necessary to create a BaseNode or any of its children. -// Unlike syncable::Entry, a sync API BaseNode is identified primarily by its -// int64 metahandle, which we call an ID here. -class BaseNode { - public: - // Enumerates the possible outcomes of trying to initialize a sync node. - enum InitByLookupResult { - INIT_OK, - // Could not find an entry matching the lookup criteria. - INIT_FAILED_ENTRY_NOT_GOOD, - // Found an entry, but it is already deleted. - INIT_FAILED_ENTRY_IS_DEL, - // Found an entry, but was unable to decrypt. - INIT_FAILED_DECRYPT_IF_NECESSARY, - // A precondition was not met for calling init, such as legal input - // arguments. - INIT_FAILED_PRECONDITION, - }; - - // All subclasses of BaseNode must provide a way to initialize themselves by - // doing an ID lookup. Returns false on failure. An invalid or deleted - // ID will result in failure. - virtual InitByLookupResult InitByIdLookup(int64 id) = 0; - - // All subclasses of BaseNode must also provide a way to initialize themselves - // by doing a client tag lookup. Returns false on failure. A deleted node - // will return FALSE. - virtual InitByLookupResult InitByClientTagLookup( - syncable::ModelType model_type, - const std::string& tag) = 0; - - // Each object is identified by a 64-bit id (internally, the syncable - // metahandle). These ids are strictly local handles. They will persist - // on this client, but the same object on a different client may have a - // different ID value. - virtual int64 GetId() const; - - // Returns the modification time of the object. - const base::Time& GetModificationTime() const; - - // Nodes are hierarchically arranged into a single-rooted tree. - // InitByRootLookup on ReadNode allows access to the root. GetParentId is - // how you find a node's parent. - int64 GetParentId() const; - - // Nodes are either folders or not. This corresponds to the IS_DIR property - // of syncable::Entry. - bool GetIsFolder() const; - - // Returns the title of the object. - // Uniqueness of the title is not enforced on siblings -- it is not an error - // for two children to share a title. - std::string GetTitle() const; - - // Returns the model type of this object. The model type is set at node - // creation time and is expected never to change. - syncable::ModelType GetModelType() const; - - // Getter specific to the BOOKMARK datatype. Returns protobuf - // data. Can only be called if GetModelType() == BOOKMARK. - const sync_pb::BookmarkSpecifics& GetBookmarkSpecifics() const; - - // Legacy, bookmark-specific getter that wraps GetBookmarkSpecifics() above. - // Returns the URL of a bookmark object. - // TODO(ncarter): Remove this datatype-specific accessor. - GURL GetURL() const; - - // Legacy, bookmark-specific getter that wraps GetBookmarkSpecifics() above. - // Fill in a vector with the byte data of this node's favicon. Assumes - // that the node is a bookmark. - // Favicons are expected to be PNG images, and though no verification is - // done on the syncapi client of this, the server may reject favicon updates - // that are invalid for whatever reason. - // TODO(ncarter): Remove this datatype-specific accessor. - void GetFaviconBytes(std::vector<unsigned char>* output) const; - - // Getter specific to the APPS datatype. Returns protobuf - // data. Can only be called if GetModelType() == APPS. - const sync_pb::AppSpecifics& GetAppSpecifics() const; - - // Getter specific to the AUTOFILL datatype. Returns protobuf - // data. Can only be called if GetModelType() == AUTOFILL. - const sync_pb::AutofillSpecifics& GetAutofillSpecifics() const; - - virtual const sync_pb::AutofillProfileSpecifics& - GetAutofillProfileSpecifics() const; - - // Getter specific to the NIGORI datatype. Returns protobuf - // data. Can only be called if GetModelType() == NIGORI. - const sync_pb::NigoriSpecifics& GetNigoriSpecifics() const; - - // Getter specific to the PASSWORD datatype. Returns protobuf - // data. Can only be called if GetModelType() == PASSWORD. - const sync_pb::PasswordSpecificsData& GetPasswordSpecifics() const; - - // Getter specific to the PREFERENCE datatype. Returns protobuf - // data. Can only be called if GetModelType() == PREFERENCE. - const sync_pb::PreferenceSpecifics& GetPreferenceSpecifics() const; - - // Getter specific to the THEME datatype. Returns protobuf - // data. Can only be called if GetModelType() == THEME. - const sync_pb::ThemeSpecifics& GetThemeSpecifics() const; - - // Getter specific to the TYPED_URLS datatype. Returns protobuf - // data. Can only be called if GetModelType() == TYPED_URLS. - const sync_pb::TypedUrlSpecifics& GetTypedUrlSpecifics() const; - - // Getter specific to the EXTENSIONS datatype. Returns protobuf - // data. Can only be called if GetModelType() == EXTENSIONS. - const sync_pb::ExtensionSpecifics& GetExtensionSpecifics() const; - - // Getter specific to the SESSIONS datatype. Returns protobuf - // data. Can only be called if GetModelType() == SESSIONS. - const sync_pb::SessionSpecifics& GetSessionSpecifics() const; - - const sync_pb::EntitySpecifics& GetEntitySpecifics() const; - - // Returns the local external ID associated with the node. - int64 GetExternalId() const; - - // Returns true iff this node has children. - bool HasChildren() const; - - // Return the ID of the node immediately before this in the sibling order. - // For the first node in the ordering, return 0. - int64 GetPredecessorId() const; - - // Return the ID of the node immediately after this in the sibling order. - // For the last node in the ordering, return 0. - int64 GetSuccessorId() const; - - // Return the ID of the first child of this node. If this node has no - // children, return 0. - int64 GetFirstChildId() const; - - // These virtual accessors provide access to data members of derived classes. - virtual const syncable::Entry* GetEntry() const = 0; - virtual const BaseTransaction* GetTransaction() const = 0; - - // Dumps a summary of node info into a DictionaryValue and returns it. - // Transfers ownership of the DictionaryValue to the caller. - base::DictionaryValue* GetSummaryAsValue() const; - - // Dumps all node details into a DictionaryValue and returns it. - // Transfers ownership of the DictionaryValue to the caller. - base::DictionaryValue* GetDetailsAsValue() const; - - protected: - BaseNode(); - virtual ~BaseNode(); - // The server has a size limit on client tags, so we generate a fixed length - // hash locally. This also ensures that ModelTypes have unique namespaces. - static std::string GenerateSyncableHash(syncable::ModelType model_type, - const std::string& client_tag); - - // Determines whether part of the entry is encrypted, and if so attempts to - // decrypt it. Unless decryption is necessary and fails, this will always - // return |true|. If the contents are encrypted, the decrypted data will be - // stored in |unencrypted_data_|. - // This method is invoked once when the BaseNode is initialized. - bool DecryptIfNecessary(); - - // Returns the unencrypted specifics associated with |entry|. If |entry| was - // not encrypted, it directly returns |entry|'s EntitySpecifics. Otherwise, - // returns |unencrypted_data_|. - const sync_pb::EntitySpecifics& GetUnencryptedSpecifics( - const syncable::Entry* entry) const; - - // Copy |specifics| into |unencrypted_data_|. - void SetUnencryptedSpecifics(const sync_pb::EntitySpecifics& specifics); - - private: - // Have to friend the test class as well to allow member functions to access - // protected/private BaseNode methods. - friend class SyncManagerTest; - FRIEND_TEST_ALL_PREFIXES(SyncApiTest, GenerateSyncableHash); - FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, UpdateEntryWithEncryption); - FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, - UpdatePasswordSetEntitySpecificsNoChange); - FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, UpdatePasswordSetPasswordSpecifics); - FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, UpdatePasswordNewPassphrase); - FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, UpdatePasswordReencryptEverything); - FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetBookmarkTitle); - FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetBookmarkTitleWithEncryption); - FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetNonBookmarkTitle); - FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetNonBookmarkTitleWithEncryption); - FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, SetPreviouslyEncryptedSpecifics); - - void* operator new(size_t size); // Node is meant for stack use only. - - // A holder for the unencrypted data stored in an encrypted node. - sync_pb::EntitySpecifics unencrypted_data_; - - // Same as |unencrypted_data_|, but for legacy password encryption. - scoped_ptr<sync_pb::PasswordSpecificsData> password_data_; - - DISALLOW_COPY_AND_ASSIGN(BaseNode); -}; - -} // namespace sync_api - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_BASE_NODE_H_ diff --git a/chrome/browser/sync/internal_api/base_transaction.cc b/chrome/browser/sync/internal_api/base_transaction.cc deleted file mode 100644 index d14384e..0000000 --- a/chrome/browser/sync/internal_api/base_transaction.cc +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/base_transaction.h" - -#include "sync/syncable/syncable.h" -#include "sync/util/cryptographer.h" - -using browser_sync::Cryptographer; - -namespace sync_api { - -////////////////////////////////////////////////////////////////////////// -// BaseTransaction member definitions -BaseTransaction::BaseTransaction(UserShare* share) { - DCHECK(share && share->directory.get()); - directory_ = share->directory.get(); -} -BaseTransaction::~BaseTransaction() { -} - -browser_sync::Cryptographer* BaseTransaction::GetCryptographer() const { - return directory_->GetCryptographer(this->GetWrappedTrans()); -} - -syncable::ModelTypeSet GetEncryptedTypes( - const sync_api::BaseTransaction* trans) { - return trans->GetCryptographer()->GetEncryptedTypes(); -} - -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/base_transaction.h b/chrome/browser/sync/internal_api/base_transaction.h deleted file mode 100644 index bf3fa9c..0000000 --- a/chrome/browser/sync/internal_api/base_transaction.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_BASE_TRANSACTION_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_BASE_TRANSACTION_H_ -#pragma once - -#include "chrome/browser/sync/internal_api/user_share.h" - -#include "sync/util/cryptographer.h" - -namespace syncable { -class BaseTransaction; -class Directory; -} - -namespace sync_api { - -// Sync API's BaseTransaction, ReadTransaction, and WriteTransaction allow for -// batching of several read and/or write operations. The read and write -// operations are performed by creating ReadNode and WriteNode instances using -// the transaction. These transaction classes wrap identically named classes in -// syncable, and are used in a similar way. Unlike syncable::BaseTransaction, -// whose construction requires an explicit syncable::Directory, a sync -// API BaseTransaction is created from a UserShare object. -class BaseTransaction { - public: - // Provide access to the underlying syncable.h objects from BaseNode. - virtual syncable::BaseTransaction* GetWrappedTrans() const = 0; - browser_sync::Cryptographer* GetCryptographer() const; - - syncable::Directory* GetDirectory() const { - return directory_; - } - - protected: - explicit BaseTransaction(UserShare* share); - virtual ~BaseTransaction(); - - BaseTransaction() : directory_(NULL) { } - - private: - syncable::Directory* directory_; - - DISALLOW_COPY_AND_ASSIGN(BaseTransaction); -}; - -syncable::ModelTypeSet GetEncryptedTypes( - const sync_api::BaseTransaction* trans); - -} // namespace sync_api - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_BASE_TRANSACTION_H_ diff --git a/chrome/browser/sync/internal_api/change_record.cc b/chrome/browser/sync/internal_api/change_record.cc deleted file mode 100644 index f130203..0000000 --- a/chrome/browser/sync/internal_api/change_record.cc +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/change_record.h" - -#include "base/string_number_conversions.h" -#include "base/values.h" -#include "chrome/browser/sync/internal_api/base_node.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "sync/protocol/proto_value_conversions.h" - -namespace sync_api { - -ChangeRecord::ChangeRecord() - : id(kInvalidId), action(ACTION_ADD) {} - -ChangeRecord::~ChangeRecord() {} - -DictionaryValue* ChangeRecord::ToValue() const { - DictionaryValue* value = new DictionaryValue(); - std::string action_str; - switch (action) { - case ACTION_ADD: - action_str = "Add"; - break; - case ACTION_DELETE: - action_str = "Delete"; - break; - case ACTION_UPDATE: - action_str = "Update"; - break; - default: - NOTREACHED(); - action_str = "Unknown"; - break; - } - value->SetString("action", action_str); - value->SetString("id", base::Int64ToString(id)); - if (action == ACTION_DELETE) { - if (extra.get()) { - value->Set("extra", extra->ToValue()); - } - value->Set("specifics", - browser_sync::EntitySpecificsToValue(specifics)); - } - return value; -} - -ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData() {} - -ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData( - const sync_pb::PasswordSpecificsData& data) - : unencrypted_(data) { -} - -ExtraPasswordChangeRecordData::~ExtraPasswordChangeRecordData() {} - -DictionaryValue* ExtraPasswordChangeRecordData::ToValue() const { - return browser_sync::PasswordSpecificsDataToValue(unencrypted_); -} - -const sync_pb::PasswordSpecificsData& - ExtraPasswordChangeRecordData::unencrypted() const { - return unencrypted_; -} - -} // namespace sync_api - diff --git a/chrome/browser/sync/internal_api/change_record.h b/chrome/browser/sync/internal_api/change_record.h deleted file mode 100644 index 4d0b527..0000000 --- a/chrome/browser/sync/internal_api/change_record.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_CHANGE_RECORD_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_CHANGE_RECORD_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "base/memory/linked_ptr.h" -#include "sync/protocol/password_specifics.pb.h" -#include "sync/protocol/sync.pb.h" -#include "sync/util/immutable.h" - -namespace base { -class DictionaryValue; -} // namespace base - -namespace sync_api { - -// TODO(zea): One day get passwords playing nicely with the rest of encryption -// and get rid of this. -class ExtraPasswordChangeRecordData { - public: - ExtraPasswordChangeRecordData(); - explicit ExtraPasswordChangeRecordData( - const sync_pb::PasswordSpecificsData& data); - virtual ~ExtraPasswordChangeRecordData(); - - // Transfers ownership of the DictionaryValue to the caller. - virtual base::DictionaryValue* ToValue() const; - - const sync_pb::PasswordSpecificsData& unencrypted() const; - private: - sync_pb::PasswordSpecificsData unencrypted_; -}; - -// ChangeRecord indicates a single item that changed as a result of a sync -// operation. This gives the sync id of the node that changed, and the type -// of change. To get the actual property values after an ADD or UPDATE, the -// client should get the node with InitByIdLookup(), using the provided id. -struct ChangeRecord { - enum Action { - ACTION_ADD, - ACTION_DELETE, - ACTION_UPDATE, - }; - ChangeRecord(); - ~ChangeRecord(); - - // Transfers ownership of the DictionaryValue to the caller. - base::DictionaryValue* ToValue() const; - - int64 id; - Action action; - sync_pb::EntitySpecifics specifics; - linked_ptr<ExtraPasswordChangeRecordData> extra; -}; - -typedef std::vector<ChangeRecord> ChangeRecordList; - -typedef browser_sync::Immutable<ChangeRecordList> ImmutableChangeRecordList; - -} // namespace sync_api - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_CHANGE_RECORD_H_ diff --git a/chrome/browser/sync/internal_api/change_record_unittest.cc b/chrome/browser/sync/internal_api/change_record_unittest.cc deleted file mode 100644 index ac99510..0000000 --- a/chrome/browser/sync/internal_api/change_record_unittest.cc +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/change_record.h" - -#include "base/memory/scoped_ptr.h" -#include "base/string_number_conversions.h" -#include "base/test/values_test_util.h" -#include "base/values.h" -#include "sync/protocol/extension_specifics.pb.h" -#include "sync/protocol/proto_value_conversions.h" -#include "sync/protocol/sync.pb.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace sync_api { -namespace { - -using base::ExpectDictDictionaryValue; -using base::ExpectDictStringValue; -using testing::Invoke; -using testing::StrictMock; - -class ChangeRecordTest : public testing::Test {}; - -void ExpectChangeRecordActionValue(ChangeRecord::Action expected_value, - const base::DictionaryValue& value, - const std::string& key) { - std::string str_value; - EXPECT_TRUE(value.GetString(key, &str_value)); - switch (expected_value) { - case ChangeRecord::ACTION_ADD: - EXPECT_EQ("Add", str_value); - break; - case ChangeRecord::ACTION_UPDATE: - EXPECT_EQ("Update", str_value); - break; - case ChangeRecord::ACTION_DELETE: - EXPECT_EQ("Delete", str_value); - break; - default: - NOTREACHED(); - break; - } -} - -void CheckChangeRecordValue( - const ChangeRecord& record, - const base::DictionaryValue& value) { - ExpectChangeRecordActionValue(record.action, value, "action"); - ExpectDictStringValue(base::Int64ToString(record.id), value, "id"); - if (record.action == ChangeRecord::ACTION_DELETE) { - scoped_ptr<base::DictionaryValue> expected_extra_value; - if (record.extra.get()) { - expected_extra_value.reset(record.extra->ToValue()); - } - base::Value* extra_value = NULL; - EXPECT_EQ(record.extra.get() != NULL, - value.Get("extra", &extra_value)); - EXPECT_TRUE(Value::Equals(extra_value, expected_extra_value.get())); - - scoped_ptr<DictionaryValue> expected_specifics_value( - browser_sync::EntitySpecificsToValue(record.specifics)); - ExpectDictDictionaryValue(*expected_specifics_value, - value, "specifics"); - } -} - -class MockExtraChangeRecordData - : public ExtraPasswordChangeRecordData { - public: - MOCK_CONST_METHOD0(ToValue, DictionaryValue*()); -}; - -TEST_F(ChangeRecordTest, ChangeRecordToValue) { - sync_pb::EntitySpecifics old_specifics; - old_specifics.mutable_extension()->set_id("old"); - sync_pb::EntitySpecifics new_specifics; - old_specifics.mutable_extension()->set_id("new"); - - const int64 kTestId = 5; - - // Add - { - ChangeRecord record; - record.action = ChangeRecord::ACTION_ADD; - record.id = kTestId; - record.specifics = old_specifics; - record.extra.reset(new StrictMock<MockExtraChangeRecordData>()); - scoped_ptr<DictionaryValue> value(record.ToValue()); - CheckChangeRecordValue(record, *value); - } - - // Update - { - ChangeRecord record; - record.action = ChangeRecord::ACTION_UPDATE; - record.id = kTestId; - record.specifics = old_specifics; - record.extra.reset(new StrictMock<MockExtraChangeRecordData>()); - scoped_ptr<DictionaryValue> value(record.ToValue()); - CheckChangeRecordValue(record, *value); - } - - // Delete (no extra) - { - ChangeRecord record; - record.action = ChangeRecord::ACTION_DELETE; - record.id = kTestId; - record.specifics = old_specifics; - scoped_ptr<DictionaryValue> value(record.ToValue()); - CheckChangeRecordValue(record, *value); - } - - // Delete (with extra) - { - ChangeRecord record; - record.action = ChangeRecord::ACTION_DELETE; - record.id = kTestId; - record.specifics = old_specifics; - - DictionaryValue extra_value; - extra_value.SetString("foo", "bar"); - scoped_ptr<StrictMock<MockExtraChangeRecordData> > extra( - new StrictMock<MockExtraChangeRecordData>()); - EXPECT_CALL(*extra, ToValue()).Times(2).WillRepeatedly( - Invoke(&extra_value, &DictionaryValue::DeepCopy)); - - record.extra.reset(extra.release()); - scoped_ptr<DictionaryValue> value(record.ToValue()); - CheckChangeRecordValue(record, *value); - } -} - -} // namespace -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/change_reorder_buffer.cc b/chrome/browser/sync/internal_api/change_reorder_buffer.cc deleted file mode 100644 index f262ff6..0000000 --- a/chrome/browser/sync/internal_api/change_reorder_buffer.cc +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/change_reorder_buffer.h" - -#include <limits> -#include <queue> -#include <set> -#include <utility> // for pair<> -#include <vector> - -#include "chrome/browser/sync/internal_api/read_node.h" -#include "sync/syncable/model_type.h" -#include "sync/syncable/syncable.h" - -using std::numeric_limits; -using std::pair; -using std::queue; -using std::set; -using std::vector; - -namespace sync_api { - -// Traversal provides a way to collect a set of nodes from the syncable -// directory structure and then traverse them, along with any intermediate -// nodes, in a top-down fashion, starting from a single common ancestor. A -// Traversal starts out empty and is grown by means of the ExpandToInclude -// method. Once constructed, the top(), begin_children(), and end_children() -// methods can be used to explore the nodes in root-to-leaf order. -class ChangeReorderBuffer::Traversal { - public: - typedef pair<int64, int64> ParentChildLink; - typedef set<ParentChildLink> LinkSet; - - Traversal() : top_(kInvalidId) { } - - // Expand the traversal so that it includes the node indicated by - // |child_handle|. - void ExpandToInclude(syncable::BaseTransaction* trans, - int64 child_handle) { - // If |top_| is invalid, this is the first insertion -- easy. - if (top_ == kInvalidId) { - top_ = child_handle; - return; - } - - int64 node_to_include = child_handle; - while (node_to_include != kInvalidId && node_to_include != top_) { - int64 node_parent = 0; - - syncable::Entry node(trans, syncable::GET_BY_HANDLE, node_to_include); - CHECK(node.good()); - if (node.Get(syncable::ID).IsRoot()) { - // If we've hit the root, and the root isn't already in the tree - // (it would have to be |top_| if it were), start a new expansion - // upwards from |top_| to unite the original traversal with the - // path we just added that goes from |child_handle| to the root. - node_to_include = top_; - top_ = node.Get(syncable::META_HANDLE); - } else { - // Otherwise, get the parent ID so that we can add a ParentChildLink. - syncable::Entry parent(trans, syncable::GET_BY_ID, - node.Get(syncable::PARENT_ID)); - CHECK(parent.good()); - node_parent = parent.Get(syncable::META_HANDLE); - - ParentChildLink link(node_parent, node_to_include); - - // If the link exists in the LinkSet |links_|, we don't need to search - // any higher; we are done. - if (links_.find(link) != links_.end()) - return; - - // Otherwise, extend |links_|, and repeat on the parent. - links_.insert(link); - node_to_include = node_parent; - } - } - } - - // Return the top node of the traversal. Use this as a starting point - // for walking the tree. - int64 top() const { return top_; } - - // Return an iterator corresponding to the first child (in the traversal) - // of the node specified by |parent_id|. Iterate this return value until - // it is equal to the value returned by end_children(parent_id). The - // enumeration thus provided is unordered. - LinkSet::const_iterator begin_children(int64 parent_id) const { - return links_.upper_bound( - ParentChildLink(parent_id, numeric_limits<int64>::min())); - } - - // Return an iterator corresponding to the last child in the traversal - // of the node specified by |parent_id|. - LinkSet::const_iterator end_children(int64 parent_id) const { - return begin_children(parent_id + 1); - } - - private: - // The topmost point in the directory hierarchy that is in the traversal, - // and thus the first node to be traversed. If the traversal is empty, - // this is kInvalidId. If the traversal contains exactly one member, |top_| - // will be the solitary member, and |links_| will be empty. - int64 top_; - // A set of single-level links that compose the traversal below |top_|. The - // (parent, child) ordering of values enables efficient lookup of children - // given the parent handle, which is used for top-down traversal. |links_| - // is expected to be connected -- every node that appears as a parent in a - // link must either appear as a child of another link, or else be the - // topmost node, |top_|. - LinkSet links_; - - DISALLOW_COPY_AND_ASSIGN(Traversal); -}; - -ChangeReorderBuffer::ChangeReorderBuffer() { -} - -ChangeReorderBuffer::~ChangeReorderBuffer() { -} - -bool ChangeReorderBuffer::GetAllChangesInTreeOrder( - const BaseTransaction* sync_trans, - ImmutableChangeRecordList* changes) { - syncable::BaseTransaction* trans = sync_trans->GetWrappedTrans(); - - // Step 1: Iterate through the operations, doing three things: - // (a) Push deleted items straight into the |changelist|. - // (b) Construct a traversal spanning all non-deleted items. - // (c) Construct a set of all parent nodes of any position changes. - set<int64> parents_of_position_changes; - Traversal traversal; - - ChangeRecordList changelist; - - OperationMap::const_iterator i; - for (i = operations_.begin(); i != operations_.end(); ++i) { - if (i->second == OP_DELETE) { - ChangeRecord record; - record.id = i->first; - record.action = ChangeRecord::ACTION_DELETE; - if (specifics_.find(record.id) != specifics_.end()) - record.specifics = specifics_[record.id]; - if (extra_data_.find(record.id) != extra_data_.end()) - record.extra = extra_data_[record.id]; - changelist.push_back(record); - } else { - traversal.ExpandToInclude(trans, i->first); - if (i->second == OP_ADD || - i->second == OP_UPDATE_POSITION_AND_PROPERTIES) { - ReadNode node(sync_trans); - CHECK_EQ(BaseNode::INIT_OK, node.InitByIdLookup(i->first)); - - // We only care about parents of entry's with position-sensitive models. - if (syncable::ShouldMaintainPosition( - node.GetEntry()->GetModelType())) { - parents_of_position_changes.insert(node.GetParentId()); - } - } - } - } - - // Step 2: Breadth-first expansion of the traversal, enumerating children in - // the syncable sibling order if there were any position updates. - queue<int64> to_visit; - to_visit.push(traversal.top()); - while (!to_visit.empty()) { - int64 next = to_visit.front(); - to_visit.pop(); - - // If the node has an associated action, output a change record. - i = operations_.find(next); - if (i != operations_.end()) { - ChangeRecord record; - record.id = next; - if (i->second == OP_ADD) - record.action = ChangeRecord::ACTION_ADD; - else - record.action = ChangeRecord::ACTION_UPDATE; - if (specifics_.find(record.id) != specifics_.end()) - record.specifics = specifics_[record.id]; - if (extra_data_.find(record.id) != extra_data_.end()) - record.extra = extra_data_[record.id]; - changelist.push_back(record); - } - - // Now add the children of |next| to |to_visit|. - if (parents_of_position_changes.find(next) == - parents_of_position_changes.end()) { - // No order changes on this parent -- traverse only the nodes listed - // in the traversal (and not in sibling order). - Traversal::LinkSet::const_iterator j = traversal.begin_children(next); - Traversal::LinkSet::const_iterator end = traversal.end_children(next); - for (; j != end; ++j) { - CHECK(j->first == next); - to_visit.push(j->second); - } - } else { - // There were ordering changes on the children of this parent, so - // enumerate all the children in the sibling order. - syncable::Entry parent(trans, syncable::GET_BY_HANDLE, next); - syncable::Id id; - if (!trans->directory()->GetFirstChildId( - trans, parent.Get(syncable::ID), &id)) { - *changes = ImmutableChangeRecordList(); - return false; - } - while (!id.IsRoot()) { - syncable::Entry child(trans, syncable::GET_BY_ID, id); - CHECK(child.good()); - int64 handle = child.Get(syncable::META_HANDLE); - to_visit.push(handle); - // If there is no operation on this child node, record it as as an - // update, so that the listener gets notified of all nodes in the new - // ordering. - if (operations_.find(handle) == operations_.end()) - operations_[handle] = OP_UPDATE_POSITION_AND_PROPERTIES; - id = child.Get(syncable::NEXT_ID); - } - } - } - - *changes = ImmutableChangeRecordList(&changelist); - return true; -} - -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/change_reorder_buffer.h b/chrome/browser/sync/internal_api/change_reorder_buffer.h deleted file mode 100644 index f474dd5..0000000 --- a/chrome/browser/sync/internal_api/change_reorder_buffer.h +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Defines ChangeReorderBuffer, which can be used to sort a list of item -// actions to achieve the ordering constraint required by the SyncObserver -// interface of the SyncAPI. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_CHANGE_REORDER_BUFFER_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_CHANGE_REORDER_BUFFER_H_ -#pragma once - -#include <map> -#include <vector> - -#include "base/compiler_specific.h" -#include "base/memory/linked_ptr.h" -#include "chrome/browser/sync/internal_api/base_transaction.h" -#include "chrome/browser/sync/internal_api/change_record.h" -#include "sync/protocol/sync.pb.h" - -namespace sync_api { - -// ChangeReorderBuffer is a utility type which accepts an unordered set -// of changes (via its Push methods), and yields an ImmutableChangeRecordList -// (via the GetAllChangesInTreeOrder method) that are in the order that -// the SyncObserver expects them to be. A buffer is initially empty. -// -// The ordering produced by ChangeReorderBuffer is as follows: -// (a) All Deleted items appear first. -// (b) For Updated and/or Added items, parents appear before their children. -// (c) When there are changes to the sibling order (this means Added items, -// or Updated items with the |position_changed| parameter set to true), -// all siblings under a parent will appear in the output, even if they -// are not explicitly pushed. The sibling order will be preserved in -// the output list -- items will appear before their sibling-order -// successors. -// (d) When there are no changes to the sibling order under a parent node, -// the sibling order is not necessarily preserved in the output for -// its children. -class ChangeReorderBuffer { - public: - ChangeReorderBuffer(); - ~ChangeReorderBuffer(); - - // Insert an item, identified by the metahandle |id|, into the reorder - // buffer. This item will appear in the output list as an ACTION_ADD - // ChangeRecord. - void PushAddedItem(int64 id) { - operations_[id] = OP_ADD; - } - - // Insert an item, identified by the metahandle |id|, into the reorder - // buffer. This item will appear in the output list as an ACTION_DELETE - // ChangeRecord. - void PushDeletedItem(int64 id) { - operations_[id] = OP_DELETE; - } - - // Insert an item, identified by the metahandle |id|, into the reorder - // buffer. This item will appear in the output list as an ACTION_UPDATE - // ChangeRecord. Also, if |position_changed| is true, all siblings of this - // item will appear in the output list as well; if it wasn't explicitly - // pushed, the siblings will have an ACTION_UPDATE ChangeRecord. - void PushUpdatedItem(int64 id, bool position_changed) { - operations_[id] = position_changed ? OP_UPDATE_POSITION_AND_PROPERTIES : - OP_UPDATE_PROPERTIES_ONLY; - } - - void SetExtraDataForId(int64 id, ExtraPasswordChangeRecordData* extra) { - extra_data_[id] = make_linked_ptr<ExtraPasswordChangeRecordData>(extra); - } - - void SetSpecificsForId(int64 id, const sync_pb::EntitySpecifics& specifics) { - specifics_[id] = specifics; - } - - // Reset the buffer, forgetting any pushed items, so that it can be used - // again to reorder a new set of changes. - void Clear() { - operations_.clear(); - } - - bool IsEmpty() const { - return operations_.empty(); - } - - // Output a reordered list of changes to |changes| using the items - // that were pushed into the reorder buffer. |sync_trans| is used to - // determine the ordering. Returns true if successful, or false if - // an error was encountered. - bool GetAllChangesInTreeOrder( - const BaseTransaction* sync_trans, - ImmutableChangeRecordList* changes) WARN_UNUSED_RESULT; - - private: - class Traversal; - enum Operation { - OP_ADD, // AddedItem. - OP_DELETE, // DeletedItem. - OP_UPDATE_PROPERTIES_ONLY, // UpdatedItem with position_changed=0. - OP_UPDATE_POSITION_AND_PROPERTIES, // UpdatedItem with position_changed=1. - }; - typedef std::map<int64, Operation> OperationMap; - typedef std::map<int64, sync_pb::EntitySpecifics> SpecificsMap; - typedef std::map<int64, linked_ptr<ExtraPasswordChangeRecordData> > - ExtraDataMap; - - // Stores the items that have been pushed into the buffer, and the type of - // operation that was associated with them. - OperationMap operations_; - - // Stores entity-specific ChangeRecord data per-ID. - SpecificsMap specifics_; - - // Stores type-specific extra data per-ID. - ExtraDataMap extra_data_; - - DISALLOW_COPY_AND_ASSIGN(ChangeReorderBuffer); -}; - -} // namespace sync_api - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_CHANGE_REORDER_BUFFER_H_ diff --git a/chrome/browser/sync/internal_api/configure_reason.h b/chrome/browser/sync/internal_api/configure_reason.h deleted file mode 100644 index cf56e3b7..0000000 --- a/chrome/browser/sync/internal_api/configure_reason.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2011 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_SYNC_INTERNAL_API_CONFIGURE_REASON_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_CONFIGURE_REASON_H_ -#pragma once - -namespace sync_api { - -// Note: This should confirm with the enums in sync.proto for -// GetUpdatesCallerInfo. They will have 1:1 mapping but this will only map -// to a subset of the GetUpdatesCallerInfo enum values. -enum ConfigureReason { - // We should never be here during actual configure. This is for setting - // default values. - CONFIGURE_REASON_UNKNOWN, - - // The client is configuring because the user opted to sync a different set - // of datatypes. - CONFIGURE_REASON_RECONFIGURATION, - - // The client is configuring because the client is being asked to migrate. - CONFIGURE_REASON_MIGRATION, - - // Setting up sync performs an initial config to download NIGORI data, and - // also a config to download initial data once the user selects types. - CONFIGURE_REASON_NEW_CLIENT, - - // A new datatype is enabled for syncing due to a client upgrade. - CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE, -}; - -} // namespace sync_api - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_CONFIGURE_REASON_H_ diff --git a/chrome/browser/sync/internal_api/debug_info_event_listener.cc b/chrome/browser/sync/internal_api/debug_info_event_listener.cc deleted file mode 100644 index 0108f8e..0000000 --- a/chrome/browser/sync/internal_api/debug_info_event_listener.cc +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/debug_info_event_listener.h" - -using browser_sync::sessions::SyncSessionSnapshot; -namespace sync_api { - -DebugInfoEventListener::DebugInfoEventListener() - : events_dropped_(false), - cryptographer_has_pending_keys_(false), - cryptographer_ready_(false) { -} - -DebugInfoEventListener::~DebugInfoEventListener() { -} - -void DebugInfoEventListener::OnSyncCycleCompleted( - const SyncSessionSnapshot* snapshot) { - if (!snapshot) - return; - - sync_pb::DebugEventInfo event_info; - sync_pb::SyncCycleCompletedEventInfo* sync_completed_event_info = - event_info.mutable_sync_cycle_completed_event_info(); - - sync_completed_event_info->set_num_encryption_conflicts( - snapshot->num_encryption_conflicts); - sync_completed_event_info->set_num_hierarchy_conflicts( - snapshot->num_hierarchy_conflicts); - sync_completed_event_info->set_num_simple_conflicts( - snapshot->num_simple_conflicts); - sync_completed_event_info->set_num_server_conflicts( - snapshot->num_server_conflicts); - - sync_completed_event_info->set_num_updates_downloaded( - snapshot->syncer_status.num_updates_downloaded_total); - sync_completed_event_info->set_num_reflected_updates_downloaded( - snapshot->syncer_status.num_reflected_updates_downloaded_total); - sync_completed_event_info->mutable_caller_info()->set_source( - snapshot->source.updates_source); - sync_completed_event_info->mutable_caller_info()->set_notifications_enabled( - snapshot->notifications_enabled); - - AddEventToQueue(event_info); -} - -void DebugInfoEventListener::OnInitializationComplete( - const browser_sync::WeakHandle<browser_sync::JsBackend>& js_backend, - bool success) { - CreateAndAddEvent(sync_pb::DebugEventInfo::INITIALIZATION_COMPLETE); -} - -void DebugInfoEventListener::OnConnectionStatusChange( - sync_api::ConnectionStatus status) { - CreateAndAddEvent(sync_pb::DebugEventInfo::CONNECTION_STATUS_CHANGE); -} - -void DebugInfoEventListener::OnPassphraseRequired( - sync_api::PassphraseRequiredReason reason, - const sync_pb::EncryptedData& pending_keys) { - CreateAndAddEvent(sync_pb::DebugEventInfo::PASSPHRASE_REQUIRED); -} - -void DebugInfoEventListener::OnPassphraseAccepted() { - CreateAndAddEvent(sync_pb::DebugEventInfo::PASSPHRASE_ACCEPTED); -} - -void DebugInfoEventListener::OnBootstrapTokenUpdated( - const std::string& bootstrap_token) { - CreateAndAddEvent(sync_pb::DebugEventInfo::BOOTSTRAP_TOKEN_UPDATED); -} - -void DebugInfoEventListener::OnStopSyncingPermanently() { - CreateAndAddEvent(sync_pb::DebugEventInfo::STOP_SYNCING_PERMANENTLY); -} - -void DebugInfoEventListener::OnUpdatedToken(const std::string& token) { - CreateAndAddEvent(sync_pb::DebugEventInfo::UPDATED_TOKEN); -} - -void DebugInfoEventListener::OnClearServerDataFailed() { - // This command is not implemented on the client side. - NOTREACHED(); -} - -void DebugInfoEventListener::OnClearServerDataSucceeded() { - // This command is not implemented on the client side. - NOTREACHED(); -} - -void DebugInfoEventListener::OnEncryptedTypesChanged( - syncable::ModelTypeSet encrypted_types, - bool encrypt_everything) { - CreateAndAddEvent(sync_pb::DebugEventInfo::ENCRYPTED_TYPES_CHANGED); -} - -void DebugInfoEventListener::OnEncryptionComplete() { - CreateAndAddEvent(sync_pb::DebugEventInfo::ENCRYPTION_COMPLETE); -} - -void DebugInfoEventListener::OnActionableError( - const browser_sync::SyncProtocolError& sync_error) { - CreateAndAddEvent(sync_pb::DebugEventInfo::ACTIONABLE_ERROR); -} - -void DebugInfoEventListener::SetCrytographerHasPendingKeys(bool pending_keys) { - cryptographer_has_pending_keys_ = pending_keys; -} - -void DebugInfoEventListener::SetCryptographerReady(bool ready) { - cryptographer_ready_ = ready; -} - -void DebugInfoEventListener::OnNudgeFromDatatype( - syncable::ModelType datatype) { - sync_pb::DebugEventInfo event_info; - event_info.set_nudging_datatype( - syncable::GetSpecificsFieldNumberFromModelType(datatype)); - AddEventToQueue(event_info); -} - -void DebugInfoEventListener::OnIncomingNotification( - const syncable::ModelTypePayloadMap& type_payloads) { - sync_pb::DebugEventInfo event_info; - syncable::ModelTypeSet types = ModelTypePayloadMapToEnumSet(type_payloads); - - for (syncable::ModelTypeSet::Iterator it = types.First(); - it.Good(); it.Inc()) { - event_info.add_datatypes_notified_from_server( - syncable::GetSpecificsFieldNumberFromModelType(it.Get())); - } - - AddEventToQueue(event_info); -} - -void DebugInfoEventListener::GetAndClearDebugInfo( - sync_pb::DebugInfo* debug_info) { - DCHECK(events_.size() <= sync_api::kMaxEntries); - while (!events_.empty()) { - sync_pb::DebugEventInfo* event_info = debug_info->add_events(); - const sync_pb::DebugEventInfo& debug_event_info = events_.front(); - event_info->CopyFrom(debug_event_info); - events_.pop(); - } - - debug_info->set_events_dropped(events_dropped_); - debug_info->set_cryptographer_ready(cryptographer_ready_); - debug_info->set_cryptographer_has_pending_keys( - cryptographer_has_pending_keys_); - - events_dropped_ = false; -} - -void DebugInfoEventListener::CreateAndAddEvent( - sync_pb::DebugEventInfo::EventType type) { - sync_pb::DebugEventInfo event_info; - event_info.set_type(type); - AddEventToQueue(event_info); -} - -void DebugInfoEventListener::AddEventToQueue( - const sync_pb::DebugEventInfo& event_info) { - if (events_.size() >= sync_api::kMaxEntries) { - DVLOG(1) << "DebugInfoEventListener::AddEventToQueue Dropping an old event " - << "because of full queue"; - - events_.pop(); - events_dropped_ = true; - } - events_.push(event_info); -} -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/debug_info_event_listener.h b/chrome/browser/sync/internal_api/debug_info_event_listener.h deleted file mode 100644 index 5bdc9e1..0000000 --- a/chrome/browser/sync/internal_api/debug_info_event_listener.h +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_DEBUG_INFO_EVENT_LISTENER_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_DEBUG_INFO_EVENT_LISTENER_H_ - -#include <queue> -#include <string> - -#include "base/compiler_specific.h" -#include "chrome/browser/sync/internal_api/sync_manager.h" -#include "sync/js/js_backend.h" -#include "sync/protocol/sync.pb.h" -#include "sync/sessions/debug_info_getter.h" -#include "sync/sessions/session_state.h" -#include "sync/util/weak_handle.h" - -namespace sync_api { - -const unsigned int kMaxEntries = 6; - -// Listens to events and records them in a queue. And passes the events to -// syncer when requested. -class DebugInfoEventListener : public sync_api::SyncManager::Observer, - public browser_sync::sessions::DebugInfoGetter { - public: - DebugInfoEventListener(); - virtual ~DebugInfoEventListener(); - - // SyncManager::Observer implementation. - virtual void OnSyncCycleCompleted( - const browser_sync::sessions::SyncSessionSnapshot* snapshot) OVERRIDE; - virtual void OnInitializationComplete( - const browser_sync::WeakHandle<browser_sync::JsBackend>& js_backend, - bool success) OVERRIDE; - virtual void OnConnectionStatusChange( - sync_api::ConnectionStatus connection_status) OVERRIDE; - virtual void OnPassphraseRequired( - sync_api::PassphraseRequiredReason reason, - const sync_pb::EncryptedData& pending_keys) OVERRIDE; - virtual void OnPassphraseAccepted() OVERRIDE; - virtual void OnBootstrapTokenUpdated( - const std::string& bootstrap_token) OVERRIDE; - virtual void OnStopSyncingPermanently() OVERRIDE; - virtual void OnUpdatedToken(const std::string& token) OVERRIDE; - virtual void OnClearServerDataFailed() OVERRIDE; - virtual void OnClearServerDataSucceeded() OVERRIDE; - virtual void OnEncryptedTypesChanged( - syncable::ModelTypeSet encrypted_types, - bool encrypt_everything) OVERRIDE; - virtual void OnEncryptionComplete() OVERRIDE; - virtual void OnActionableError( - const browser_sync::SyncProtocolError& sync_error) OVERRIDE; - - // Sync manager events. - void OnNudgeFromDatatype(syncable::ModelType datatype); - void OnIncomingNotification( - const syncable::ModelTypePayloadMap& type_payloads); - - // DebugInfoGetter Implementation. - virtual void GetAndClearDebugInfo(sync_pb::DebugInfo* debug_info) OVERRIDE; - - // Functions to set cryptographer state. - void SetCrytographerHasPendingKeys(bool pending_keys); - void SetCryptographerReady(bool ready); - - private: - FRIEND_TEST_ALL_PREFIXES(DebugInfoEventListenerTest, VerifyEventsAdded); - FRIEND_TEST_ALL_PREFIXES(DebugInfoEventListenerTest, VerifyQueueSize); - FRIEND_TEST_ALL_PREFIXES(DebugInfoEventListenerTest, VerifyGetAndClearEvents); - - void AddEventToQueue(const sync_pb::DebugEventInfo& event_info); - void CreateAndAddEvent(sync_pb::DebugEventInfo::EventType type); - std::queue<sync_pb::DebugEventInfo> events_; - - // True indicates we had to drop one or more events to keep our limit of - // |kMaxEntries|. - bool events_dropped_; - - // Cryptographer has keys that are not yet decrypted. - bool cryptographer_has_pending_keys_; - - // Cryptographer is initialized and does not have pending keys. - bool cryptographer_ready_; - - DISALLOW_COPY_AND_ASSIGN(DebugInfoEventListener); -}; - -} // namespace sync_api -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_DEBUG_INFO_EVENT_LISTENER_H_ diff --git a/chrome/browser/sync/internal_api/debug_info_event_listener_unittest.cc b/chrome/browser/sync/internal_api/debug_info_event_listener_unittest.cc deleted file mode 100644 index 79b99ba..0000000 --- a/chrome/browser/sync/internal_api/debug_info_event_listener_unittest.cc +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2011 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/sync/internal_api/debug_info_event_listener.h" -#include "testing/gtest/include/gtest/gtest.h" - -typedef testing::Test DebugInfoEventListenerTest; - -namespace sync_api { -TEST_F(DebugInfoEventListenerTest, VerifyEventsAdded) { - sync_api::DebugInfoEventListener debug_info_event_listener; - debug_info_event_listener.CreateAndAddEvent( - sync_pb::DebugEventInfo::ENCRYPTION_COMPLETE); - ASSERT_EQ(debug_info_event_listener.events_.size(), 1U); - const sync_pb::DebugEventInfo& debug_info = - debug_info_event_listener.events_.back(); - ASSERT_TRUE(debug_info.has_type()); - ASSERT_EQ(debug_info.type(), sync_pb::DebugEventInfo::ENCRYPTION_COMPLETE); -} - -TEST_F(DebugInfoEventListenerTest, VerifyQueueSize) { - sync_api::DebugInfoEventListener debug_info_event_listener; - for (int i = 0; i < 10; ++i) { - debug_info_event_listener.CreateAndAddEvent( - sync_pb::DebugEventInfo::ENCRYPTION_COMPLETE); - } - ASSERT_EQ(debug_info_event_listener.events_.size(), - sync_api::kMaxEntries); -} - -TEST_F(DebugInfoEventListenerTest, VerifyGetAndClearEvents) { - sync_api::DebugInfoEventListener debug_info_event_listener; - debug_info_event_listener.CreateAndAddEvent( - sync_pb::DebugEventInfo::ENCRYPTION_COMPLETE); - ASSERT_EQ(debug_info_event_listener.events_.size(), 1U); - sync_pb::DebugInfo debug_info; - debug_info_event_listener.GetAndClearDebugInfo(&debug_info); - ASSERT_EQ(debug_info_event_listener.events_.size(), 0U); - ASSERT_EQ(debug_info.events_size(), 1); - ASSERT_TRUE(debug_info.events(0).has_type()); - ASSERT_EQ(debug_info.events(0).type(), - sync_pb::DebugEventInfo::ENCRYPTION_COMPLETE); -} - -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/http_post_provider_factory.h b/chrome/browser/sync/internal_api/http_post_provider_factory.h deleted file mode 100644 index 214d064..0000000 --- a/chrome/browser/sync/internal_api/http_post_provider_factory.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2011 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_SYNC_INTERNAL_API_HTTP_POST_PROVIDER_FACTORY_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_HTTP_POST_PROVIDER_FACTORY_H_ -#pragma once - -namespace sync_api { - -class HttpPostProviderInterface; - -// A factory to create HttpPostProviders to hide details about the -// implementations and dependencies. -// A factory instance itself should be owned by whomever uses it to create -// HttpPostProviders. -class HttpPostProviderFactory { - public: - virtual ~HttpPostProviderFactory() {} - - // Obtain a new HttpPostProviderInterface instance, owned by caller. - virtual HttpPostProviderInterface* Create() = 0; - - // When the interface is no longer needed (ready to be cleaned up), clients - // must call Destroy(). - // This allows actual HttpPostProvider subclass implementations to be - // reference counted, which is useful if a particular implementation uses - // multiple threads to serve network requests. - virtual void Destroy(HttpPostProviderInterface* http) = 0; -}; - -} // namespace sync_api - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_HTTP_POST_PROVIDER_FACTORY_H_ diff --git a/chrome/browser/sync/internal_api/http_post_provider_interface.h b/chrome/browser/sync/internal_api/http_post_provider_interface.h deleted file mode 100644 index ffc087e..0000000 --- a/chrome/browser/sync/internal_api/http_post_provider_interface.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2011 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_SYNC_INTERNAL_API_HTTP_POST_PROVIDER_INTERFACE_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_HTTP_POST_PROVIDER_INTERFACE_H_ -#pragma once - -#include <string> - -namespace sync_api { - -// An interface the embedding application (e.g. Chromium) implements to provide -// required HTTP POST functionality to the syncer backend. This interface is -// designed for one-time use. You create one, use it, and create another if you -// want to make a subsequent POST. -class HttpPostProviderInterface { - public: - virtual ~HttpPostProviderInterface() {} - - // Use specified user agent string when POSTing. If not called a default UA - // may be used. - virtual void SetUserAgent(const char* user_agent) = 0; - - // Add additional headers to the request. - virtual void SetExtraRequestHeaders(const char* headers) = 0; - - // Set the URL to POST to. - virtual void SetURL(const char* url, int port) = 0; - - // Set the type, length and content of the POST payload. - // |content_type| is a null-terminated MIME type specifier. - // |content| is a data buffer; Do not interpret as a null-terminated string. - // |content_length| is the total number of chars in |content|. It is used to - // assign/copy |content| data. - virtual void SetPostPayload(const char* content_type, - int content_length, - const char* content) = 0; - - // Returns true if the URL request succeeded. If the request failed, - // error() may be non-zero and hence contain more information. - virtual bool MakeSynchronousPost(int* error_code, int* response_code) = 0; - - // Get the length of the content returned in the HTTP response. - // This does not count the trailing null-terminating character returned - // by GetResponseContent, so it is analogous to calling string.length. - virtual int GetResponseContentLength() const = 0; - - // Get the content returned in the HTTP response. - // This is a null terminated string of characters. - // Value should be copied. - virtual const char* GetResponseContent() const = 0; - - // Get the value of a header returned in the HTTP response. - // If the header is not present, returns the empty string. - virtual const std::string GetResponseHeaderValue( - const std::string& name) const = 0; - - // Abandon any pending POST and unblock caller in MakeSynchronousPost. - // This must be safe to call from any thread. - virtual void Abort() = 0; -}; - -} // namespace sync_api - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_HTTP_POST_PROVIDER_INTERFACE_H_ diff --git a/chrome/browser/sync/internal_api/js_mutation_event_observer.cc b/chrome/browser/sync/internal_api/js_mutation_event_observer.cc deleted file mode 100644 index 2a630800..0000000 --- a/chrome/browser/sync/internal_api/js_mutation_event_observer.cc +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/js_mutation_event_observer.h" - -#include <string> - -#include "base/location.h" -#include "base/logging.h" -#include "base/string_number_conversions.h" -#include "base/values.h" -#include "sync/js/js_event_details.h" -#include "sync/js/js_event_handler.h" - -namespace browser_sync { - -JsMutationEventObserver::JsMutationEventObserver() - : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} - -JsMutationEventObserver::~JsMutationEventObserver() { - DCHECK(non_thread_safe_.CalledOnValidThread()); -} - -base::WeakPtr<JsMutationEventObserver> JsMutationEventObserver::AsWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); -} - -void JsMutationEventObserver::InvalidateWeakPtrs() { - weak_ptr_factory_.InvalidateWeakPtrs(); -} - -void JsMutationEventObserver::SetJsEventHandler( - const WeakHandle<JsEventHandler>& event_handler) { - event_handler_ = event_handler; -} - -namespace { - -// Max number of changes we attempt to convert to values (to avoid -// running out of memory). -const size_t kChangeLimit = 100; - -} // namespace - -void JsMutationEventObserver::OnChangesApplied( - syncable::ModelType model_type, - int64 write_transaction_id, - const sync_api::ImmutableChangeRecordList& changes) { - if (!event_handler_.IsInitialized()) { - return; - } - DictionaryValue details; - details.SetString("modelType", syncable::ModelTypeToString(model_type)); - details.SetString("writeTransactionId", - base::Int64ToString(write_transaction_id)); - base::Value* changes_value = NULL; - const size_t changes_size = changes.Get().size(); - if (changes_size <= kChangeLimit) { - ListValue* changes_list = new ListValue(); - for (sync_api::ChangeRecordList::const_iterator it = - changes.Get().begin(); it != changes.Get().end(); ++it) { - changes_list->Append(it->ToValue()); - } - changes_value = changes_list; - } else { - changes_value = - Value::CreateStringValue( - base::Uint64ToString(static_cast<uint64>(changes_size)) + - " changes"); - } - details.Set("changes", changes_value); - HandleJsEvent(FROM_HERE, "onChangesApplied", JsEventDetails(&details)); -} - -void JsMutationEventObserver::OnChangesComplete( - syncable::ModelType model_type) { - if (!event_handler_.IsInitialized()) { - return; - } - DictionaryValue details; - details.SetString("modelType", syncable::ModelTypeToString(model_type)); - HandleJsEvent(FROM_HERE, "onChangesComplete", JsEventDetails(&details)); -} - -void JsMutationEventObserver::OnTransactionWrite( - const syncable::ImmutableWriteTransactionInfo& write_transaction_info, - syncable::ModelTypeSet models_with_changes) { - DCHECK(non_thread_safe_.CalledOnValidThread()); - if (!event_handler_.IsInitialized()) { - return; - } - DictionaryValue details; - details.Set("writeTransactionInfo", - write_transaction_info.Get().ToValue(kChangeLimit)); - details.Set("modelsWithChanges", - syncable::ModelTypeSetToValue(models_with_changes)); - HandleJsEvent(FROM_HERE, "onTransactionWrite", JsEventDetails(&details)); -} - -void JsMutationEventObserver::HandleJsEvent( - const tracked_objects::Location& from_here, - const std::string& name, const JsEventDetails& details) { - if (!event_handler_.IsInitialized()) { - NOTREACHED(); - return; - } - event_handler_.Call(from_here, - &JsEventHandler::HandleJsEvent, name, details); -} - -} // namespace browser_sync diff --git a/chrome/browser/sync/internal_api/js_mutation_event_observer.h b/chrome/browser/sync/internal_api/js_mutation_event_observer.h deleted file mode 100644 index 850fe75..0000000 --- a/chrome/browser/sync/internal_api/js_mutation_event_observer.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_JS_MUTATION_EVENT_OBSERVER_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_JS_MUTATION_EVENT_OBSERVER_H_ -#pragma once - -#include <string> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/non_thread_safe.h" -#include "chrome/browser/sync/internal_api/sync_manager.h" -#include "sync/syncable/transaction_observer.h" -#include "sync/util/weak_handle.h" - -namespace tracked_objects { -class Location; -} // namespace tracked_objects - -namespace browser_sync { - -class JsEventDetails; -class JsEventHandler; - -// Observes all change- and transaction-related events and routes a -// summarized version to a JsEventHandler. -class JsMutationEventObserver - : public sync_api::SyncManager::ChangeObserver, - public syncable::TransactionObserver { - public: - JsMutationEventObserver(); - - virtual ~JsMutationEventObserver(); - - base::WeakPtr<JsMutationEventObserver> AsWeakPtr(); - - void InvalidateWeakPtrs(); - - void SetJsEventHandler(const WeakHandle<JsEventHandler>& event_handler); - - // sync_api::SyncManager::ChangeObserver implementation. - virtual void OnChangesApplied( - syncable::ModelType model_type, - int64 write_transaction_id, - const sync_api::ImmutableChangeRecordList& changes) OVERRIDE; - virtual void OnChangesComplete(syncable::ModelType model_type) OVERRIDE; - - // syncable::TransactionObserver implementation. - virtual void OnTransactionWrite( - const syncable::ImmutableWriteTransactionInfo& write_transaction_info, - syncable::ModelTypeSet models_with_changes) OVERRIDE; - - private: - base::NonThreadSafe non_thread_safe_; - base::WeakPtrFactory<JsMutationEventObserver> weak_ptr_factory_; - WeakHandle<JsEventHandler> event_handler_; - - void HandleJsEvent( - const tracked_objects::Location& from_here, - const std::string& name, const JsEventDetails& details); - - DISALLOW_COPY_AND_ASSIGN(JsMutationEventObserver); -}; - -} // namespace browser_sync - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_JS_MUTATION_EVENT_OBSERVER_H_ diff --git a/chrome/browser/sync/internal_api/js_mutation_event_observer_unittest.cc b/chrome/browser/sync/internal_api/js_mutation_event_observer_unittest.cc deleted file mode 100644 index 89ef5cb..0000000 --- a/chrome/browser/sync/internal_api/js_mutation_event_observer_unittest.cc +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/js_mutation_event_observer.h" - -#include "base/basictypes.h" -#include "base/message_loop.h" -#include "base/values.h" -#include "sync/js/js_event_details.h" -#include "sync/js/js_test_util.h" -#include "sync/syncable/model_type.h" -#include "sync/util/weak_handle.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace browser_sync { -namespace { - -using ::testing::InSequence; -using ::testing::StrictMock; - -class JsMutationEventObserverTest : public testing::Test { - protected: - JsMutationEventObserverTest() { - js_mutation_event_observer_.SetJsEventHandler( - mock_js_event_handler_.AsWeakHandle()); - } - - private: - // This must be destroyed after the member variables below in order - // for WeakHandles to be destroyed properly. - MessageLoop message_loop_; - - protected: - StrictMock<MockJsEventHandler> mock_js_event_handler_; - JsMutationEventObserver js_mutation_event_observer_; - - void PumpLoop() { - message_loop_.RunAllPending(); - } -}; - -TEST_F(JsMutationEventObserverTest, OnChangesApplied) { - InSequence dummy; - - // We don't test with passwords as that requires additional setup. - - // Build a list of example ChangeRecords. - sync_api::ChangeRecord changes[syncable::MODEL_TYPE_COUNT]; - for (int i = syncable::AUTOFILL_PROFILE; - i < syncable::MODEL_TYPE_COUNT; ++i) { - changes[i].id = i; - switch (i % 3) { - case 0: - changes[i].action = - sync_api::ChangeRecord::ACTION_ADD; - break; - case 1: - changes[i].action = - sync_api::ChangeRecord::ACTION_UPDATE; - break; - default: - changes[i].action = - sync_api::ChangeRecord::ACTION_DELETE; - break; - } - } - - // For each i, we call OnChangesApplied() with the first arg equal - // to i cast to ModelType and the second argument with the changes - // starting from changes[i]. - - // Set expectations for each data type. - for (int i = syncable::AUTOFILL_PROFILE; - i < syncable::MODEL_TYPE_COUNT; ++i) { - const std::string& model_type_str = - syncable::ModelTypeToString(syncable::ModelTypeFromInt(i)); - DictionaryValue expected_details; - expected_details.SetString("modelType", model_type_str); - expected_details.SetString("writeTransactionId", "0"); - ListValue* expected_changes = new ListValue(); - expected_details.Set("changes", expected_changes); - for (int j = i; j < syncable::MODEL_TYPE_COUNT; ++j) { - expected_changes->Append(changes[j].ToValue()); - } - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onChangesApplied", - HasDetailsAsDictionary(expected_details))); - } - - // Fire OnChangesApplied() for each data type. - for (int i = syncable::AUTOFILL_PROFILE; - i < syncable::MODEL_TYPE_COUNT; ++i) { - sync_api::ChangeRecordList - local_changes(changes + i, changes + arraysize(changes)); - js_mutation_event_observer_.OnChangesApplied( - syncable::ModelTypeFromInt(i), - 0, sync_api::ImmutableChangeRecordList(&local_changes)); - } - - PumpLoop(); -} - -TEST_F(JsMutationEventObserverTest, OnChangesComplete) { - InSequence dummy; - - for (int i = syncable::FIRST_REAL_MODEL_TYPE; - i < syncable::MODEL_TYPE_COUNT; ++i) { - DictionaryValue expected_details; - expected_details.SetString( - "modelType", - syncable::ModelTypeToString(syncable::ModelTypeFromInt(i))); - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onChangesComplete", - HasDetailsAsDictionary(expected_details))); - } - - for (int i = syncable::FIRST_REAL_MODEL_TYPE; - i < syncable::MODEL_TYPE_COUNT; ++i) { - js_mutation_event_observer_.OnChangesComplete( - syncable::ModelTypeFromInt(i)); - } - PumpLoop(); -} - -} // namespace -} // namespace browser_sync diff --git a/chrome/browser/sync/internal_api/js_sync_manager_observer.cc b/chrome/browser/sync/internal_api/js_sync_manager_observer.cc deleted file mode 100644 index 6aa236c..0000000 --- a/chrome/browser/sync/internal_api/js_sync_manager_observer.cc +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/js_sync_manager_observer.h" - -#include <cstddef> - -#include "base/location.h" -#include "base/logging.h" -#include "base/string_number_conversions.h" -#include "base/values.h" -#include "chrome/browser/sync/internal_api/change_record.h" -#include "sync/js/js_arg_list.h" -#include "sync/js/js_event_details.h" -#include "sync/js/js_event_handler.h" -#include "sync/sessions/session_state.h" -#include "sync/syncable/model_type.h" - -namespace browser_sync { - -using browser_sync::SyncProtocolError; - -JsSyncManagerObserver::JsSyncManagerObserver() {} - -JsSyncManagerObserver::~JsSyncManagerObserver() {} - -void JsSyncManagerObserver::SetJsEventHandler( - const WeakHandle<JsEventHandler>& event_handler) { - event_handler_ = event_handler; -} - -void JsSyncManagerObserver::OnSyncCycleCompleted( - const sessions::SyncSessionSnapshot* snapshot) { - if (!event_handler_.IsInitialized()) { - return; - } - DictionaryValue details; - details.Set("snapshot", snapshot->ToValue()); - HandleJsEvent(FROM_HERE, "onSyncCycleCompleted", JsEventDetails(&details)); -} - -void JsSyncManagerObserver::OnConnectionStatusChange( - sync_api::ConnectionStatus status) { - if (!event_handler_.IsInitialized()) { - return; - } - DictionaryValue details; - details.SetString("status", sync_api::ConnectionStatusToString(status)); - HandleJsEvent(FROM_HERE, - "onConnectionStatusChange", JsEventDetails(&details)); -} - -void JsSyncManagerObserver::OnUpdatedToken(const std::string& token) { - if (!event_handler_.IsInitialized()) { - return; - } - DictionaryValue details; - details.SetString("token", "<redacted>"); - HandleJsEvent(FROM_HERE, "onUpdatedToken", JsEventDetails(&details)); -} - -void JsSyncManagerObserver::OnPassphraseRequired( - sync_api::PassphraseRequiredReason reason, - const sync_pb::EncryptedData& pending_keys) { - if (!event_handler_.IsInitialized()) { - return; - } - DictionaryValue details; - details.SetString("reason", - sync_api::PassphraseRequiredReasonToString(reason)); - HandleJsEvent(FROM_HERE, "onPassphraseRequired", JsEventDetails(&details)); -} - -void JsSyncManagerObserver::OnPassphraseAccepted() { - if (!event_handler_.IsInitialized()) { - return; - } - DictionaryValue details; - HandleJsEvent(FROM_HERE, "onPassphraseAccepted", JsEventDetails(&details)); -} - -void JsSyncManagerObserver::OnBootstrapTokenUpdated( - const std::string& boostrap_token) { - if (!event_handler_.IsInitialized()) { - return; - } - DictionaryValue details; - details.SetString("bootstrapToken", "<redacted>"); - HandleJsEvent(FROM_HERE, "OnBootstrapTokenUpdated", JsEventDetails(&details)); -} - -void JsSyncManagerObserver::OnEncryptedTypesChanged( - syncable::ModelTypeSet encrypted_types, - bool encrypt_everything) { - if (!event_handler_.IsInitialized()) { - return; - } - DictionaryValue details; - details.Set("encryptedTypes", - syncable::ModelTypeSetToValue(encrypted_types)); - details.SetBoolean("encryptEverything", encrypt_everything); - HandleJsEvent(FROM_HERE, - "onEncryptedTypesChanged", JsEventDetails(&details)); -} - -void JsSyncManagerObserver::OnEncryptionComplete() { - if (!event_handler_.IsInitialized()) { - return; - } - DictionaryValue details; - HandleJsEvent(FROM_HERE, "onEncryptionComplete", JsEventDetails()); -} - -void JsSyncManagerObserver::OnActionableError( - const SyncProtocolError& sync_error) { - if (!event_handler_.IsInitialized()) { - return; - } - DictionaryValue details; - details.Set("syncError", sync_error.ToValue()); - HandleJsEvent(FROM_HERE, "onActionableError", - JsEventDetails(&details)); -} - -void JsSyncManagerObserver::OnInitializationComplete( - const WeakHandle<JsBackend>& js_backend, - bool success) { - if (!event_handler_.IsInitialized()) { - return; - } - // Ignore the |js_backend| argument; it's not really convertible to - // JSON anyway. - HandleJsEvent(FROM_HERE, "onInitializationComplete", JsEventDetails()); -} - -void JsSyncManagerObserver::OnStopSyncingPermanently() { - if (!event_handler_.IsInitialized()) { - return; - } - HandleJsEvent(FROM_HERE, "onStopSyncingPermanently", JsEventDetails()); -} - -void JsSyncManagerObserver::OnClearServerDataSucceeded() { - if (!event_handler_.IsInitialized()) { - return; - } - HandleJsEvent(FROM_HERE, "onClearServerDataSucceeded", JsEventDetails()); -} - -void JsSyncManagerObserver::OnClearServerDataFailed() { - if (!event_handler_.IsInitialized()) { - return; - } - HandleJsEvent(FROM_HERE, "onClearServerDataFailed", JsEventDetails()); -} - -void JsSyncManagerObserver::HandleJsEvent( - const tracked_objects::Location& from_here, - const std::string& name, const JsEventDetails& details) { - if (!event_handler_.IsInitialized()) { - NOTREACHED(); - return; - } - event_handler_.Call(from_here, - &JsEventHandler::HandleJsEvent, name, details); -} - -} // namespace browser_sync diff --git a/chrome/browser/sync/internal_api/js_sync_manager_observer.h b/chrome/browser/sync/internal_api/js_sync_manager_observer.h deleted file mode 100644 index de7ec6b..0000000 --- a/chrome/browser/sync/internal_api/js_sync_manager_observer.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_JS_SYNC_MANAGER_OBSERVER_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_JS_SYNC_MANAGER_OBSERVER_H_ -#pragma once - -#include <string> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "chrome/browser/sync/internal_api/sync_manager.h" -#include "sync/protocol/sync_protocol_error.h" -#include "sync/util/weak_handle.h" - -namespace tracked_objects { -class Location; -} // namespace tracked_objects - -namespace browser_sync { - -class JsEventDetails; -class JsEventHandler; - -// Routes SyncManager events to a JsEventHandler. -class JsSyncManagerObserver : public sync_api::SyncManager::Observer { - public: - JsSyncManagerObserver(); - virtual ~JsSyncManagerObserver(); - - void SetJsEventHandler(const WeakHandle<JsEventHandler>& event_handler); - - // sync_api::SyncManager::Observer implementation. - virtual void OnSyncCycleCompleted( - const sessions::SyncSessionSnapshot* snapshot) OVERRIDE; - virtual void OnConnectionStatusChange( - sync_api::ConnectionStatus status) OVERRIDE; - virtual void OnUpdatedToken(const std::string& token) OVERRIDE; - virtual void OnPassphraseRequired( - sync_api::PassphraseRequiredReason reason, - const sync_pb::EncryptedData& pending_keys) OVERRIDE; - virtual void OnPassphraseAccepted() OVERRIDE; - virtual void OnBootstrapTokenUpdated( - const std::string& bootstrap_token) OVERRIDE; - virtual void OnEncryptedTypesChanged( - syncable::ModelTypeSet encrypted_types, - bool encrypt_everything) OVERRIDE; - virtual void OnEncryptionComplete() OVERRIDE; - virtual void OnInitializationComplete( - const WeakHandle<JsBackend>& js_backend, bool success) OVERRIDE; - virtual void OnStopSyncingPermanently() OVERRIDE; - virtual void OnClearServerDataSucceeded() OVERRIDE; - virtual void OnClearServerDataFailed() OVERRIDE; - virtual void OnActionableError( - const browser_sync::SyncProtocolError& sync_protocol_error) OVERRIDE; - - private: - void HandleJsEvent(const tracked_objects::Location& from_here, - const std::string& name, const JsEventDetails& details); - - WeakHandle<JsEventHandler> event_handler_; - - DISALLOW_COPY_AND_ASSIGN(JsSyncManagerObserver); -}; - -} // namespace browser_sync - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_JS_SYNC_MANAGER_OBSERVER_H_ diff --git a/chrome/browser/sync/internal_api/js_sync_manager_observer_unittest.cc b/chrome/browser/sync/internal_api/js_sync_manager_observer_unittest.cc deleted file mode 100644 index ac65e57..0000000 --- a/chrome/browser/sync/internal_api/js_sync_manager_observer_unittest.cc +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/js_sync_manager_observer.h" - -#include "base/basictypes.h" -#include "base/location.h" -#include "base/message_loop.h" -#include "base/values.h" -#include "sync/js/js_event_details.h" -#include "sync/js/js_test_util.h" -#include "sync/protocol/sync_protocol_error.h" -#include "sync/sessions/session_state.h" -#include "sync/syncable/model_type.h" -#include "sync/util/weak_handle.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace browser_sync { -namespace { - -using ::testing::InSequence; -using ::testing::StrictMock; - -class JsSyncManagerObserverTest : public testing::Test { - protected: - JsSyncManagerObserverTest() { - js_sync_manager_observer_.SetJsEventHandler( - mock_js_event_handler_.AsWeakHandle()); - } - - private: - // This must be destroyed after the member variables below in order - // for WeakHandles to be destroyed properly. - MessageLoop message_loop_; - - protected: - StrictMock<MockJsEventHandler> mock_js_event_handler_; - JsSyncManagerObserver js_sync_manager_observer_; - - void PumpLoop() { - message_loop_.RunAllPending(); - } -}; - -TEST_F(JsSyncManagerObserverTest, NoArgNotifiations) { - InSequence dummy; - - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onInitializationComplete", - HasDetails(JsEventDetails()))); - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onStopSyncingPermanently", - HasDetails(JsEventDetails()))); - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onClearServerDataSucceeded", - HasDetails(JsEventDetails()))); - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onClearServerDataFailed", - HasDetails(JsEventDetails()))); - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onEncryptionComplete", - HasDetails(JsEventDetails()))); - - js_sync_manager_observer_.OnInitializationComplete(WeakHandle<JsBackend>(), - true); - js_sync_manager_observer_.OnStopSyncingPermanently(); - js_sync_manager_observer_.OnClearServerDataSucceeded(); - js_sync_manager_observer_.OnClearServerDataFailed(); - js_sync_manager_observer_.OnEncryptionComplete(); - PumpLoop(); -} - -TEST_F(JsSyncManagerObserverTest, OnSyncCycleCompleted) { - std::string download_progress_markers[syncable::MODEL_TYPE_COUNT]; - sessions::SyncSessionSnapshot snapshot(sessions::SyncerStatus(), - sessions::ErrorCounters(), - 100, - false, - syncable::ModelTypeSet(), - download_progress_markers, - false, - true, - 100, - 8, - 5, - 2, - 7, - false, - sessions::SyncSourceInfo(), - false, - 0, - base::Time::Now(), - false); - DictionaryValue expected_details; - expected_details.Set("snapshot", snapshot.ToValue()); - - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onSyncCycleCompleted", - HasDetailsAsDictionary(expected_details))); - - js_sync_manager_observer_.OnSyncCycleCompleted(&snapshot); - PumpLoop(); -} - -TEST_F(JsSyncManagerObserverTest, OnActionableError) { - browser_sync::SyncProtocolError sync_error; - sync_error.action = browser_sync::CLEAR_USER_DATA_AND_RESYNC; - sync_error.error_type = browser_sync::TRANSIENT_ERROR; - DictionaryValue expected_details; - expected_details.Set("syncError", sync_error.ToValue()); - - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onActionableError", - HasDetailsAsDictionary(expected_details))); - - js_sync_manager_observer_.OnActionableError(sync_error); - PumpLoop(); -} - - -TEST_F(JsSyncManagerObserverTest, OnConnectionStatusChange) { - const sync_api::ConnectionStatus kStatus = - sync_api::CONNECTION_AUTH_ERROR; - DictionaryValue expected_details; - expected_details.SetString("status", - sync_api::ConnectionStatusToString(kStatus)); - - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onConnectionStatusChange", - HasDetailsAsDictionary(expected_details))); - - js_sync_manager_observer_.OnConnectionStatusChange(kStatus); - PumpLoop(); -} - -TEST_F(JsSyncManagerObserverTest, OnPassphraseRequired) { - InSequence dummy; - - DictionaryValue reason_passphrase_not_required_details; - DictionaryValue reason_encryption_details; - DictionaryValue reason_decryption_details; - - reason_passphrase_not_required_details.SetString( - "reason", - sync_api::PassphraseRequiredReasonToString( - sync_api::REASON_PASSPHRASE_NOT_REQUIRED)); - reason_encryption_details.SetString( - "reason", - sync_api::PassphraseRequiredReasonToString(sync_api::REASON_ENCRYPTION)); - reason_decryption_details.SetString( - "reason", - sync_api::PassphraseRequiredReasonToString(sync_api::REASON_DECRYPTION)); - - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onPassphraseRequired", - HasDetailsAsDictionary( - reason_passphrase_not_required_details))); - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onPassphraseRequired", - HasDetailsAsDictionary(reason_encryption_details))); - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onPassphraseRequired", - HasDetailsAsDictionary(reason_decryption_details))); - - js_sync_manager_observer_.OnPassphraseRequired( - sync_api::REASON_PASSPHRASE_NOT_REQUIRED, - sync_pb::EncryptedData()); - js_sync_manager_observer_.OnPassphraseRequired(sync_api::REASON_ENCRYPTION, - sync_pb::EncryptedData()); - js_sync_manager_observer_.OnPassphraseRequired(sync_api::REASON_DECRYPTION, - sync_pb::EncryptedData()); - PumpLoop(); -} - -TEST_F(JsSyncManagerObserverTest, SensitiveNotifiations) { - DictionaryValue redacted_token_details; - redacted_token_details.SetString("token", "<redacted>"); - DictionaryValue redacted_bootstrap_token_details; - redacted_bootstrap_token_details.SetString("bootstrapToken", "<redacted>"); - - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onUpdatedToken", - HasDetailsAsDictionary(redacted_token_details))); - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent( - "OnBootstrapTokenUpdated", - HasDetailsAsDictionary(redacted_bootstrap_token_details))); - - js_sync_manager_observer_.OnUpdatedToken("sensitive_token"); - js_sync_manager_observer_.OnBootstrapTokenUpdated("sensitive_token"); - PumpLoop(); -} - -TEST_F(JsSyncManagerObserverTest, OnEncryptedTypesChanged) { - DictionaryValue expected_details; - ListValue* encrypted_type_values = new ListValue(); - const bool encrypt_everything = false; - expected_details.Set("encryptedTypes", encrypted_type_values); - expected_details.SetBoolean("encryptEverything", encrypt_everything); - syncable::ModelTypeSet encrypted_types; - - for (int i = syncable::FIRST_REAL_MODEL_TYPE; - i < syncable::MODEL_TYPE_COUNT; ++i) { - syncable::ModelType type = syncable::ModelTypeFromInt(i); - encrypted_types.Put(type); - encrypted_type_values->Append(Value::CreateStringValue( - syncable::ModelTypeToString(type))); - } - - EXPECT_CALL(mock_js_event_handler_, - HandleJsEvent("onEncryptedTypesChanged", - HasDetailsAsDictionary(expected_details))); - - js_sync_manager_observer_.OnEncryptedTypesChanged( - encrypted_types, encrypt_everything); - PumpLoop(); -} - -} // namespace -} // namespace browser_sync diff --git a/chrome/browser/sync/internal_api/read_node.cc b/chrome/browser/sync/internal_api/read_node.cc deleted file mode 100644 index 417fff8..0000000 --- a/chrome/browser/sync/internal_api/read_node.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/read_node.h" - -#include "base/logging.h" -#include "chrome/browser/sync/internal_api/base_transaction.h" -#include "sync/syncable/syncable.h" - -namespace sync_api { - -////////////////////////////////////////////////////////////////////////// -// ReadNode member definitions -ReadNode::ReadNode(const BaseTransaction* transaction) - : entry_(NULL), transaction_(transaction) { - DCHECK(transaction); -} - -ReadNode::ReadNode() { - entry_ = NULL; - transaction_ = NULL; -} - -ReadNode::~ReadNode() { - delete entry_; -} - -void ReadNode::InitByRootLookup() { - DCHECK(!entry_) << "Init called twice"; - syncable::BaseTransaction* trans = transaction_->GetWrappedTrans(); - entry_ = new syncable::Entry(trans, syncable::GET_BY_ID, trans->root_id()); - if (!entry_->good()) - DCHECK(false) << "Could not lookup root node for reading."; -} - -BaseNode::InitByLookupResult ReadNode::InitByIdLookup(int64 id) { - DCHECK(!entry_) << "Init called twice"; - DCHECK_NE(id, kInvalidId); - syncable::BaseTransaction* trans = transaction_->GetWrappedTrans(); - entry_ = new syncable::Entry(trans, syncable::GET_BY_HANDLE, id); - if (!entry_->good()) - return INIT_FAILED_ENTRY_NOT_GOOD; - if (entry_->Get(syncable::IS_DEL)) - return INIT_FAILED_ENTRY_IS_DEL; - syncable::ModelType model_type = GetModelType(); - LOG_IF(WARNING, model_type == syncable::UNSPECIFIED || - model_type == syncable::TOP_LEVEL_FOLDER) - << "SyncAPI InitByIdLookup referencing unusual object."; - return DecryptIfNecessary() ? INIT_OK : INIT_FAILED_DECRYPT_IF_NECESSARY; -} - -BaseNode::InitByLookupResult ReadNode::InitByClientTagLookup( - syncable::ModelType model_type, - const std::string& tag) { - DCHECK(!entry_) << "Init called twice"; - if (tag.empty()) - return INIT_FAILED_PRECONDITION; - - const std::string hash = GenerateSyncableHash(model_type, tag); - - entry_ = new syncable::Entry(transaction_->GetWrappedTrans(), - syncable::GET_BY_CLIENT_TAG, hash); - if (!entry_->good()) - return INIT_FAILED_ENTRY_NOT_GOOD; - if (entry_->Get(syncable::IS_DEL)) - return INIT_FAILED_ENTRY_IS_DEL; - return DecryptIfNecessary() ? INIT_OK : INIT_FAILED_DECRYPT_IF_NECESSARY; -} - -const syncable::Entry* ReadNode::GetEntry() const { - return entry_; -} - -const BaseTransaction* ReadNode::GetTransaction() const { - return transaction_; -} - -BaseNode::InitByLookupResult ReadNode::InitByTagLookup( - const std::string& tag) { - DCHECK(!entry_) << "Init called twice"; - if (tag.empty()) - return INIT_FAILED_PRECONDITION; - syncable::BaseTransaction* trans = transaction_->GetWrappedTrans(); - entry_ = new syncable::Entry(trans, syncable::GET_BY_SERVER_TAG, tag); - if (!entry_->good()) - return INIT_FAILED_ENTRY_NOT_GOOD; - if (entry_->Get(syncable::IS_DEL)) - return INIT_FAILED_ENTRY_IS_DEL; - syncable::ModelType model_type = GetModelType(); - LOG_IF(WARNING, model_type == syncable::UNSPECIFIED || - model_type == syncable::TOP_LEVEL_FOLDER) - << "SyncAPI InitByTagLookup referencing unusually typed object."; - return DecryptIfNecessary() ? INIT_OK : INIT_FAILED_DECRYPT_IF_NECESSARY; -} - -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/read_node.h b/chrome/browser/sync/internal_api/read_node.h deleted file mode 100644 index 74bcd32..0000000 --- a/chrome/browser/sync/internal_api/read_node.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_READ_NODE_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_READ_NODE_H_ -#pragma once - -#include <string> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "chrome/browser/sync/internal_api/base_node.h" -#include "sync/syncable/model_type.h" - -namespace sync_api { - -// ReadNode wraps a syncable::Entry to provide the functionality of a -// read-only BaseNode. -class ReadNode : public BaseNode { - public: - // Create an unpopulated ReadNode on the given transaction. Call some flavor - // of Init to populate the ReadNode with a database entry. - explicit ReadNode(const BaseTransaction* transaction); - virtual ~ReadNode(); - - // A client must use one (and only one) of the following Init variants to - // populate the node. - - // BaseNode implementation. - virtual InitByLookupResult InitByIdLookup(int64 id) OVERRIDE; - virtual InitByLookupResult InitByClientTagLookup( - syncable::ModelType model_type, - const std::string& tag) OVERRIDE; - - // There is always a root node, so this can't fail. The root node is - // never mutable, so root lookup is only possible on a ReadNode. - void InitByRootLookup(); - - // Each server-created permanent node is tagged with a unique string. - // Look up the node with the particular tag. If it does not exist, - // return false. - InitByLookupResult InitByTagLookup(const std::string& tag); - - // Implementation of BaseNode's abstract virtual accessors. - virtual const syncable::Entry* GetEntry() const OVERRIDE; - virtual const BaseTransaction* GetTransaction() const OVERRIDE; - - protected: - ReadNode(); - - private: - void* operator new(size_t size); // Node is meant for stack use only. - - // The underlying syncable object which this class wraps. - syncable::Entry* entry_; - - // The sync API transaction that is the parent of this node. - const BaseTransaction* transaction_; - - DISALLOW_COPY_AND_ASSIGN(ReadNode); -}; - -} // namespace sync_api - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_READ_NODE_H_ diff --git a/chrome/browser/sync/internal_api/read_transaction.cc b/chrome/browser/sync/internal_api/read_transaction.cc deleted file mode 100644 index a3991ba..0000000 --- a/chrome/browser/sync/internal_api/read_transaction.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/read_transaction.h" - -#include "sync/syncable/syncable.h" - -namespace sync_api { - -////////////////////////////////////////////////////////////////////////// -// ReadTransaction member definitions -ReadTransaction::ReadTransaction(const tracked_objects::Location& from_here, - UserShare* share) - : BaseTransaction(share), - transaction_(NULL), - close_transaction_(true) { - transaction_ = new syncable::ReadTransaction(from_here, - share->directory.get()); -} - -ReadTransaction::ReadTransaction(UserShare* share, - syncable::BaseTransaction* trans) - : BaseTransaction(share), - transaction_(trans), - close_transaction_(false) {} - -ReadTransaction::~ReadTransaction() { - if (close_transaction_) { - delete transaction_; - } -} - -syncable::BaseTransaction* ReadTransaction::GetWrappedTrans() const { - return transaction_; -} - -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/read_transaction.h b/chrome/browser/sync/internal_api/read_transaction.h deleted file mode 100644 index 62d279be..0000000 --- a/chrome/browser/sync/internal_api/read_transaction.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2011 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_SYNC_INTERNAL_API_READ_TRANSACTION_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_READ_TRANSACTION_H_ - -#include "base/compiler_specific.h" -#include "chrome/browser/sync/internal_api/base_transaction.h" - -namespace tracked_objects { -class Location; -} // namespace tracked_objects - -namespace sync_api { - -struct UserShare; - -// Sync API's ReadTransaction is a read-only BaseTransaction. It wraps -// a syncable::ReadTransaction. -class ReadTransaction : public BaseTransaction { - public: - // Start a new read-only transaction on the specified repository. - ReadTransaction(const tracked_objects::Location& from_here, - UserShare* share); - - // Resume the middle of a transaction. Will not close transaction. - ReadTransaction(UserShare* share, syncable::BaseTransaction* trans); - - virtual ~ReadTransaction(); - - // BaseTransaction override. - virtual syncable::BaseTransaction* GetWrappedTrans() const OVERRIDE; - private: - void* operator new(size_t size); // Transaction is meant for stack use only. - - // The underlying syncable object which this class wraps. - syncable::BaseTransaction* transaction_; - bool close_transaction_; - - DISALLOW_COPY_AND_ASSIGN(ReadTransaction); -}; - -} // namespace sync_api - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_READ_TRANSACTION_H_ diff --git a/chrome/browser/sync/internal_api/sync_manager.cc b/chrome/browser/sync/internal_api/sync_manager.cc deleted file mode 100644 index 6e6f176..0000000 --- a/chrome/browser/sync/internal_api/sync_manager.cc +++ /dev/null @@ -1,2575 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/sync_manager.h" - -#include <string> - -#include "base/base64.h" -#include "base/bind.h" -#include "base/callback.h" -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/json/json_writer.h" -#include "base/memory/ref_counted.h" -#include "base/metrics/histogram.h" -#include "base/observer_list.h" -#include "base/string_number_conversions.h" -#include "base/values.h" -#include "chrome/browser/sync/internal_api/all_status.h" -#include "chrome/browser/sync/internal_api/base_node.h" -#include "chrome/browser/sync/internal_api/change_reorder_buffer.h" -#include "chrome/browser/sync/internal_api/configure_reason.h" -#include "chrome/browser/sync/internal_api/debug_info_event_listener.h" -#include "chrome/browser/sync/internal_api/js_mutation_event_observer.h" -#include "chrome/browser/sync/internal_api/js_sync_manager_observer.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/syncapi_internal.h" -#include "chrome/browser/sync/internal_api/syncapi_server_connection_manager.h" -#include "chrome/browser/sync/internal_api/user_share.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" -#include "net/base/network_change_notifier.h" -#include "sync/engine/net/server_connection_manager.h" -#include "sync/engine/nigori_util.h" -#include "sync/engine/polling_constants.h" -#include "sync/engine/sync_scheduler.h" -#include "sync/engine/syncer_types.h" -#include "sync/js/js_arg_list.h" -#include "sync/js/js_backend.h" -#include "sync/js/js_event_details.h" -#include "sync/js/js_event_handler.h" -#include "sync/js/js_reply_handler.h" -#include "sync/notifier/sync_notifier.h" -#include "sync/notifier/sync_notifier_observer.h" -#include "sync/protocol/encryption.pb.h" -#include "sync/protocol/proto_value_conversions.h" -#include "sync/protocol/sync.pb.h" -#include "sync/syncable/directory_change_delegate.h" -#include "sync/syncable/model_type.h" -#include "sync/syncable/model_type_payload_map.h" -#include "sync/syncable/syncable.h" -#include "sync/util/cryptographer.h" -#include "sync/util/get_session_name.h" -#include "sync/util/time.h" - -using base::TimeDelta; -using browser_sync::AllStatus; -using browser_sync::Cryptographer; -using browser_sync::Encryptor; -using browser_sync::JsArgList; -using browser_sync::JsBackend; -using browser_sync::JsEventDetails; -using browser_sync::JsEventHandler; -using browser_sync::JsEventHandler; -using browser_sync::JsReplyHandler; -using browser_sync::JsMutationEventObserver; -using browser_sync::JsSyncManagerObserver; -using browser_sync::ModelSafeWorkerRegistrar; -using browser_sync::kNigoriTag; -using browser_sync::KeyParams; -using browser_sync::ModelSafeRoutingInfo; -using browser_sync::ReportUnrecoverableErrorFunction; -using browser_sync::ServerConnectionEvent; -using browser_sync::ServerConnectionEventListener; -using browser_sync::SyncEngineEvent; -using browser_sync::SyncEngineEventListener; -using browser_sync::SyncScheduler; -using browser_sync::Syncer; -using browser_sync::UnrecoverableErrorHandler; -using browser_sync::WeakHandle; -using browser_sync::sessions::SyncSessionContext; -using syncable::ImmutableWriteTransactionInfo; -using syncable::ModelType; -using syncable::ModelTypeSet; -using syncable::SPECIFICS; -using sync_pb::GetUpdatesCallerInfo; - -namespace { - -// Delays for syncer nudges. -static const int kSyncRefreshDelayMsec = 500; -static const int kSyncSchedulerDelayMsec = 250; - -GetUpdatesCallerInfo::GetUpdatesSource GetSourceFromReason( - sync_api::ConfigureReason reason) { - switch (reason) { - case sync_api::CONFIGURE_REASON_RECONFIGURATION: - return GetUpdatesCallerInfo::RECONFIGURATION; - case sync_api::CONFIGURE_REASON_MIGRATION: - return GetUpdatesCallerInfo::MIGRATION; - case sync_api::CONFIGURE_REASON_NEW_CLIENT: - return GetUpdatesCallerInfo::NEW_CLIENT; - case sync_api::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE: - return GetUpdatesCallerInfo::NEWLY_SUPPORTED_DATATYPE; - default: - NOTREACHED(); - } - - return GetUpdatesCallerInfo::UNKNOWN; -} - -// The maximum number of times we will automatically overwrite the nigori node -// because the encryption keys don't match (per chrome instantiation). -static const int kNigoriOverwriteLimit = 10; - -} // namespace - -namespace sync_api { - -const int SyncManager::kDefaultNudgeDelayMilliseconds = 200; -const int SyncManager::kPreferencesNudgeDelayMilliseconds = 2000; - -// Maximum count and size for traffic recorder. -const unsigned int kMaxMessagesToRecord = 10; -const unsigned int kMaxMessageSizeToRecord = 5 * 1024; - -////////////////////////////////////////////////////////////////////////// -// SyncManager's implementation: SyncManager::SyncInternal -class SyncManager::SyncInternal - : public net::NetworkChangeNotifier::IPAddressObserver, - public browser_sync::Cryptographer::Observer, - public sync_notifier::SyncNotifierObserver, - public JsBackend, - public SyncEngineEventListener, - public ServerConnectionEventListener, - public syncable::DirectoryChangeDelegate { - public: - explicit SyncInternal(const std::string& name) - : name_(name), - weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), - enable_sync_tabs_for_other_clients_(false), - registrar_(NULL), - change_delegate_(NULL), - initialized_(false), - testing_mode_(NON_TEST), - observing_ip_address_changes_(false), - traffic_recorder_(kMaxMessagesToRecord, kMaxMessageSizeToRecord), - encryptor_(NULL), - unrecoverable_error_handler_(NULL), - report_unrecoverable_error_function_(NULL), - created_on_loop_(MessageLoop::current()), - nigori_overwrite_count_(0) { - // Pre-fill |notification_info_map_|. - for (int i = syncable::FIRST_REAL_MODEL_TYPE; - i < syncable::MODEL_TYPE_COUNT; ++i) { - notification_info_map_.insert( - std::make_pair(syncable::ModelTypeFromInt(i), NotificationInfo())); - } - - // Bind message handlers. - BindJsMessageHandler( - "getNotificationState", - &SyncManager::SyncInternal::GetNotificationState); - BindJsMessageHandler( - "getNotificationInfo", - &SyncManager::SyncInternal::GetNotificationInfo); - BindJsMessageHandler( - "getRootNodeDetails", - &SyncManager::SyncInternal::GetRootNodeDetails); - BindJsMessageHandler( - "getNodeSummariesById", - &SyncManager::SyncInternal::GetNodeSummariesById); - BindJsMessageHandler( - "getNodeDetailsById", - &SyncManager::SyncInternal::GetNodeDetailsById); - BindJsMessageHandler( - "getAllNodes", - &SyncManager::SyncInternal::GetAllNodes); - BindJsMessageHandler( - "getChildNodeIds", - &SyncManager::SyncInternal::GetChildNodeIds); - BindJsMessageHandler( - "getClientServerTraffic", - &SyncManager::SyncInternal::GetClientServerTraffic); - } - - virtual ~SyncInternal() { - CHECK(!initialized_); - } - - bool Init(const FilePath& database_location, - const WeakHandle<JsEventHandler>& event_handler, - const std::string& sync_server_and_path, - int port, - bool use_ssl, - const scoped_refptr<base::TaskRunner>& blocking_task_runner, - HttpPostProviderFactory* post_factory, - ModelSafeWorkerRegistrar* model_safe_worker_registrar, - browser_sync::ExtensionsActivityMonitor* - extensions_activity_monitor, - ChangeDelegate* change_delegate, - const std::string& user_agent, - const SyncCredentials& credentials, - bool enable_sync_tabs_for_other_clients, - sync_notifier::SyncNotifier* sync_notifier, - const std::string& restored_key_for_bootstrapping, - TestingMode testing_mode, - Encryptor* encryptor, - UnrecoverableErrorHandler* unrecoverable_error_handler, - ReportUnrecoverableErrorFunction - report_unrecoverable_error_function); - - // Sign into sync with given credentials. - // We do not verify the tokens given. After this call, the tokens are set - // and the sync DB is open. True if successful, false if something - // went wrong. - bool SignIn(const SyncCredentials& credentials); - - // Update tokens that we're using in Sync. Email must stay the same. - void UpdateCredentials(const SyncCredentials& credentials); - - // Called when the user disables or enables a sync type. - void UpdateEnabledTypes(); - - // Conditionally sets the flag in the Nigori node which instructs other - // clients to start syncing tabs. - void MaybeSetSyncTabsInNigoriNode(ModelTypeSet enabled_types); - - // Tell the sync engine to start the syncing process. - void StartSyncingNormally(); - - // Whether or not the Nigori node is encrypted using an explicit passphrase. - bool IsUsingExplicitPassphrase(); - - // Update the Cryptographer from the current nigori node and write back any - // necessary changes to the nigori node. We also detect missing encryption - // keys and write them into the nigori node. - // Also updates or adds the device information into the nigori node. - // Note: opens a transaction and can trigger an ON_PASSPHRASE_REQUIRED, so - // should only be called after syncapi is fully initialized. - // Calls the callback argument with true if cryptographer is ready, false - // otherwise. - void UpdateCryptographerAndNigori( - const std::string& chrome_version, - const base::Closure& done_callback); - - // Stores the current set of encryption keys (if the cryptographer is ready) - // and encrypted types into the nigori node. - void UpdateNigoriEncryptionState(Cryptographer* cryptographer, - WriteNode* nigori_node); - - // Updates the nigori node with any new encrypted types and then - // encrypts the nodes for those new data types as well as other - // nodes that should be encrypted but aren't. Triggers - // OnPassphraseRequired if the cryptographer isn't ready. - void RefreshEncryption(); - - // Re-encrypts the encrypted data types using the passed passphrase, and sets - // a flag in the nigori node specifying whether the current passphrase is - // explicit (custom passphrase) or non-explicit (GAIA). If the existing - // encryption passphrase is "explicit", the data cannot be re-encrypted and - // SetEncryptionPassphrase will do nothing. - // If !is_explicit and there are pending keys, we will attempt to decrypt them - // using this passphrase. If this fails, we will save this encryption key to - // be applied later after the pending keys are resolved. - // Calls FinishSetPassphrase at the end, which notifies observers of the - // result of the set passphrase operation, updates the nigori node, and does - // re-encryption. - void SetEncryptionPassphrase(const std::string& passphrase, bool is_explicit); - - // Provides a passphrase for decrypting the user's existing sync data. Calls - // FinishSetPassphrase at the end, which notifies observers of the result of - // the set passphrase operation, updates the nigori node, and does - // re-encryption. - void SetDecryptionPassphrase(const std::string& passphrase); - - // The final step of SetEncryptionPassphrase and SetDecryptionPassphrase that - // notifies observers of the result of the set passphrase operation, updates - // the nigori node, and does re-encryption. - // |success|: true if the operation was successful and false otherwise. If - // success == false, we send an OnPassphraseRequired notification. - // |bootstrap_token|: used to inform observers if the cryptographer's - // bootstrap token was updated. - // |is_explicit|: used to differentiate between a custom passphrase (true) and - // a GAIA passphrase that is implicitly used for encryption - // (false). - // |trans| and |nigori_node|: used to access data in the cryptographer. - void FinishSetPassphrase( - bool success, - const std::string& bootstrap_token, - bool is_explicit, - WriteTransaction* trans, - WriteNode* nigori_node); - - // Call periodically from a database-safe thread to persist recent changes - // to the syncapi model. - void SaveChanges(); - - // DirectoryChangeDelegate implementation. - // This listener is called upon completion of a syncable transaction, and - // builds the list of sync-engine initiated changes that will be forwarded to - // the SyncManager's Observers. - virtual void HandleTransactionCompleteChangeEvent( - ModelTypeSet models_with_changes) OVERRIDE; - virtual ModelTypeSet HandleTransactionEndingChangeEvent( - const ImmutableWriteTransactionInfo& write_transaction_info, - syncable::BaseTransaction* trans) OVERRIDE; - virtual void HandleCalculateChangesChangeEventFromSyncApi( - const ImmutableWriteTransactionInfo& write_transaction_info, - syncable::BaseTransaction* trans) OVERRIDE; - virtual void HandleCalculateChangesChangeEventFromSyncer( - const ImmutableWriteTransactionInfo& write_transaction_info, - syncable::BaseTransaction* trans) OVERRIDE; - - // Open the directory named with username_for_share - bool OpenDirectory(); - - // Cryptographer::Observer implementation. - virtual void OnEncryptedTypesChanged( - syncable::ModelTypeSet encrypted_types, - bool encrypt_everything) OVERRIDE; - - // SyncNotifierObserver implementation. - virtual void OnNotificationStateChange( - bool notifications_enabled) OVERRIDE; - - virtual void OnIncomingNotification( - const syncable::ModelTypePayloadMap& type_payloads, - sync_notifier::IncomingNotificationSource source) OVERRIDE; - - virtual void StoreState(const std::string& cookie) OVERRIDE; - - void AddObserver(SyncManager::Observer* observer); - void RemoveObserver(SyncManager::Observer* observer); - - // Accessors for the private members. - syncable::Directory* directory() { return share_.directory.get(); } - SyncAPIServerConnectionManager* connection_manager() { - return connection_manager_.get(); - } - SyncScheduler* scheduler() const { return scheduler_.get(); } - UserShare* GetUserShare() { - DCHECK(initialized_); - return &share_; - } - - // Return the currently active (validated) username for use with syncable - // types. - const std::string& username_for_share() const { - return share_.name; - } - - Status GetStatus(); - - void RequestNudge(const tracked_objects::Location& nudge_location); - - void RequestNudgeForDataTypes( - const tracked_objects::Location& nudge_location, - ModelTypeSet type); - - TimeDelta GetNudgeDelayTimeDelta(const ModelType& model_type); - - void NotifyCryptographerState(Cryptographer* cryptographer); - - // See SyncManager::Shutdown* for information. - void StopSyncingForShutdown(const base::Closure& callback); - void ShutdownOnSyncThread(); - - // If this is a deletion for a password, sets the legacy - // ExtraPasswordChangeRecordData field of |buffer|. Otherwise sets - // |buffer|'s specifics field to contain the unencrypted data. - void SetExtraChangeRecordData(int64 id, - syncable::ModelType type, - ChangeReorderBuffer* buffer, - Cryptographer* cryptographer, - const syncable::EntryKernel& original, - bool existed_before, - bool exists_now); - - // Called only by our NetworkChangeNotifier. - virtual void OnIPAddressChanged() OVERRIDE; - - bool InitialSyncEndedForAllEnabledTypes() { - syncable::ModelTypeSet types; - ModelSafeRoutingInfo enabled_types; - registrar_->GetModelSafeRoutingInfo(&enabled_types); - for (ModelSafeRoutingInfo::const_iterator i = enabled_types.begin(); - i != enabled_types.end(); ++i) { - types.Put(i->first); - } - - return InitialSyncEndedForTypes(types, &share_); - } - - // SyncEngineEventListener implementation. - virtual void OnSyncEngineEvent(const SyncEngineEvent& event) OVERRIDE; - - // ServerConnectionEventListener implementation. - virtual void OnServerConnectionEvent( - const ServerConnectionEvent& event) OVERRIDE; - - // JsBackend implementation. - virtual void SetJsEventHandler( - const WeakHandle<JsEventHandler>& event_handler) OVERRIDE; - virtual void ProcessJsMessage( - const std::string& name, const JsArgList& args, - const WeakHandle<JsReplyHandler>& reply_handler) OVERRIDE; - - private: - struct NotificationInfo { - int total_count; - std::string payload; - - NotificationInfo() : total_count(0) {} - - ~NotificationInfo() {} - - // Returned pointer owned by the caller. - DictionaryValue* ToValue() const { - DictionaryValue* value = new DictionaryValue(); - value->SetInteger("totalCount", total_count); - value->SetString("payload", payload); - return value; - } - }; - - typedef std::map<syncable::ModelType, NotificationInfo> NotificationInfoMap; - typedef JsArgList - (SyncManager::SyncInternal::*UnboundJsMessageHandler)(const JsArgList&); - typedef base::Callback<JsArgList(const JsArgList&)> JsMessageHandler; - typedef std::map<std::string, JsMessageHandler> JsMessageHandlerMap; - - // Internal callback of UpdateCryptographerAndNigoriCallback. - void UpdateCryptographerAndNigoriCallback( - const std::string& chrome_version, - const base::Closure& done_callback, - const std::string& session_name); - - // Determine if the parents or predecessors differ between the old and new - // versions of an entry stored in |a| and |b|. Note that a node's index may - // change without its NEXT_ID changing if the node at NEXT_ID also moved (but - // the relative order is unchanged). To handle such cases, we rely on the - // caller to treat a position update on any sibling as updating the positions - // of all siblings. - static bool VisiblePositionsDiffer( - const syncable::EntryKernelMutation& mutation) { - const syncable::EntryKernel& a = mutation.original; - const syncable::EntryKernel& b = mutation.mutated; - // If the datatype isn't one where the browser model cares about position, - // don't bother notifying that data model of position-only changes. - if (!ShouldMaintainPosition( - syncable::GetModelTypeFromSpecifics(b.ref(SPECIFICS)))) - return false; - if (a.ref(syncable::NEXT_ID) != b.ref(syncable::NEXT_ID)) - return true; - if (a.ref(syncable::PARENT_ID) != b.ref(syncable::PARENT_ID)) - return true; - return false; - } - - // Determine if any of the fields made visible to clients of the Sync API - // differ between the versions of an entry stored in |a| and |b|. A return - // value of false means that it should be OK to ignore this change. - static bool VisiblePropertiesDiffer( - const syncable::EntryKernelMutation& mutation, - Cryptographer* cryptographer) { - const syncable::EntryKernel& a = mutation.original; - const syncable::EntryKernel& b = mutation.mutated; - const sync_pb::EntitySpecifics& a_specifics = a.ref(SPECIFICS); - const sync_pb::EntitySpecifics& b_specifics = b.ref(SPECIFICS); - DCHECK_EQ(syncable::GetModelTypeFromSpecifics(a_specifics), - syncable::GetModelTypeFromSpecifics(b_specifics)); - syncable::ModelType model_type = - syncable::GetModelTypeFromSpecifics(b_specifics); - // Suppress updates to items that aren't tracked by any browser model. - if (model_type < syncable::FIRST_REAL_MODEL_TYPE || - !a.ref(syncable::UNIQUE_SERVER_TAG).empty()) { - return false; - } - if (a.ref(syncable::IS_DIR) != b.ref(syncable::IS_DIR)) - return true; - if (!AreSpecificsEqual(cryptographer, - a.ref(syncable::SPECIFICS), - b.ref(syncable::SPECIFICS))) { - return true; - } - // We only care if the name has changed if neither specifics is encrypted - // (encrypted nodes blow away the NON_UNIQUE_NAME). - if (!a_specifics.has_encrypted() && !b_specifics.has_encrypted() && - a.ref(syncable::NON_UNIQUE_NAME) != b.ref(syncable::NON_UNIQUE_NAME)) - return true; - if (VisiblePositionsDiffer(mutation)) - return true; - return false; - } - - bool ChangeBuffersAreEmpty() { - for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) { - if (!change_buffers_[i].IsEmpty()) - return false; - } - return true; - } - - void ReEncryptEverything(WriteTransaction* trans); - - // Called for every notification. This updates the notification statistics - // to be displayed in about:sync. - void UpdateNotificationInfo( - const syncable::ModelTypePayloadMap& type_payloads); - - // Checks for server reachabilty and requests a nudge. - void OnIPAddressChangedImpl(); - - // Helper function used only by the constructor. - void BindJsMessageHandler( - const std::string& name, UnboundJsMessageHandler unbound_message_handler); - - // Returned pointer is owned by the caller. - static DictionaryValue* NotificationInfoToValue( - const NotificationInfoMap& notification_info); - - // JS message handlers. - JsArgList GetNotificationState(const JsArgList& args); - JsArgList GetNotificationInfo(const JsArgList& args); - JsArgList GetRootNodeDetails(const JsArgList& args); - JsArgList GetAllNodes(const JsArgList& args); - JsArgList GetNodeSummariesById(const JsArgList& args); - JsArgList GetNodeDetailsById(const JsArgList& args); - JsArgList GetChildNodeIds(const JsArgList& args); - JsArgList GetClientServerTraffic(const JsArgList& args); - - FilePath database_path_; - - const std::string name_; - - base::ThreadChecker thread_checker_; - - base::WeakPtrFactory<SyncInternal> weak_ptr_factory_; - - // Thread-safe handle used by - // HandleCalculateChangesChangeEventFromSyncApi(), which can be - // called from any thread. Valid only between between calls to - // Init() and Shutdown(). - // - // TODO(akalin): Ideally, we wouldn't need to store this; instead, - // we'd have another worker class which implements - // HandleCalculateChangesChangeEventFromSyncApi() and we'd pass it a - // WeakHandle when we construct it. - WeakHandle<SyncInternal> weak_handle_this_; - - // |blocking_task_runner| is a TaskRunner to be used for tasks that - // may block on disk I/O. - scoped_refptr<base::TaskRunner> blocking_task_runner_; - - // We give a handle to share_ to clients of the API for use when constructing - // any transaction type. - UserShare share_; - - // This can be called from any thread, but only between calls to - // OpenDirectory() and ShutdownOnSyncThread(). - browser_sync::WeakHandle<SyncManager::ChangeObserver> change_observer_; - - ObserverList<SyncManager::Observer> observers_; - - // The ServerConnectionManager used to abstract communication between the - // client (the Syncer) and the sync server. - scoped_ptr<SyncAPIServerConnectionManager> connection_manager_; - - // The scheduler that runs the Syncer. Needs to be explicitly - // Start()ed. - scoped_ptr<SyncScheduler> scheduler_; - - bool enable_sync_tabs_for_other_clients_; - - // The SyncNotifier which notifies us when updates need to be downloaded. - scoped_ptr<sync_notifier::SyncNotifier> sync_notifier_; - - // A multi-purpose status watch object that aggregates stats from various - // sync components. - AllStatus allstatus_; - - // Each element of this array is a store of change records produced by - // HandleChangeEvent during the CALCULATE_CHANGES step. The changes are - // segregated by model type, and are stored here to be processed and - // forwarded to the observer slightly later, at the TRANSACTION_ENDING - // step by HandleTransactionEndingChangeEvent. The list is cleared in the - // TRANSACTION_COMPLETE step by HandleTransactionCompleteChangeEvent. - ChangeReorderBuffer change_buffers_[syncable::MODEL_TYPE_COUNT]; - - // The entity that provides us with information about which types to sync. - // The instance is shared between the SyncManager and the Syncer. - ModelSafeWorkerRegistrar* registrar_; - - SyncManager::ChangeDelegate* change_delegate_; - - // Set to true once Init has been called. - bool initialized_; - - // Controls the disabling of certain SyncManager features. - // Can be used to disable communication with the server and the use of an - // on-disk file for maintaining syncer state. - // TODO(117836): Clean up implementation of SyncManager unit tests. - TestingMode testing_mode_; - - bool observing_ip_address_changes_; - - // Map used to store the notification info to be displayed in - // about:sync page. - NotificationInfoMap notification_info_map_; - - // These are for interacting with chrome://sync-internals. - JsMessageHandlerMap js_message_handlers_; - WeakHandle<JsEventHandler> js_event_handler_; - JsSyncManagerObserver js_sync_manager_observer_; - JsMutationEventObserver js_mutation_event_observer_; - - // This is for keeping track of client events to send to the server. - DebugInfoEventListener debug_info_event_listener_; - - browser_sync::TrafficRecorder traffic_recorder_; - - Encryptor* encryptor_; - UnrecoverableErrorHandler* unrecoverable_error_handler_; - ReportUnrecoverableErrorFunction report_unrecoverable_error_function_; - - MessageLoop* const created_on_loop_; - - // The number of times we've automatically (i.e. not via SetPassphrase or - // conflict resolver) updated the nigori's encryption keys in this chrome - // instantiation. - int nigori_overwrite_count_; -}; - -// A class to calculate nudge delays for types. -class NudgeStrategy { - public: - static TimeDelta GetNudgeDelayTimeDelta(const ModelType& model_type, - SyncManager::SyncInternal* core) { - NudgeDelayStrategy delay_type = GetNudgeDelayStrategy(model_type); - return GetNudgeDelayTimeDeltaFromType(delay_type, - model_type, - core); - } - - private: - // Possible types of nudge delay for datatypes. - // Note: These are just hints. If a sync happens then all dirty entries - // would be committed as part of the sync. - enum NudgeDelayStrategy { - // Sync right away. - IMMEDIATE, - - // Sync this change while syncing another change. - ACCOMPANY_ONLY, - - // The datatype does not use one of the predefined wait times but defines - // its own wait time logic for nudge. - CUSTOM, - }; - - static NudgeDelayStrategy GetNudgeDelayStrategy(const ModelType& type) { - switch (type) { - case syncable::AUTOFILL: - return ACCOMPANY_ONLY; - case syncable::PREFERENCES: - case syncable::SESSIONS: - return CUSTOM; - default: - return IMMEDIATE; - } - } - - static TimeDelta GetNudgeDelayTimeDeltaFromType( - const NudgeDelayStrategy& delay_type, const ModelType& model_type, - const SyncManager::SyncInternal* core) { - CHECK(core); - TimeDelta delay = TimeDelta::FromMilliseconds( - SyncManager::kDefaultNudgeDelayMilliseconds); - switch (delay_type) { - case IMMEDIATE: - delay = TimeDelta::FromMilliseconds( - SyncManager::kDefaultNudgeDelayMilliseconds); - break; - case ACCOMPANY_ONLY: - delay = TimeDelta::FromSeconds( - browser_sync::kDefaultShortPollIntervalSeconds); - break; - case CUSTOM: - switch (model_type) { - case syncable::PREFERENCES: - delay = TimeDelta::FromMilliseconds( - SyncManager::kPreferencesNudgeDelayMilliseconds); - break; - case syncable::SESSIONS: - delay = core->scheduler()->sessions_commit_delay(); - break; - default: - NOTREACHED(); - } - break; - default: - NOTREACHED(); - } - return delay; - } -}; - -SyncManager::ChangeDelegate::~ChangeDelegate() {} - -SyncManager::ChangeObserver::~ChangeObserver() {} - -SyncManager::Observer::~Observer() {} - -SyncManager::SyncManager(const std::string& name) - : data_(new SyncInternal(name)) {} - -SyncManager::Status::Status() - : notifications_enabled(false), - notifications_received(0), - unsynced_count(0), - encryption_conflicts(0), - hierarchy_conflicts(0), - simple_conflicts(0), - server_conflicts(0), - committed_count(0), - syncing(false), - initial_sync_ended(false), - updates_available(0), - updates_received(0), - reflected_updates_received(0), - tombstone_updates_received(0), - num_local_overwrites_total(0), - num_server_overwrites_total(0), - nonempty_get_updates(0), - empty_get_updates(0), - sync_cycles_with_commits(0), - sync_cycles_without_commits(0), - useless_sync_cycles(0), - useful_sync_cycles(0), - cryptographer_ready(false), - crypto_has_pending_keys(false) { -} - -SyncManager::Status::~Status() { -} - -bool SyncManager::Init( - const FilePath& database_location, - const WeakHandle<JsEventHandler>& event_handler, - const std::string& sync_server_and_path, - int sync_server_port, - bool use_ssl, - const scoped_refptr<base::TaskRunner>& blocking_task_runner, - HttpPostProviderFactory* post_factory, - ModelSafeWorkerRegistrar* registrar, - browser_sync::ExtensionsActivityMonitor* extensions_activity_monitor, - ChangeDelegate* change_delegate, - const std::string& user_agent, - const SyncCredentials& credentials, - bool enable_sync_tabs_for_other_clients, - sync_notifier::SyncNotifier* sync_notifier, - const std::string& restored_key_for_bootstrapping, - TestingMode testing_mode, - Encryptor* encryptor, - UnrecoverableErrorHandler* unrecoverable_error_handler, - ReportUnrecoverableErrorFunction report_unrecoverable_error_function) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(post_factory); - DVLOG(1) << "SyncManager starting Init..."; - std::string server_string(sync_server_and_path); - return data_->Init(database_location, - event_handler, - server_string, - sync_server_port, - use_ssl, - blocking_task_runner, - post_factory, - registrar, - extensions_activity_monitor, - change_delegate, - user_agent, - credentials, - enable_sync_tabs_for_other_clients, - sync_notifier, - restored_key_for_bootstrapping, - testing_mode, - encryptor, - unrecoverable_error_handler, - report_unrecoverable_error_function); -} - -void SyncManager::UpdateCredentials(const SyncCredentials& credentials) { - DCHECK(thread_checker_.CalledOnValidThread()); - data_->UpdateCredentials(credentials); -} - -void SyncManager::UpdateEnabledTypes() { - DCHECK(thread_checker_.CalledOnValidThread()); - data_->UpdateEnabledTypes(); -} - -void SyncManager::MaybeSetSyncTabsInNigoriNode( - ModelTypeSet enabled_types) { - DCHECK(thread_checker_.CalledOnValidThread()); - data_->MaybeSetSyncTabsInNigoriNode(enabled_types); -} - -void SyncManager::ThrowUnrecoverableError() { - DCHECK(thread_checker_.CalledOnValidThread()); - ReadTransaction trans(FROM_HERE, GetUserShare()); - trans.GetWrappedTrans()->OnUnrecoverableError( - FROM_HERE, "Simulating unrecoverable error for testing purposes."); -} - -bool SyncManager::InitialSyncEndedForAllEnabledTypes() { - return data_->InitialSyncEndedForAllEnabledTypes(); -} - -void SyncManager::StartSyncingNormally() { - DCHECK(thread_checker_.CalledOnValidThread()); - data_->StartSyncingNormally(); -} - -void SyncManager::SetEncryptionPassphrase(const std::string& passphrase, - bool is_explicit) { - DCHECK(thread_checker_.CalledOnValidThread()); - data_->SetEncryptionPassphrase(passphrase, is_explicit); -} - -void SyncManager::SetDecryptionPassphrase(const std::string& passphrase) { - DCHECK(thread_checker_.CalledOnValidThread()); - data_->SetDecryptionPassphrase(passphrase); -} - -void SyncManager::EnableEncryptEverything() { - DCHECK(thread_checker_.CalledOnValidThread()); - { - // Update the cryptographer to know we're now encrypting everything. - WriteTransaction trans(FROM_HERE, GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - // Only set encrypt everything if we know we can encrypt. This allows the - // user to cancel encryption if they have forgotten their passphrase. - if (cryptographer->is_ready()) - cryptographer->set_encrypt_everything(); - } - - // Reads from cryptographer so will automatically encrypt all - // datatypes and update the nigori node as necessary. Will trigger - // OnPassphraseRequired if necessary. - data_->RefreshEncryption(); -} - -bool SyncManager::EncryptEverythingEnabledForTest() const { - ReadTransaction trans(FROM_HERE, GetUserShare()); - return trans.GetCryptographer()->encrypt_everything(); -} - -bool SyncManager::IsUsingExplicitPassphrase() { - return data_ && data_->IsUsingExplicitPassphrase(); -} - -void SyncManager::RequestCleanupDisabledTypes() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (data_->scheduler()) - data_->scheduler()->ScheduleCleanupDisabledTypes(); -} - -void SyncManager::RequestClearServerData() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (data_->scheduler()) - data_->scheduler()->ScheduleClearUserData(); -} - -void SyncManager::RequestConfig( - ModelTypeSet types, ConfigureReason reason) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (!data_->scheduler()) { - LOG(INFO) - << "SyncManager::RequestConfig: bailing out because scheduler is " - << "null"; - return; - } - StartConfigurationMode(base::Closure()); - data_->scheduler()->ScheduleConfig(types, GetSourceFromReason(reason)); -} - -void SyncManager::StartConfigurationMode(const base::Closure& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (!data_->scheduler()) { - LOG(INFO) - << "SyncManager::StartConfigurationMode: could not start " - << "configuration mode because because scheduler is null"; - return; - } - data_->scheduler()->Start( - browser_sync::SyncScheduler::CONFIGURATION_MODE, callback); -} - -bool SyncManager::SyncInternal::Init( - const FilePath& database_location, - const WeakHandle<JsEventHandler>& event_handler, - const std::string& sync_server_and_path, - int port, - bool use_ssl, - const scoped_refptr<base::TaskRunner>& blocking_task_runner, - HttpPostProviderFactory* post_factory, - ModelSafeWorkerRegistrar* model_safe_worker_registrar, - browser_sync::ExtensionsActivityMonitor* extensions_activity_monitor, - ChangeDelegate* change_delegate, - const std::string& user_agent, - const SyncCredentials& credentials, - bool enable_sync_tabs_for_other_clients, - sync_notifier::SyncNotifier* sync_notifier, - const std::string& restored_key_for_bootstrapping, - TestingMode testing_mode, - Encryptor* encryptor, - UnrecoverableErrorHandler* unrecoverable_error_handler, - ReportUnrecoverableErrorFunction report_unrecoverable_error_function) { - CHECK(!initialized_); - - DCHECK(thread_checker_.CalledOnValidThread()); - - DVLOG(1) << "Starting SyncInternal initialization."; - - weak_handle_this_ = MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()); - - blocking_task_runner_ = blocking_task_runner; - - registrar_ = model_safe_worker_registrar; - change_delegate_ = change_delegate; - testing_mode_ = testing_mode; - - enable_sync_tabs_for_other_clients_ = enable_sync_tabs_for_other_clients; - - sync_notifier_.reset(sync_notifier); - - AddObserver(&js_sync_manager_observer_); - SetJsEventHandler(event_handler); - - AddObserver(&debug_info_event_listener_); - - database_path_ = database_location.Append( - syncable::Directory::kSyncDatabaseFilename); - encryptor_ = encryptor; - unrecoverable_error_handler_ = unrecoverable_error_handler; - report_unrecoverable_error_function_ = report_unrecoverable_error_function; - share_.directory.reset( - new syncable::Directory(encryptor_, - unrecoverable_error_handler_, - report_unrecoverable_error_function_)); - - connection_manager_.reset(new SyncAPIServerConnectionManager( - sync_server_and_path, port, use_ssl, user_agent, post_factory)); - - net::NetworkChangeNotifier::AddIPAddressObserver(this); - observing_ip_address_changes_ = true; - - connection_manager()->AddListener(this); - - - // Test mode does not use a syncer context or syncer thread. - if (testing_mode_ == NON_TEST) { - // Build a SyncSessionContext and store the worker in it. - DVLOG(1) << "Sync is bringing up SyncSessionContext."; - std::vector<SyncEngineEventListener*> listeners; - listeners.push_back(&allstatus_); - listeners.push_back(this); - SyncSessionContext* context = new SyncSessionContext( - connection_manager_.get(), - directory(), - model_safe_worker_registrar, - extensions_activity_monitor, - listeners, - &debug_info_event_listener_, - &traffic_recorder_); - context->set_account_name(credentials.email); - // The SyncScheduler takes ownership of |context|. - scheduler_.reset(new SyncScheduler(name_, context, new Syncer())); - } - - bool signed_in = SignIn(credentials); - - if (signed_in) { - if (scheduler()) { - scheduler()->Start( - browser_sync::SyncScheduler::CONFIGURATION_MODE, base::Closure()); - } - - initialized_ = true; - - // Cryptographer should only be accessed while holding a - // transaction. Grabbing the user share for the transaction - // checks the initialization state, so this must come after - // |initialized_| is set to true. - ReadTransaction trans(FROM_HERE, GetUserShare()); - trans.GetCryptographer()->Bootstrap(restored_key_for_bootstrapping); - trans.GetCryptographer()->AddObserver(this); - } - - // Notify that initialization is complete. Note: This should be the last to - // execute if |signed_in| is false. Reason being in that case we would - // post a task to shutdown sync. But if this function posts any other tasks - // on the UI thread and if shutdown wins then that tasks would execute on - // a freed pointer. This is because UI thread is not shut down. - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnInitializationComplete( - MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()), - signed_in)); - - if (!signed_in && testing_mode_ == NON_TEST) - return false; - - sync_notifier_->AddObserver(this); - - return signed_in; -} - -void SyncManager::SyncInternal::UpdateCryptographerAndNigori( - const std::string& chrome_version, - const base::Closure& done_callback) { - DCHECK(initialized_); - browser_sync::GetSessionName( - blocking_task_runner_, - base::Bind( - &SyncManager::SyncInternal::UpdateCryptographerAndNigoriCallback, - weak_ptr_factory_.GetWeakPtr(), - chrome_version, - done_callback)); -} - -void SyncManager::SyncInternal::UpdateNigoriEncryptionState( - Cryptographer* cryptographer, - WriteNode* nigori_node) { - DCHECK(nigori_node); - sync_pb::NigoriSpecifics nigori = nigori_node->GetNigoriSpecifics(); - - if (cryptographer->is_ready() && - nigori_overwrite_count_ < kNigoriOverwriteLimit) { - // Does not modify the encrypted blob if the unencrypted data already - // matches what is about to be written. - sync_pb::EncryptedData original_keys = nigori.encrypted(); - if (!cryptographer->GetKeys(nigori.mutable_encrypted())) - NOTREACHED(); - - if (nigori.encrypted().SerializeAsString() != - original_keys.SerializeAsString()) { - // We've updated the nigori node's encryption keys. In order to prevent - // a possible looping of two clients constantly overwriting each other, - // we limit the absolute number of overwrites per client instantiation. - nigori_overwrite_count_++; - UMA_HISTOGRAM_COUNTS("Sync.AutoNigoriOverwrites", - nigori_overwrite_count_); - } - - // Note: we don't try to set using_explicit_passphrase here since if that - // is lost the user can always set it again. The main point is to preserve - // the encryption keys so all data remains decryptable. - } - cryptographer->UpdateNigoriFromEncryptedTypes(&nigori); - - // If nothing has changed, this is a no-op. - nigori_node->SetNigoriSpecifics(nigori); -} - -void SyncManager::SyncInternal::UpdateCryptographerAndNigoriCallback( - const std::string& chrome_version, - const base::Closure& done_callback, - const std::string& session_name) { - if (!directory()->initial_sync_ended_for_type(syncable::NIGORI)) { - done_callback.Run(); // Should only happen during first time sync. - return; - } - - bool success = false; - { - WriteTransaction trans(FROM_HERE, GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - WriteNode node(&trans); - - if (node.InitByTagLookup(kNigoriTag) == sync_api::BaseNode::INIT_OK) { - sync_pb::NigoriSpecifics nigori(node.GetNigoriSpecifics()); - Cryptographer::UpdateResult result = cryptographer->Update(nigori); - if (result == Cryptographer::NEEDS_PASSPHRASE) { - sync_pb::EncryptedData pending_keys; - if (cryptographer->has_pending_keys()) - pending_keys = cryptographer->GetPendingKeys(); - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnPassphraseRequired(sync_api::REASON_DECRYPTION, - pending_keys)); - } - - - // Add or update device information. - bool contains_this_device = false; - for (int i = 0; i < nigori.device_information_size(); ++i) { - const sync_pb::DeviceInformation& device_information = - nigori.device_information(i); - if (device_information.cache_guid() == directory()->cache_guid()) { - // Update the version number in case it changed due to an update. - if (device_information.chrome_version() != chrome_version) { - sync_pb::DeviceInformation* mutable_device_information = - nigori.mutable_device_information(i); - mutable_device_information->set_chrome_version( - chrome_version); - } - contains_this_device = true; - } - } - - if (!contains_this_device) { - sync_pb::DeviceInformation* device_information = - nigori.add_device_information(); - device_information->set_cache_guid(directory()->cache_guid()); -#if defined(OS_CHROMEOS) - device_information->set_platform("ChromeOS"); -#elif defined(OS_LINUX) - device_information->set_platform("Linux"); -#elif defined(OS_MACOSX) - device_information->set_platform("Mac"); -#elif defined(OS_WIN) - device_information->set_platform("Windows"); -#endif - device_information->set_name(session_name); - device_information->set_chrome_version(chrome_version); - } - // Disabled to avoid nigori races. TODO(zea): re-enable. crbug.com/122837 - // node.SetNigoriSpecifics(nigori); - - // Make sure the nigori node has the up to date encryption info. - UpdateNigoriEncryptionState(cryptographer, &node); - - NotifyCryptographerState(cryptographer); - allstatus_.SetEncryptedTypes(cryptographer->GetEncryptedTypes()); - - success = cryptographer->is_ready(); - } else { - NOTREACHED(); - } - } - - if (success) - RefreshEncryption(); - done_callback.Run(); -} - -void SyncManager::SyncInternal::NotifyCryptographerState( - Cryptographer * cryptographer) { - // TODO(lipalani): Explore the possibility of hooking this up to - // SyncManager::Observer and making |AllStatus| a listener for that. - allstatus_.SetCryptographerReady(cryptographer->is_ready()); - allstatus_.SetCryptoHasPendingKeys(cryptographer->has_pending_keys()); - debug_info_event_listener_.SetCryptographerReady(cryptographer->is_ready()); - debug_info_event_listener_.SetCrytographerHasPendingKeys( - cryptographer->has_pending_keys()); -} - -void SyncManager::SyncInternal::StartSyncingNormally() { - // Start the sync scheduler. - if (scheduler()) // NULL during certain unittests. - scheduler()->Start(SyncScheduler::NORMAL_MODE, base::Closure()); -} - -bool SyncManager::SyncInternal::OpenDirectory() { - DCHECK(!initialized_) << "Should only happen once"; - - // Set before Open(). - change_observer_ = - browser_sync::MakeWeakHandle(js_mutation_event_observer_.AsWeakPtr()); - WeakHandle<syncable::TransactionObserver> transaction_observer( - browser_sync::MakeWeakHandle(js_mutation_event_observer_.AsWeakPtr())); - - syncable::DirOpenResult open_result = syncable::NOT_INITIALIZED; - if (testing_mode_ == TEST_IN_MEMORY) { - open_result = directory()->OpenInMemoryForTest( - username_for_share(), this, transaction_observer); - } else { - open_result = directory()->Open( - database_path_, username_for_share(), this, transaction_observer); - } - if (open_result != syncable::OPENED) { - LOG(ERROR) << "Could not open share for:" << username_for_share(); - return false; - } - - connection_manager()->set_client_id(directory()->cache_guid()); - return true; -} - -bool SyncManager::SyncInternal::SignIn(const SyncCredentials& credentials) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(share_.name.empty()); - share_.name = credentials.email; - - DVLOG(1) << "Signing in user: " << username_for_share(); - if (!OpenDirectory()) - return false; - - // Retrieve and set the sync notifier state. This should be done - // only after OpenDirectory is called. - std::string unique_id = directory()->cache_guid(); - std::string state = directory()->GetNotificationState(); - DVLOG(1) << "Read notification unique ID: " << unique_id; - if (VLOG_IS_ON(1)) { - std::string encoded_state; - base::Base64Encode(state, &encoded_state); - DVLOG(1) << "Read notification state: " << encoded_state; - } - allstatus_.SetUniqueId(unique_id); - sync_notifier_->SetUniqueId(unique_id); - sync_notifier_->SetState(state); - - UpdateCredentials(credentials); - UpdateEnabledTypes(); - return true; -} - -void SyncManager::SyncInternal::UpdateCredentials( - const SyncCredentials& credentials) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK_EQ(credentials.email, share_.name); - DCHECK(!credentials.email.empty()); - DCHECK(!credentials.sync_token.empty()); - - observing_ip_address_changes_ = true; - if (connection_manager()->set_auth_token(credentials.sync_token)) { - sync_notifier_->UpdateCredentials( - credentials.email, credentials.sync_token); - if (testing_mode_ == NON_TEST && initialized_) { - if (scheduler()) - scheduler()->OnCredentialsUpdated(); - } - } -} - -void SyncManager::SyncInternal::UpdateEnabledTypes() { - DCHECK(thread_checker_.CalledOnValidThread()); - ModelSafeRoutingInfo routes; - registrar_->GetModelSafeRoutingInfo(&routes); - const ModelTypeSet enabled_types = GetRoutingInfoTypes(routes); - sync_notifier_->UpdateEnabledTypes(enabled_types); - if (enable_sync_tabs_for_other_clients_) - MaybeSetSyncTabsInNigoriNode(enabled_types); -} - -void SyncManager::SyncInternal::MaybeSetSyncTabsInNigoriNode( - const ModelTypeSet enabled_types) { - // The initialized_ check is to ensure that we don't CHECK in GetUserShare - // when this is called on start-up. It's ok to ignore that case, since - // presumably this would've run when the user originally enabled sessions. - if (initialized_ && enabled_types.Has(syncable::SESSIONS)) { - WriteTransaction trans(FROM_HERE, GetUserShare()); - WriteNode node(&trans); - if (node.InitByTagLookup(kNigoriTag) != sync_api::BaseNode::INIT_OK) { - LOG(WARNING) << "Unable to set 'sync_tabs' bit because Nigori node not " - << "found."; - return; - } - - sync_pb::NigoriSpecifics specifics(node.GetNigoriSpecifics()); - specifics.set_sync_tabs(true); - node.SetNigoriSpecifics(specifics); - } -} - -void SyncManager::SyncInternal::SetEncryptionPassphrase( - const std::string& passphrase, - bool is_explicit) { - // We do not accept empty passphrases. - if (passphrase.empty()) { - NOTREACHED() << "Cannot encrypt with an empty passphrase."; - return; - } - - // All accesses to the cryptographer are protected by a transaction. - WriteTransaction trans(FROM_HERE, GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - KeyParams key_params = {"localhost", "dummy", passphrase}; - WriteNode node(&trans); - if (node.InitByTagLookup(kNigoriTag) != sync_api::BaseNode::INIT_OK) { - // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. - NOTREACHED(); - return; - } - - bool nigori_has_explicit_passphrase = - node.GetNigoriSpecifics().using_explicit_passphrase(); - std::string bootstrap_token; - sync_pb::EncryptedData pending_keys; - if (cryptographer->has_pending_keys()) - pending_keys = cryptographer->GetPendingKeys(); - bool success = false; - - - // There are six cases to handle here: - // 1. The user has no pending keys and is setting their current GAIA password - // as the encryption passphrase. This happens either during first time sync - // with a clean profile, or after re-authenticating on a profile that was - // already signed in with the cryptographer ready. - // 2. The user has no pending keys, and is overwriting an (already provided) - // implicit passphrase with an explicit (custom) passphrase. - // 3. The user has pending keys for an explicit passphrase that is somehow set - // to their current GAIA passphrase. - // 4. The user has pending keys encrypted with their current GAIA passphrase - // and the caller passes in the current GAIA passphrase. - // 5. The user has pending keys encrypted with an older GAIA passphrase - // and the caller passes in the current GAIA passphrase. - // 6. The user has previously done encryption with an explicit passphrase. - // Furthermore, we enforce the fact that the bootstrap encryption token will - // always be derived from the newest GAIA password if the account is using - // an implicit passphrase (even if the data is encrypted with an old GAIA - // password). If the account is using an explicit (custom) passphrase, the - // bootstrap token will be derived from the most recently provided explicit - // passphrase (that was able to decrypt the data). - if (!nigori_has_explicit_passphrase) { - if (!cryptographer->has_pending_keys()) { - if (cryptographer->AddKey(key_params)) { - // Case 1 and 2. We set a new GAIA passphrase when there are no pending - // keys (1), or overwriting an implicit passphrase with a new explicit - // one (2) when there are no pending keys. - DVLOG(1) << "Setting " << (is_explicit ? "explicit" : "implicit" ) - << " passphrase for encryption."; - cryptographer->GetBootstrapToken(&bootstrap_token); - success = true; - } else { - NOTREACHED() << "Failed to add key to cryptographer."; - success = false; - } - } else { // cryptographer->has_pending_keys() == true - if (is_explicit) { - // This can only happen if the nigori node is updated with a new - // implicit passphrase while a client is attempting to set a new custom - // passphrase (race condition). - DVLOG(1) << "Failing because an implicit passphrase is already set."; - success = false; - } else { // is_explicit == false - if (cryptographer->DecryptPendingKeys(key_params)) { - // Case 4. We successfully decrypted with the implicit GAIA passphrase - // passed in. - DVLOG(1) << "Implicit internal passphrase accepted for decryption."; - cryptographer->GetBootstrapToken(&bootstrap_token); - success = true; - } else { - // Case 5. Encryption was done with an old GAIA password, but we were - // provided with the current GAIA password. We need to generate a new - // bootstrap token to preserve it. We build a temporary cryptographer - // to allow us to extract these params without polluting our current - // cryptographer. - DVLOG(1) << "Implicit internal passphrase failed to decrypt, adding " - << "anyways as default passphrase and persisting via " - << "bootstrap token."; - Cryptographer temp_cryptographer(encryptor_); - temp_cryptographer.AddKey(key_params); - temp_cryptographer.GetBootstrapToken(&bootstrap_token); - // We then set the new passphrase as the default passphrase of the - // real cryptographer, even though we have pending keys. This is safe, - // as although Cryptographer::is_initialized() will now be true, - // is_ready() will remain false due to having pending keys. - cryptographer->AddKey(key_params); - success = false; - } - } // is_explicit - } // cryptographer->has_pending_keys() - } else { // nigori_has_explicit_passphrase == true - // Case 6. We do not want to override a previously set explicit passphrase, - // so we return a failure. - DVLOG(1) << "Failing because an explicit passphrase is already set."; - success = false; - } - - DVLOG_IF(1, !success) - << "Failure in SetEncryptionPassphrase; notifying and returning."; - DVLOG_IF(1, success) - << "Successfully set encryption passphrase; updating nigori and " - "reencrypting."; - - FinishSetPassphrase( - success, bootstrap_token, is_explicit, &trans, &node); -} - -void SyncManager::SyncInternal::SetDecryptionPassphrase( - const std::string& passphrase) { - // We do not accept empty passphrases. - if (passphrase.empty()) { - NOTREACHED() << "Cannot decrypt with an empty passphrase."; - return; - } - - // All accesses to the cryptographer are protected by a transaction. - WriteTransaction trans(FROM_HERE, GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - KeyParams key_params = {"localhost", "dummy", passphrase}; - WriteNode node(&trans); - if (node.InitByTagLookup(kNigoriTag) != sync_api::BaseNode::INIT_OK) { - // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. - NOTREACHED(); - return; - } - - if (!cryptographer->has_pending_keys()) { - // Note that this *can* happen in a rare situation where data is - // re-encrypted on another client while a SetDecryptionPassphrase() call is - // in-flight on this client. It is rare enough that we choose to do nothing. - NOTREACHED() << "Attempt to set decryption passphrase failed because there " - << "were no pending keys."; - return; - } - - bool nigori_has_explicit_passphrase = - node.GetNigoriSpecifics().using_explicit_passphrase(); - std::string bootstrap_token; - sync_pb::EncryptedData pending_keys; - pending_keys = cryptographer->GetPendingKeys(); - bool success = false; - - // There are three cases to handle here: - // 7. We're using the current GAIA password to decrypt the pending keys. This - // happens when signing in to an account with a previously set implicit - // passphrase, where the data is already encrypted with the newest GAIA - // password. - // 8. The user is providing an old GAIA password to decrypt the pending keys. - // In this case, the user is using an implicit passphrase, but has changed - // their password since they last encrypted their data, and therefore - // their current GAIA password was unable to decrypt the data. This will - // happen when the user is setting up a new profile with a previously - // encrypted account (after changing passwords). - // 9. The user is providing a previously set explicit passphrase to decrypt - // the pending keys. - if (!nigori_has_explicit_passphrase) { - if (cryptographer->is_initialized()) { - // We only want to change the default encryption key to the pending - // one if the pending keybag already contains the current default. - // This covers the case where a different client re-encrypted - // everything with a newer gaia passphrase (and hence the keybag - // contains keys from all previously used gaia passphrases). - // Otherwise, we're in a situation where the pending keys are - // encrypted with an old gaia passphrase, while the default is the - // current gaia passphrase. In that case, we preserve the default. - Cryptographer temp_cryptographer(encryptor_); - temp_cryptographer.SetPendingKeys(cryptographer->GetPendingKeys()); - if (temp_cryptographer.DecryptPendingKeys(key_params)) { - // Check to see if the pending bag of keys contains the current - // default key. - sync_pb::EncryptedData encrypted; - cryptographer->GetKeys(&encrypted); - if (temp_cryptographer.CanDecrypt(encrypted)) { - DVLOG(1) << "Implicit user provided passphrase accepted for " - << "decryption, overwriting default."; - // Case 7. The pending keybag contains the current default. Go ahead - // and update the cryptographer, letting the default change. - cryptographer->DecryptPendingKeys(key_params); - cryptographer->GetBootstrapToken(&bootstrap_token); - success = true; - } else { - // Case 8. The pending keybag does not contain the current default - // encryption key. We decrypt the pending keys here, and in - // FinishSetPassphrase, re-encrypt everything with the current GAIA - // passphrase instead of the passphrase just provided by the user. - DVLOG(1) << "Implicit user provided passphrase accepted for " - << "decryption, restoring implicit internal passphrase " - << "as default."; - std::string bootstrap_token_from_current_key; - cryptographer->GetBootstrapToken( - &bootstrap_token_from_current_key); - cryptographer->DecryptPendingKeys(key_params); - // Overwrite the default from the pending keys. - cryptographer->AddKeyFromBootstrapToken( - bootstrap_token_from_current_key); - success = true; - } - } else { // !temp_cryptographer.DecryptPendingKeys(..) - DVLOG(1) << "Implicit user provided passphrase failed to decrypt."; - success = false; - } // temp_cryptographer.DecryptPendingKeys(...) - } else { // cryptographer->is_initialized() == false - if (cryptographer->DecryptPendingKeys(key_params)) { - // This can happpen in two cases: - // - First time sync on android, where we'll never have a - // !user_provided passphrase. - // - This is a restart for a client that lost their bootstrap token. - // In both cases, we should go ahead and initialize the cryptographer - // and persist the new bootstrap token. - // - // Note: at this point, we cannot distinguish between cases 7 and 8 - // above. This user provided passphrase could be the current or the - // old. But, as long as we persist the token, there's nothing more - // we can do. - cryptographer->GetBootstrapToken(&bootstrap_token); - DVLOG(1) << "Implicit user provided passphrase accepted, initializing" - << " cryptographer."; - success = true; - } else { - DVLOG(1) << "Implicit user provided passphrase failed to decrypt."; - success = false; - } - } // cryptographer->is_initialized() - } else { // nigori_has_explicit_passphrase == true - // Case 9. Encryption was done with an explicit passphrase, and we decrypt - // with the passphrase provided by the user. - if (cryptographer->DecryptPendingKeys(key_params)) { - DVLOG(1) << "Explicit passphrase accepted for decryption."; - cryptographer->GetBootstrapToken(&bootstrap_token); - success = true; - } else { - DVLOG(1) << "Explicit passphrase failed to decrypt."; - success = false; - } - } // nigori_has_explicit_passphrase - - DVLOG_IF(1, !success) - << "Failure in SetDecryptionPassphrase; notifying and returning."; - DVLOG_IF(1, success) - << "Successfully set decryption passphrase; updating nigori and " - "reencrypting."; - - FinishSetPassphrase(success, - bootstrap_token, - nigori_has_explicit_passphrase, - &trans, - &node); -} - -void SyncManager::SyncInternal::FinishSetPassphrase( - bool success, - const std::string& bootstrap_token, - bool is_explicit, - WriteTransaction* trans, - WriteNode* nigori_node) { - Cryptographer* cryptographer = trans->GetCryptographer(); - NotifyCryptographerState(cryptographer); - - // It's possible we need to change the bootstrap token even if we failed to - // set the passphrase (for example if we need to preserve the new GAIA - // passphrase). - if (!bootstrap_token.empty()) { - DVLOG(1) << "Bootstrap token updated."; - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnBootstrapTokenUpdated(bootstrap_token)); - } - - if (!success) { - if (cryptographer->is_ready()) { - LOG(ERROR) << "Attempt to change passphrase failed while cryptographer " - << "was ready."; - } else if (cryptographer->has_pending_keys()) { - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnPassphraseRequired(sync_api::REASON_DECRYPTION, - cryptographer->GetPendingKeys())); - } else { - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnPassphraseRequired(sync_api::REASON_ENCRYPTION, - sync_pb::EncryptedData())); - } - return; - } - - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnPassphraseAccepted()); - DCHECK(cryptographer->is_ready()); - - // TODO(tim): Bug 58231. It would be nice if setting a passphrase didn't - // require messing with the Nigori node, because we can't set a passphrase - // until download conditions are met vs Cryptographer init. It seems like - // it's safe to defer this work. - sync_pb::NigoriSpecifics specifics(nigori_node->GetNigoriSpecifics()); - // Does not modify specifics.encrypted() if the original decrypted data was - // the same. - if (!cryptographer->GetKeys(specifics.mutable_encrypted())) { - NOTREACHED(); - return; - } - specifics.set_using_explicit_passphrase(is_explicit); - nigori_node->SetNigoriSpecifics(specifics); - - // Does nothing if everything is already encrypted or the cryptographer has - // pending keys. - ReEncryptEverything(trans); -} - -bool SyncManager::SyncInternal::IsUsingExplicitPassphrase() { - ReadTransaction trans(FROM_HERE, &share_); - ReadNode node(&trans); - if (node.InitByTagLookup(kNigoriTag) != sync_api::BaseNode::INIT_OK) { - // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. - NOTREACHED(); - return false; - } - - return node.GetNigoriSpecifics().using_explicit_passphrase(); -} - -void SyncManager::SyncInternal::RefreshEncryption() { - DCHECK(initialized_); - - WriteTransaction trans(FROM_HERE, GetUserShare()); - WriteNode node(&trans); - if (node.InitByTagLookup(kNigoriTag) != sync_api::BaseNode::INIT_OK) { - NOTREACHED() << "Unable to set encrypted datatypes because Nigori node not " - << "found."; - return; - } - - Cryptographer* cryptographer = trans.GetCryptographer(); - - if (!cryptographer->is_ready()) { - DVLOG(1) << "Attempting to encrypt datatypes when cryptographer not " - << "initialized, prompting for passphrase."; - // TODO(zea): this isn't really decryption, but that's the only way we have - // to prompt the user for a passsphrase. See http://crbug.com/91379. - sync_pb::EncryptedData pending_keys; - if (cryptographer->has_pending_keys()) - pending_keys = cryptographer->GetPendingKeys(); - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnPassphraseRequired(sync_api::REASON_DECRYPTION, - pending_keys)); - return; - } - - UpdateNigoriEncryptionState(cryptographer, &node); - - allstatus_.SetEncryptedTypes(cryptographer->GetEncryptedTypes()); - - // We reencrypt everything regardless of whether the set of encrypted - // types changed to ensure that any stray unencrypted entries are overwritten. - ReEncryptEverything(&trans); -} - -void SyncManager::SyncInternal::ReEncryptEverything(WriteTransaction* trans) { - Cryptographer* cryptographer = trans->GetCryptographer(); - if (!cryptographer || !cryptographer->is_ready()) - return; - syncable::ModelTypeSet encrypted_types = GetEncryptedTypes(trans); - ModelSafeRoutingInfo routes; - registrar_->GetModelSafeRoutingInfo(&routes); - std::string tag; - for (syncable::ModelTypeSet::Iterator iter = encrypted_types.First(); - iter.Good(); iter.Inc()) { - if (iter.Get() == syncable::PASSWORDS || - iter.Get() == syncable::NIGORI || - routes.count(iter.Get()) == 0) - continue; - ReadNode type_root(trans); - tag = syncable::ModelTypeToRootTag(iter.Get()); - if (type_root.InitByTagLookup(tag) != sync_api::BaseNode::INIT_OK) { - // This can happen when we enable a datatype for the first time on restart - // (for example when we upgrade) and therefore haven't done the initial - // download for that type at the time we RefreshEncryption. There's - // nothing we can do for now, so just move on to the next type. - continue; - } - - // Iterate through all children of this datatype. - std::queue<int64> to_visit; - int64 child_id = type_root.GetFirstChildId(); - to_visit.push(child_id); - while (!to_visit.empty()) { - child_id = to_visit.front(); - to_visit.pop(); - if (child_id == kInvalidId) - continue; - - WriteNode child(trans); - if (child.InitByIdLookup(child_id) != sync_api::BaseNode::INIT_OK) { - NOTREACHED(); - continue; - } - if (child.GetIsFolder()) { - to_visit.push(child.GetFirstChildId()); - } - if (child.GetEntry()->Get(syncable::UNIQUE_SERVER_TAG).empty()) { - // Rewrite the specifics of the node with encrypted data if necessary - // (only rewrite the non-unique folders). - child.ResetFromSpecifics(); - } - to_visit.push(child.GetSuccessorId()); - } - } - - if (routes.count(syncable::PASSWORDS) > 0) { - // Passwords are encrypted with their own legacy scheme. - ReadNode passwords_root(trans); - std::string passwords_tag = - syncable::ModelTypeToRootTag(syncable::PASSWORDS); - // It's possible we'll have the password routing info and not the password - // root if we attempted to set a passphrase before passwords was enabled. - if (passwords_root.InitByTagLookup(passwords_tag) == - sync_api::BaseNode::INIT_OK) { - int64 child_id = passwords_root.GetFirstChildId(); - while (child_id != kInvalidId) { - WriteNode child(trans); - if (child.InitByIdLookup(child_id) != sync_api::BaseNode::INIT_OK) { - NOTREACHED(); - return; - } - child.SetPasswordSpecifics(child.GetPasswordSpecifics()); - child_id = child.GetSuccessorId(); - } - } - } - - // NOTE: We notify from within a transaction. - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, OnEncryptionComplete()); -} - -SyncManager::~SyncManager() { - DCHECK(thread_checker_.CalledOnValidThread()); - delete data_; -} - -void SyncManager::AddObserver(Observer* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); - data_->AddObserver(observer); -} - -void SyncManager::RemoveObserver(Observer* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); - data_->RemoveObserver(observer); -} - -void SyncManager::StopSyncingForShutdown(const base::Closure& callback) { - data_->StopSyncingForShutdown(callback); -} - -void SyncManager::SyncInternal::StopSyncingForShutdown( - const base::Closure& callback) { - DVLOG(2) << "StopSyncingForShutdown"; - if (scheduler()) // May be null in tests. - scheduler()->RequestStop(callback); - else - created_on_loop_->PostTask(FROM_HERE, callback); - - if (connection_manager_.get()) - connection_manager_->TerminateAllIO(); -} - -void SyncManager::ShutdownOnSyncThread() { - DCHECK(thread_checker_.CalledOnValidThread()); - data_->ShutdownOnSyncThread(); -} - -void SyncManager::SyncInternal::ShutdownOnSyncThread() { - DCHECK(thread_checker_.CalledOnValidThread()); - - // Prevent any in-flight method calls from running. Also - // invalidates |weak_handle_this_| and |change_observer_|. - weak_ptr_factory_.InvalidateWeakPtrs(); - js_mutation_event_observer_.InvalidateWeakPtrs(); - - scheduler_.reset(); - - SetJsEventHandler(WeakHandle<JsEventHandler>()); - RemoveObserver(&js_sync_manager_observer_); - - RemoveObserver(&debug_info_event_listener_); - - if (sync_notifier_.get()) { - sync_notifier_->RemoveObserver(this); - } - sync_notifier_.reset(); - - if (connection_manager_.get()) { - connection_manager_->RemoveListener(this); - } - connection_manager_.reset(); - - net::NetworkChangeNotifier::RemoveIPAddressObserver(this); - observing_ip_address_changes_ = false; - - if (initialized_ && directory()) { - { - // Cryptographer should only be accessed while holding a - // transaction. - ReadTransaction trans(FROM_HERE, GetUserShare()); - trans.GetCryptographer()->RemoveObserver(this); - } - directory()->SaveChanges(); - } - - share_.directory.reset(); - - change_delegate_ = NULL; - registrar_ = NULL; - - initialized_ = false; - - // We reset these here, since only now we know they will not be - // accessed from other threads (since we shut down everything). - change_observer_.Reset(); - weak_handle_this_.Reset(); -} - -void SyncManager::SyncInternal::OnIPAddressChanged() { - DVLOG(1) << "IP address change detected"; - if (!observing_ip_address_changes_) { - DVLOG(1) << "IP address change dropped."; - return; - } - - OnIPAddressChangedImpl(); -} - -void SyncManager::SyncInternal::OnIPAddressChangedImpl() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (scheduler()) - scheduler()->OnConnectionStatusChange(); -} - -void SyncManager::SyncInternal::OnServerConnectionEvent( - const ServerConnectionEvent& event) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (event.connection_code == - browser_sync::HttpResponse::SERVER_CONNECTION_OK) { - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnConnectionStatusChange(CONNECTION_OK)); - } - - if (event.connection_code == browser_sync::HttpResponse::SYNC_AUTH_ERROR) { - observing_ip_address_changes_ = false; - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnConnectionStatusChange(CONNECTION_AUTH_ERROR)); - } - - if (event.connection_code == - browser_sync::HttpResponse::SYNC_SERVER_ERROR) { - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnConnectionStatusChange(CONNECTION_SERVER_ERROR)); - } -} - -void SyncManager::SyncInternal::HandleTransactionCompleteChangeEvent( - ModelTypeSet models_with_changes) { - // This notification happens immediately after the transaction mutex is - // released. This allows work to be performed without blocking other threads - // from acquiring a transaction. - if (!change_delegate_) - return; - - // Call commit. - for (ModelTypeSet::Iterator it = models_with_changes.First(); - it.Good(); it.Inc()) { - change_delegate_->OnChangesComplete(it.Get()); - change_observer_.Call( - FROM_HERE, &SyncManager::ChangeObserver::OnChangesComplete, it.Get()); - } -} - -ModelTypeSet - SyncManager::SyncInternal::HandleTransactionEndingChangeEvent( - const ImmutableWriteTransactionInfo& write_transaction_info, - syncable::BaseTransaction* trans) { - // This notification happens immediately before a syncable WriteTransaction - // falls out of scope. It happens while the channel mutex is still held, - // and while the transaction mutex is held, so it cannot be re-entrant. - if (!change_delegate_ || ChangeBuffersAreEmpty()) - return ModelTypeSet(); - - // This will continue the WriteTransaction using a read only wrapper. - // This is the last chance for read to occur in the WriteTransaction - // that's closing. This special ReadTransaction will not close the - // underlying transaction. - ReadTransaction read_trans(GetUserShare(), trans); - - ModelTypeSet models_with_changes; - for (int i = syncable::FIRST_REAL_MODEL_TYPE; - i < syncable::MODEL_TYPE_COUNT; ++i) { - const syncable::ModelType type = syncable::ModelTypeFromInt(i); - if (change_buffers_[type].IsEmpty()) - continue; - - ImmutableChangeRecordList ordered_changes; - // TODO(akalin): Propagate up the error further (see - // http://crbug.com/100907). - CHECK(change_buffers_[type].GetAllChangesInTreeOrder(&read_trans, - &ordered_changes)); - if (!ordered_changes.Get().empty()) { - change_delegate_-> - OnChangesApplied(type, &read_trans, ordered_changes); - change_observer_.Call(FROM_HERE, - &SyncManager::ChangeObserver::OnChangesApplied, - type, write_transaction_info.Get().id, ordered_changes); - models_with_changes.Put(type); - } - change_buffers_[i].Clear(); - } - return models_with_changes; -} - -void SyncManager::SyncInternal::HandleCalculateChangesChangeEventFromSyncApi( - const ImmutableWriteTransactionInfo& write_transaction_info, - syncable::BaseTransaction* trans) { - if (!scheduler()) { - return; - } - - // We have been notified about a user action changing a sync model. - LOG_IF(WARNING, !ChangeBuffersAreEmpty()) << - "CALCULATE_CHANGES called with unapplied old changes."; - - // The mutated model type, or UNSPECIFIED if nothing was mutated. - syncable::ModelTypeSet mutated_model_types; - - const syncable::ImmutableEntryKernelMutationMap& mutations = - write_transaction_info.Get().mutations; - for (syncable::EntryKernelMutationMap::const_iterator it = - mutations.Get().begin(); it != mutations.Get().end(); ++it) { - if (!it->second.mutated.ref(syncable::IS_UNSYNCED)) { - continue; - } - - syncable::ModelType model_type = - syncable::GetModelTypeFromSpecifics( - it->second.mutated.ref(SPECIFICS)); - if (model_type < syncable::FIRST_REAL_MODEL_TYPE) { - NOTREACHED() << "Permanent or underspecified item changed via syncapi."; - continue; - } - - // Found real mutation. - if (model_type != syncable::UNSPECIFIED) { - mutated_model_types.Put(model_type); - } - } - - // Nudge if necessary. - if (!mutated_model_types.Empty()) { - if (weak_handle_this_.IsInitialized()) { - weak_handle_this_.Call(FROM_HERE, - &SyncInternal::RequestNudgeForDataTypes, - FROM_HERE, - mutated_model_types); - } else { - NOTREACHED(); - } - } -} - -void SyncManager::SyncInternal::SetExtraChangeRecordData(int64 id, - syncable::ModelType type, ChangeReorderBuffer* buffer, - Cryptographer* cryptographer, const syncable::EntryKernel& original, - bool existed_before, bool exists_now) { - // If this is a deletion and the datatype was encrypted, we need to decrypt it - // and attach it to the buffer. - if (!exists_now && existed_before) { - sync_pb::EntitySpecifics original_specifics(original.ref(SPECIFICS)); - if (type == syncable::PASSWORDS) { - // Passwords must use their own legacy ExtraPasswordChangeRecordData. - scoped_ptr<sync_pb::PasswordSpecificsData> data( - DecryptPasswordSpecifics(original_specifics, cryptographer)); - if (!data.get()) { - NOTREACHED(); - return; - } - buffer->SetExtraDataForId(id, new ExtraPasswordChangeRecordData(*data)); - } else if (original_specifics.has_encrypted()) { - // All other datatypes can just create a new unencrypted specifics and - // attach it. - const sync_pb::EncryptedData& encrypted = original_specifics.encrypted(); - if (!cryptographer->Decrypt(encrypted, &original_specifics)) { - NOTREACHED(); - return; - } - } - buffer->SetSpecificsForId(id, original_specifics); - } -} - -void SyncManager::SyncInternal::HandleCalculateChangesChangeEventFromSyncer( - const ImmutableWriteTransactionInfo& write_transaction_info, - syncable::BaseTransaction* trans) { - // We only expect one notification per sync step, so change_buffers_ should - // contain no pending entries. - LOG_IF(WARNING, !ChangeBuffersAreEmpty()) << - "CALCULATE_CHANGES called with unapplied old changes."; - - Cryptographer* crypto = directory()->GetCryptographer(trans); - const syncable::ImmutableEntryKernelMutationMap& mutations = - write_transaction_info.Get().mutations; - for (syncable::EntryKernelMutationMap::const_iterator it = - mutations.Get().begin(); it != mutations.Get().end(); ++it) { - bool existed_before = !it->second.original.ref(syncable::IS_DEL); - bool exists_now = !it->second.mutated.ref(syncable::IS_DEL); - - // Omit items that aren't associated with a model. - syncable::ModelType type = - syncable::GetModelTypeFromSpecifics( - it->second.mutated.ref(SPECIFICS)); - if (type < syncable::FIRST_REAL_MODEL_TYPE) - continue; - - int64 handle = it->first; - if (exists_now && !existed_before) - change_buffers_[type].PushAddedItem(handle); - else if (!exists_now && existed_before) - change_buffers_[type].PushDeletedItem(handle); - else if (exists_now && existed_before && - VisiblePropertiesDiffer(it->second, crypto)) { - change_buffers_[type].PushUpdatedItem( - handle, VisiblePositionsDiffer(it->second)); - } - - SetExtraChangeRecordData(handle, type, &change_buffers_[type], crypto, - it->second.original, existed_before, exists_now); - } -} - -SyncManager::Status SyncManager::SyncInternal::GetStatus() { - return allstatus_.status(); -} - -void SyncManager::SyncInternal::RequestNudge( - const tracked_objects::Location& location) { - if (scheduler()) { - scheduler()->ScheduleNudge( - TimeDelta::FromMilliseconds(0), browser_sync::NUDGE_SOURCE_LOCAL, - ModelTypeSet(), location); - } -} - -TimeDelta SyncManager::SyncInternal::GetNudgeDelayTimeDelta( - const ModelType& model_type) { - return NudgeStrategy::GetNudgeDelayTimeDelta(model_type, this); -} - -void SyncManager::SyncInternal::RequestNudgeForDataTypes( - const tracked_objects::Location& nudge_location, - ModelTypeSet types) { - if (!scheduler()) { - NOTREACHED(); - return; - } - - debug_info_event_listener_.OnNudgeFromDatatype(types.First().Get()); - - // TODO(lipalani) : Calculate the nudge delay based on all types. - base::TimeDelta nudge_delay = NudgeStrategy::GetNudgeDelayTimeDelta( - types.First().Get(), - this); - scheduler()->ScheduleNudge(nudge_delay, - browser_sync::NUDGE_SOURCE_LOCAL, - types, - nudge_location); -} - -void SyncManager::SyncInternal::OnSyncEngineEvent( - const SyncEngineEvent& event) { - DCHECK(thread_checker_.CalledOnValidThread()); - // Only send an event if this is due to a cycle ending and this cycle - // concludes a canonical "sync" process; that is, based on what is known - // locally we are "all happy" and up-to-date. There may be new changes on - // the server, but we'll get them on a subsequent sync. - // - // Notifications are sent at the end of every sync cycle, regardless of - // whether we should sync again. - if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) { - ModelSafeRoutingInfo enabled_types; - registrar_->GetModelSafeRoutingInfo(&enabled_types); - { - // Check to see if we need to notify the frontend that we have newly - // encrypted types or that we require a passphrase. - ReadTransaction trans(FROM_HERE, GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - // If we've completed a sync cycle and the cryptographer isn't ready - // yet, prompt the user for a passphrase. - if (cryptographer->has_pending_keys()) { - DVLOG(1) << "OnPassPhraseRequired Sent"; - sync_pb::EncryptedData pending_keys = cryptographer->GetPendingKeys(); - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnPassphraseRequired(sync_api::REASON_DECRYPTION, - pending_keys)); - } else if (!cryptographer->is_ready() && - event.snapshot->initial_sync_ended.Has(syncable::NIGORI)) { - DVLOG(1) << "OnPassphraseRequired sent because cryptographer is not " - << "ready"; - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnPassphraseRequired(sync_api::REASON_ENCRYPTION, - sync_pb::EncryptedData())); - } - - NotifyCryptographerState(cryptographer); - allstatus_.SetEncryptedTypes(cryptographer->GetEncryptedTypes()); - } - - if (!initialized_) { - LOG(INFO) << "OnSyncCycleCompleted not sent because sync api is not " - << "initialized"; - return; - } - - if (!event.snapshot->has_more_to_sync) { - // To account for a nigori node arriving with stale/bad data, we ensure - // that the nigori node is up to date at the end of each cycle. - WriteTransaction trans(FROM_HERE, GetUserShare()); - WriteNode nigori_node(&trans); - if (nigori_node.InitByTagLookup(kNigoriTag) == - sync_api::BaseNode::INIT_OK) { - Cryptographer* cryptographer = trans.GetCryptographer(); - UpdateNigoriEncryptionState(cryptographer, &nigori_node); - } - - DVLOG(1) << "Sending OnSyncCycleCompleted"; - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnSyncCycleCompleted(event.snapshot)); - } - - // This is here for tests, which are still using p2p notifications. - // - // TODO(chron): Consider changing this back to track has_more_to_sync - // only notify peers if a successful commit has occurred. - bool is_notifiable_commit = - (event.snapshot->syncer_status.num_successful_commits > 0); - if (is_notifiable_commit) { - if (sync_notifier_.get()) { - const ModelTypeSet changed_types = - syncable::ModelTypePayloadMapToEnumSet( - event.snapshot->source.types); - sync_notifier_->SendNotification(changed_types); - } else { - DVLOG(1) << "Not sending notification: sync_notifier_ is NULL"; - } - } - } - - if (event.what_happened == SyncEngineEvent::STOP_SYNCING_PERMANENTLY) { - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnStopSyncingPermanently()); - return; - } - - if (event.what_happened == SyncEngineEvent::CLEAR_SERVER_DATA_SUCCEEDED) { - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnClearServerDataSucceeded()); - return; - } - - if (event.what_happened == SyncEngineEvent::CLEAR_SERVER_DATA_FAILED) { - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnClearServerDataFailed()); - return; - } - - if (event.what_happened == SyncEngineEvent::UPDATED_TOKEN) { - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnUpdatedToken(event.updated_token)); - return; - } - - if (event.what_happened == SyncEngineEvent::ACTIONABLE_ERROR) { - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnActionableError( - event.snapshot->errors.sync_protocol_error)); - return; - } - -} - -void SyncManager::SyncInternal::SetJsEventHandler( - const WeakHandle<JsEventHandler>& event_handler) { - js_event_handler_ = event_handler; - js_sync_manager_observer_.SetJsEventHandler(js_event_handler_); - js_mutation_event_observer_.SetJsEventHandler(js_event_handler_); -} - -void SyncManager::SyncInternal::ProcessJsMessage( - const std::string& name, const JsArgList& args, - const WeakHandle<JsReplyHandler>& reply_handler) { - if (!initialized_) { - NOTREACHED(); - return; - } - - if (!reply_handler.IsInitialized()) { - DVLOG(1) << "Uninitialized reply handler; dropping unknown message " - << name << " with args " << args.ToString(); - return; - } - - JsMessageHandler js_message_handler = js_message_handlers_[name]; - if (js_message_handler.is_null()) { - DVLOG(1) << "Dropping unknown message " << name - << " with args " << args.ToString(); - return; - } - - reply_handler.Call(FROM_HERE, - &JsReplyHandler::HandleJsReply, - name, js_message_handler.Run(args)); -} - -void SyncManager::SyncInternal::BindJsMessageHandler( - const std::string& name, - UnboundJsMessageHandler unbound_message_handler) { - js_message_handlers_[name] = - base::Bind(unbound_message_handler, base::Unretained(this)); -} - -DictionaryValue* SyncManager::SyncInternal::NotificationInfoToValue( - const NotificationInfoMap& notification_info) { - DictionaryValue* value = new DictionaryValue(); - - for (NotificationInfoMap::const_iterator it = notification_info.begin(); - it != notification_info.end(); ++it) { - const std::string& model_type_str = - syncable::ModelTypeToString(it->first); - value->Set(model_type_str, it->second.ToValue()); - } - - return value; -} - -JsArgList SyncManager::SyncInternal::GetNotificationState( - const JsArgList& args) { - bool notifications_enabled = allstatus_.status().notifications_enabled; - ListValue return_args; - return_args.Append(Value::CreateBooleanValue(notifications_enabled)); - return JsArgList(&return_args); -} - -JsArgList SyncManager::SyncInternal::GetNotificationInfo( - const JsArgList& args) { - ListValue return_args; - return_args.Append(NotificationInfoToValue(notification_info_map_)); - return JsArgList(&return_args); -} - -JsArgList SyncManager::SyncInternal::GetRootNodeDetails( - const JsArgList& args) { - ReadTransaction trans(FROM_HERE, GetUserShare()); - ReadNode root(&trans); - root.InitByRootLookup(); - ListValue return_args; - return_args.Append(root.GetDetailsAsValue()); - return JsArgList(&return_args); -} - -JsArgList SyncManager::SyncInternal::GetClientServerTraffic( - const JsArgList& args) { - ListValue return_args; - ListValue* value = traffic_recorder_.ToValue(); - if (value != NULL) - return_args.Append(value); - return JsArgList(&return_args); -} - -namespace { - -int64 GetId(const ListValue& ids, int i) { - std::string id_str; - if (!ids.GetString(i, &id_str)) { - return kInvalidId; - } - int64 id = kInvalidId; - if (!base::StringToInt64(id_str, &id)) { - return kInvalidId; - } - return id; -} - -JsArgList GetNodeInfoById(const JsArgList& args, - UserShare* user_share, - DictionaryValue* (BaseNode::*info_getter)() const) { - CHECK(info_getter); - ListValue return_args; - ListValue* node_summaries = new ListValue(); - return_args.Append(node_summaries); - ListValue* id_list = NULL; - ReadTransaction trans(FROM_HERE, user_share); - if (args.Get().GetList(0, &id_list)) { - CHECK(id_list); - for (size_t i = 0; i < id_list->GetSize(); ++i) { - int64 id = GetId(*id_list, i); - if (id == kInvalidId) { - continue; - } - ReadNode node(&trans); - if (node.InitByIdLookup(id) != sync_api::BaseNode::INIT_OK) { - continue; - } - node_summaries->Append((node.*info_getter)()); - } - } - return JsArgList(&return_args); -} - -} // namespace - -JsArgList SyncManager::SyncInternal::GetNodeSummariesById( - const JsArgList& args) { - return GetNodeInfoById(args, GetUserShare(), &BaseNode::GetSummaryAsValue); -} - -JsArgList SyncManager::SyncInternal::GetNodeDetailsById( - const JsArgList& args) { - return GetNodeInfoById(args, GetUserShare(), &BaseNode::GetDetailsAsValue); -} - -JsArgList SyncManager::SyncInternal::GetAllNodes( - const JsArgList& args) { - ListValue return_args; - ListValue* result = new ListValue(); - return_args.Append(result); - - ReadTransaction trans(FROM_HERE, GetUserShare()); - std::vector<const syncable::EntryKernel*> entry_kernels; - trans.GetDirectory()->GetAllEntryKernels(trans.GetWrappedTrans(), - &entry_kernels); - - for (std::vector<const syncable::EntryKernel*>::const_iterator it = - entry_kernels.begin(); it != entry_kernels.end(); ++it) { - result->Append((*it)->ToValue()); - } - - return JsArgList(&return_args); -} - -JsArgList SyncManager::SyncInternal::GetChildNodeIds( - const JsArgList& args) { - ListValue return_args; - ListValue* child_ids = new ListValue(); - return_args.Append(child_ids); - int64 id = GetId(args.Get(), 0); - if (id != kInvalidId) { - ReadTransaction trans(FROM_HERE, GetUserShare()); - syncable::Directory::ChildHandles child_handles; - trans.GetDirectory()->GetChildHandlesByHandle(trans.GetWrappedTrans(), - id, &child_handles); - for (syncable::Directory::ChildHandles::const_iterator it = - child_handles.begin(); it != child_handles.end(); ++it) { - child_ids->Append(Value::CreateStringValue( - base::Int64ToString(*it))); - } - } - return JsArgList(&return_args); -} - -void SyncManager::SyncInternal::OnEncryptedTypesChanged( - syncable::ModelTypeSet encrypted_types, - bool encrypt_everything) { - // NOTE: We're in a transaction. - FOR_EACH_OBSERVER( - SyncManager::Observer, observers_, - OnEncryptedTypesChanged(encrypted_types, encrypt_everything)); -} - -void SyncManager::SyncInternal::OnNotificationStateChange( - bool notifications_enabled) { - DVLOG(1) << "P2P: Notifications enabled = " - << (notifications_enabled ? "true" : "false"); - allstatus_.SetNotificationsEnabled(notifications_enabled); - if (scheduler()) { - scheduler()->set_notifications_enabled(notifications_enabled); - } - if (js_event_handler_.IsInitialized()) { - DictionaryValue details; - details.Set("enabled", Value::CreateBooleanValue(notifications_enabled)); - js_event_handler_.Call(FROM_HERE, - &JsEventHandler::HandleJsEvent, - "onNotificationStateChange", - JsEventDetails(&details)); - } -} - -void SyncManager::SyncInternal::UpdateNotificationInfo( - const syncable::ModelTypePayloadMap& type_payloads) { - for (syncable::ModelTypePayloadMap::const_iterator it = type_payloads.begin(); - it != type_payloads.end(); ++it) { - NotificationInfo* info = ¬ification_info_map_[it->first]; - info->total_count++; - info->payload = it->second; - } -} - -void SyncManager::SyncInternal::OnIncomingNotification( - const syncable::ModelTypePayloadMap& type_payloads, - sync_notifier::IncomingNotificationSource source) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (source == sync_notifier::LOCAL_NOTIFICATION) { - if (scheduler()) { - scheduler()->ScheduleNudgeWithPayloads( - TimeDelta::FromMilliseconds(kSyncRefreshDelayMsec), - browser_sync::NUDGE_SOURCE_LOCAL_REFRESH, - type_payloads, FROM_HERE); - } - } else if (!type_payloads.empty()) { - if (scheduler()) { - scheduler()->ScheduleNudgeWithPayloads( - TimeDelta::FromMilliseconds(kSyncSchedulerDelayMsec), - browser_sync::NUDGE_SOURCE_NOTIFICATION, - type_payloads, FROM_HERE); - } - allstatus_.IncrementNotificationsReceived(); - UpdateNotificationInfo(type_payloads); - debug_info_event_listener_.OnIncomingNotification(type_payloads); - } else { - LOG(WARNING) << "Sync received notification without any type information."; - } - - if (js_event_handler_.IsInitialized()) { - DictionaryValue details; - ListValue* changed_types = new ListValue(); - details.Set("changedTypes", changed_types); - for (syncable::ModelTypePayloadMap::const_iterator - it = type_payloads.begin(); - it != type_payloads.end(); ++it) { - const std::string& model_type_str = - syncable::ModelTypeToString(it->first); - changed_types->Append(Value::CreateStringValue(model_type_str)); - } - details.SetString("source", (source == sync_notifier::LOCAL_NOTIFICATION) ? - "LOCAL_NOTIFICATION" : "REMOTE_NOTIFICATION"); - js_event_handler_.Call(FROM_HERE, - &JsEventHandler::HandleJsEvent, - "onIncomingNotification", - JsEventDetails(&details)); - } -} - -void SyncManager::SyncInternal::StoreState( - const std::string& state) { - if (!directory()) { - LOG(ERROR) << "Could not write notification state"; - // TODO(akalin): Propagate result callback all the way to this - // function and call it with "false" to signal failure. - return; - } - if (VLOG_IS_ON(1)) { - std::string encoded_state; - base::Base64Encode(state, &encoded_state); - DVLOG(1) << "Writing notification state: " << encoded_state; - } - directory()->SetNotificationState(state); - directory()->SaveChanges(); -} - -void SyncManager::SyncInternal::AddObserver( - SyncManager::Observer* observer) { - observers_.AddObserver(observer); -} - -void SyncManager::SyncInternal::RemoveObserver( - SyncManager::Observer* observer) { - observers_.RemoveObserver(observer); -} - -SyncManager::Status SyncManager::GetDetailedStatus() const { - return data_->GetStatus(); -} - -void SyncManager::SaveChanges() { - DCHECK(thread_checker_.CalledOnValidThread()); - data_->SaveChanges(); -} - -void SyncManager::SyncInternal::SaveChanges() { - directory()->SaveChanges(); -} - -UserShare* SyncManager::GetUserShare() const { - return data_->GetUserShare(); -} - -void SyncManager::RefreshNigori(const std::string& chrome_version, - const base::Closure& done_callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - data_->UpdateCryptographerAndNigori( - chrome_version, - done_callback); -} - -TimeDelta SyncManager::GetNudgeDelayTimeDelta( - const ModelType& model_type) { - return data_->GetNudgeDelayTimeDelta(model_type); -} - -syncable::ModelTypeSet SyncManager::GetEncryptedDataTypesForTest() const { - ReadTransaction trans(FROM_HERE, GetUserShare()); - return GetEncryptedTypes(&trans); -} - -bool SyncManager::ReceivedExperimentalTypes(syncable::ModelTypeSet* to_add) - const { - ReadTransaction trans(FROM_HERE, GetUserShare()); - ReadNode node(&trans); - if (node.InitByTagLookup(kNigoriTag) != sync_api::BaseNode::INIT_OK) { - DVLOG(1) << "Couldn't find Nigori node."; - return false; - } - if (node.GetNigoriSpecifics().sync_tabs()) { - to_add->Put(syncable::SESSIONS); - return true; - } - return false; -} - -bool SyncManager::HasUnsyncedItems() const { - sync_api::ReadTransaction trans(FROM_HERE, GetUserShare()); - return (trans.GetWrappedTrans()->directory()->unsynced_entity_count() != 0); -} - -void SyncManager::TriggerOnNotificationStateChangeForTest( - bool notifications_enabled) { - DCHECK(thread_checker_.CalledOnValidThread()); - data_->OnNotificationStateChange(notifications_enabled); -} - -void SyncManager::TriggerOnIncomingNotificationForTest( - ModelTypeSet model_types) { - DCHECK(thread_checker_.CalledOnValidThread()); - syncable::ModelTypePayloadMap model_types_with_payloads = - syncable::ModelTypePayloadMapFromEnumSet(model_types, - std::string()); - - data_->OnIncomingNotification(model_types_with_payloads, - sync_notifier::REMOTE_NOTIFICATION); -} - -const char* ConnectionStatusToString(ConnectionStatus status) { - switch (status) { - case CONNECTION_OK: - return "CONNECTION_OK"; - case CONNECTION_AUTH_ERROR: - return "CONNECTION_AUTH_ERROR"; - case CONNECTION_SERVER_ERROR: - return "CONNECTION_SERVER_ERROR"; - default: - NOTREACHED(); - return "INVALID_CONNECTION_STATUS"; - } -} - -// Helper function that converts a PassphraseRequiredReason value to a string. -const char* PassphraseRequiredReasonToString( - PassphraseRequiredReason reason) { - switch (reason) { - case REASON_PASSPHRASE_NOT_REQUIRED: - return "REASON_PASSPHRASE_NOT_REQUIRED"; - case REASON_ENCRYPTION: - return "REASON_ENCRYPTION"; - case REASON_DECRYPTION: - return "REASON_DECRYPTION"; - default: - NOTREACHED(); - return "INVALID_REASON"; - } -} - -// Helper function to determine if initial sync had ended for types. -bool InitialSyncEndedForTypes(syncable::ModelTypeSet types, - sync_api::UserShare* share) { - for (syncable::ModelTypeSet::Iterator i = types.First(); - i.Good(); i.Inc()) { - if (!share->directory->initial_sync_ended_for_type(i.Get())) - return false; - } - return true; -} - -syncable::ModelTypeSet GetTypesWithEmptyProgressMarkerToken( - syncable::ModelTypeSet types, - sync_api::UserShare* share) { - syncable::ModelTypeSet result; - for (syncable::ModelTypeSet::Iterator i = types.First(); - i.Good(); i.Inc()) { - sync_pb::DataTypeProgressMarker marker; - share->directory->GetDownloadProgress(i.Get(), &marker); - - if (marker.token().empty()) - result.Put(i.Get()); - - } - return result; -} - -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/sync_manager.h b/chrome/browser/sync/internal_api/sync_manager.h deleted file mode 100644 index 488c727..0000000 --- a/chrome/browser/sync/internal_api/sync_manager.h +++ /dev/null @@ -1,644 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_SYNC_MANAGER_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_SYNC_MANAGER_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/callback_forward.h" -#include "base/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/task_runner.h" -#include "base/threading/thread_checker.h" -#include "base/time.h" -#include "chrome/browser/sync/internal_api/change_record.h" -#include "chrome/browser/sync/internal_api/configure_reason.h" -#include "sync/protocol/sync_protocol_error.h" -#include "sync/syncable/model_type.h" -#include "sync/util/report_unrecoverable_error_function.h" -#include "sync/util/unrecoverable_error_handler.h" -#include "sync/util/weak_handle.h" - -namespace browser_sync { -class Encryptor; -class ExtensionsActivityMonitor; -class JsBackend; -class JsEventHandler; -class ModelSafeWorkerRegistrar; - -namespace sessions { -struct SyncSessionSnapshot; -} // namespace sessions -} // namespace browser_sync - -namespace sync_notifier { -class SyncNotifier; -} // namespace sync_notifier - -namespace sync_pb { -class EncryptedData; -} // namespace sync_pb - -namespace sync_api { - -class BaseTransaction; -class HttpPostProviderFactory; -struct UserShare; - -// Used by SyncManager::OnConnectionStatusChange(). -enum ConnectionStatus { - CONNECTION_OK, - CONNECTION_AUTH_ERROR, - CONNECTION_SERVER_ERROR -}; - -// Reasons due to which browser_sync::Cryptographer might require a passphrase. -enum PassphraseRequiredReason { - REASON_PASSPHRASE_NOT_REQUIRED = 0, // Initial value. - REASON_ENCRYPTION = 1, // The cryptographer requires a - // passphrase for its first attempt at - // encryption. Happens only during - // migration or upgrade. - REASON_DECRYPTION = 2, // The cryptographer requires a - // passphrase for its first attempt at - // decryption. -}; - - -// Contains everything needed to talk to and identify a user account. -struct SyncCredentials { - std::string email; - std::string sync_token; -}; - -// SyncManager encapsulates syncable::Directory and serves as the parent of all -// other objects in the sync API. If multiple threads interact with the same -// local sync repository (i.e. the same sqlite database), they should share a -// single SyncManager instance. The caller should typically create one -// SyncManager for the lifetime of a user session. -// -// Unless stated otherwise, all methods of SyncManager should be called on the -// same thread. -class SyncManager { - public: - // SyncInternal contains the implementation of SyncManager, while abstracting - // internal types from clients of the interface. - class SyncInternal; - - // Status encapsulates detailed state about the internals of the SyncManager. - struct Status { - Status(); - ~Status(); - - bool notifications_enabled; // True only if subscribed for notifications. - - // Notifications counters updated by the actions in synapi. - int notifications_received; - - browser_sync::SyncProtocolError sync_protocol_error; - - // Number of unsynced items counted at the start of most recent sync cycle. - int unsynced_count; - - // Number of encryption conflicts counted during most recent sync cycle. - int encryption_conflicts; - - // Number of hierarchy conflicts counted during most recent sync cycle. - int hierarchy_conflicts; - - // Number of simple conflicts counted during most recent sync cycle. - int simple_conflicts; - - // Number of items the server refused to commit due to conflict during most - // recent sync cycle. - int server_conflicts; - - // Number of items successfully committed during most recent sync cycle. - int committed_count; - - bool syncing; - // True after a client has done a first sync. - bool initial_sync_ended; - - // Total updates available. If zero, nothing left to download. - int64 updates_available; - // Total updates received by the syncer since browser start. - int updates_received; - // Total updates received that are echoes of our own changes. - int reflected_updates_received; - - // Of updates_received, how many were tombstones. - int tombstone_updates_received; - - // Total number of overwrites due to conflict resolver since browser start. - int num_local_overwrites_total; - int num_server_overwrites_total; - - // Count of empty and non empty getupdates; - int nonempty_get_updates; - int empty_get_updates; - - // Count of sync cycles that successfully committed items; - int sync_cycles_with_commits; - int sync_cycles_without_commits; - - // Count of useless and useful syncs we perform. - int useless_sync_cycles; - int useful_sync_cycles; - - // Encryption related. - syncable::ModelTypeSet encrypted_types; - bool cryptographer_ready; - bool crypto_has_pending_keys; - - // The unique identifer for this client. - std::string unique_id; - }; - - // An interface the embedding application implements to be notified - // on change events. Note that these methods may be called on *any* - // thread. - class ChangeDelegate { - public: - // Notify the delegate that changes have been applied to the sync model. - // - // This will be invoked on the same thread as on which ApplyChanges was - // called. |changes| is an array of size |change_count|, and contains the - // ID of each individual item that was changed. |changes| exists only for - // the duration of the call. If items of multiple data types change at - // the same time, this method is invoked once per data type and |changes| - // is restricted to items of the ModelType indicated by |model_type|. - // Because the observer is passed a |trans|, the observer can assume a - // read lock on the sync model that will be released after the function - // returns. - // - // The SyncManager constructs |changes| in the following guaranteed order: - // - // 1. Deletions, from leaves up to parents. - // 2. Updates to existing items with synced parents & predecessors. - // 3. New items with synced parents & predecessors. - // 4. Items with parents & predecessors in |changes|. - // 5. Repeat #4 until all items are in |changes|. - // - // Thus, an implementation of OnChangesApplied should be able to - // process the change records in the order without having to worry about - // forward dependencies. But since deletions come before reparent - // operations, a delete may temporarily orphan a node that is - // updated later in the list. - virtual void OnChangesApplied( - syncable::ModelType model_type, - const BaseTransaction* trans, - const ImmutableChangeRecordList& changes) = 0; - - // OnChangesComplete gets called when the TransactionComplete event is - // posted (after OnChangesApplied finishes), after the transaction lock - // and the change channel mutex are released. - // - // The purpose of this function is to support processors that require - // split-transactions changes. For example, if a model processor wants to - // perform blocking I/O due to a change, it should calculate the changes - // while holding the transaction lock (from within OnChangesApplied), buffer - // those changes, let the transaction fall out of scope, and then commit - // those changes from within OnChangesComplete (postponing the blocking - // I/O to when it no longer holds any lock). - virtual void OnChangesComplete(syncable::ModelType model_type) = 0; - - protected: - virtual ~ChangeDelegate(); - }; - - // Like ChangeDelegate, except called only on the sync thread and - // not while a transaction is held. For objects that want to know - // when changes happen, but don't need to process them. - class ChangeObserver { - public: - // Ids referred to in |changes| may or may not be in the write - // transaction specified by |write_transaction_id|. If they're - // not, that means that the node didn't actually change, but we - // marked them as changed for some other reason (e.g., siblings of - // re-ordered nodes). - // - // TODO(sync, long-term): Ideally, ChangeDelegate/Observer would - // be passed a transformed version of EntryKernelMutation instead - // of a transaction that would have to be used to look up the - // changed nodes. That is, ChangeDelegate::OnChangesApplied() - // would still be called under the transaction, but all the needed - // data will be passed down. - // - // Even more ideally, we would have sync semantics such that we'd - // be able to apply changes without being under a transaction. - // But that's a ways off... - virtual void OnChangesApplied( - syncable::ModelType model_type, - int64 write_transaction_id, - const ImmutableChangeRecordList& changes) = 0; - - virtual void OnChangesComplete(syncable::ModelType model_type) = 0; - - protected: - virtual ~ChangeObserver(); - }; - - // An interface the embedding application implements to receive - // notifications from the SyncManager. Register an observer via - // SyncManager::AddObserver. All methods are called only on the - // sync thread. - class Observer { - public: - // A round-trip sync-cycle took place and the syncer has resolved any - // conflicts that may have arisen. - virtual void OnSyncCycleCompleted( - const browser_sync::sessions::SyncSessionSnapshot* snapshot) = 0; - - // Called when the status of the connection to the sync server has - // changed. - virtual void OnConnectionStatusChange(ConnectionStatus status) = 0; - - // Called when a new auth token is provided by the sync server. - virtual void OnUpdatedToken(const std::string& token) = 0; - - // Called when user interaction is required to obtain a valid passphrase. - // - If the passphrase is required for encryption, |reason| will be - // REASON_ENCRYPTION. - // - If the passphrase is required for the decryption of data that has - // already been encrypted, |reason| will be REASON_DECRYPTION. - // - If the passphrase is required because decryption failed, and a new - // passphrase is required, |reason| will be REASON_SET_PASSPHRASE_FAILED. - // - // |pending_keys| is a copy of the cryptographer's pending keys, that may be - // cached by the frontend for subsequent use by the UI. - virtual void OnPassphraseRequired( - PassphraseRequiredReason reason, - const sync_pb::EncryptedData& pending_keys) = 0; - - // Called when the passphrase provided by the user has been accepted and is - // now used to encrypt sync data. - virtual void OnPassphraseAccepted() = 0; - - // |bootstrap_token| is an opaque base64 encoded representation of the key - // generated by the current passphrase, and is provided to the observer for - // persistence purposes and use in a future initialization of sync (e.g. - // after restart). The boostrap token will always be derived from the most - // recent GAIA password (for accounts with implicit passphrases), even if - // the data is still encrypted with an older GAIA password. For accounts - // with explicit passphrases, it will be the most recently seen custom - // passphrase. - virtual void OnBootstrapTokenUpdated( - const std::string& bootstrap_token) = 0; - - // Called when initialization is complete to the point that SyncManager can - // process changes. This does not necessarily mean authentication succeeded - // or that the SyncManager is online. - // IMPORTANT: Creating any type of transaction before receiving this - // notification is illegal! - // WARNING: Calling methods on the SyncManager before receiving this - // message, unless otherwise specified, produces undefined behavior. - // - // |js_backend| is what about:sync interacts with. It can emit - // the following events: - - /** - * @param {{ enabled: boolean }} details A dictionary containing: - * - enabled: whether or not notifications are enabled. - */ - // function onNotificationStateChange(details); - - /** - * @param {{ changedTypes: Array.<string> }} details A dictionary - * containing: - * - changedTypes: a list of types (as strings) for which there - are new updates. - */ - // function onIncomingNotification(details); - - // Also, it responds to the following messages (all other messages - // are ignored): - - /** - * Gets the current notification state. - * - * @param {function(boolean)} callback Called with whether or not - * notifications are enabled. - */ - // function getNotificationState(callback); - - /** - * Gets details about the root node. - * - * @param {function(!Object)} callback Called with details about the - * root node. - */ - // TODO(akalin): Change this to getRootNodeId or eliminate it - // entirely. - // function getRootNodeDetails(callback); - - /** - * Gets summary information for a list of ids. - * - * @param {Array.<string>} idList List of 64-bit ids in decimal - * string form. - * @param {Array.<{id: string, title: string, isFolder: boolean}>} - * callback Called with summaries for the nodes in idList that - * exist. - */ - // function getNodeSummariesById(idList, callback); - - /** - * Gets detailed information for a list of ids. - * - * @param {Array.<string>} idList List of 64-bit ids in decimal - * string form. - * @param {Array.<!Object>} callback Called with detailed - * information for the nodes in idList that exist. - */ - // function getNodeDetailsById(idList, callback); - - /** - * Gets child ids for a given id. - * - * @param {string} id 64-bit id in decimal string form of the parent - * node. - * @param {Array.<string>} callback Called with the (possibly empty) - * list of child ids. - */ - // function getChildNodeIds(id); - - virtual void OnInitializationComplete( - const browser_sync::WeakHandle<browser_sync::JsBackend>& - js_backend, bool success) = 0; - - // We are no longer permitted to communicate with the server. Sync should - // be disabled and state cleaned up at once. This can happen for a number - // of reasons, e.g. swapping from a test instance to production, or a - // global stop syncing operation has wiped the store. - virtual void OnStopSyncingPermanently() = 0; - - // After a request to clear server data, these callbacks are invoked to - // indicate success or failure. - virtual void OnClearServerDataSucceeded() = 0; - virtual void OnClearServerDataFailed() = 0; - - // Called when the set of encrypted types or the encrypt - // everything flag has been changed. Note that encryption isn't - // complete until the OnEncryptionComplete() notification has been - // sent (see below). - // - // |encrypted_types| will always be a superset of - // Cryptographer::SensitiveTypes(). If |encrypt_everything| is - // true, |encrypted_types| will be the set of all known types. - // - // Until this function is called, observers can assume that the - // set of encrypted types is Cryptographer::SensitiveTypes() and - // that the encrypt everything flag is false. - // - // Called from within a transaction. - virtual void OnEncryptedTypesChanged( - syncable::ModelTypeSet encrypted_types, - bool encrypt_everything) = 0; - - // Called after we finish encrypting the current set of encrypted - // types. - // - // Called from within a transaction. - virtual void OnEncryptionComplete() = 0; - - virtual void OnActionableError( - const browser_sync::SyncProtocolError& sync_protocol_error) = 0; - - protected: - virtual ~Observer(); - }; - - enum TestingMode { - NON_TEST, - TEST_ON_DISK, - TEST_IN_MEMORY, - }; - - // Create an uninitialized SyncManager. Callers must Init() before using. - explicit SyncManager(const std::string& name); - virtual ~SyncManager(); - - // Initialize the sync manager. |database_location| specifies the path of - // the directory in which to locate a sqlite repository storing the syncer - // backend state. Initialization will open the database, or create it if it - // does not already exist. Returns false on failure. - // |event_handler| is the JsEventHandler used to propagate events to - // chrome://sync-internals. |event_handler| may be uninitialized. - // |sync_server_and_path| and |sync_server_port| represent the Chrome sync - // server to use, and |use_ssl| specifies whether to communicate securely; - // the default is false. - // |blocking_task_runner| is a TaskRunner to be used for tasks that - // may block on disk I/O. - // |post_factory| will be owned internally and used to create - // instances of an HttpPostProvider. - // |model_safe_worker| ownership is given to the SyncManager. - // |user_agent| is a 7-bit ASCII string suitable for use as the User-Agent - // HTTP header. Used internally when collecting stats to classify clients. - // |sync_notifier| is owned and used to listen for notifications. - // |report_unrecoverable_error_function| may be NULL. - bool Init(const FilePath& database_location, - const browser_sync::WeakHandle<browser_sync::JsEventHandler>& - event_handler, - const std::string& sync_server_and_path, - int sync_server_port, - bool use_ssl, - const scoped_refptr<base::TaskRunner>& blocking_task_runner, - HttpPostProviderFactory* post_factory, - browser_sync::ModelSafeWorkerRegistrar* registrar, - browser_sync::ExtensionsActivityMonitor* - extensions_activity_monitor, - ChangeDelegate* change_delegate, - const std::string& user_agent, - const SyncCredentials& credentials, - bool enable_sync_tabs_for_other_clients, - sync_notifier::SyncNotifier* sync_notifier, - const std::string& restored_key_for_bootstrapping, - TestingMode testing_mode, - browser_sync::Encryptor* encryptor, - browser_sync::UnrecoverableErrorHandler* - unrecoverable_error_handler, - browser_sync::ReportUnrecoverableErrorFunction - report_unrecoverable_error_function); - - // Throw an unrecoverable error from a transaction (mostly used for - // testing). - void ThrowUnrecoverableError(); - - // Check if the database has been populated with a full "initial" download of - // sync items for each data type currently present in the routing info. - // Prerequisite for calling this is that OnInitializationComplete has been - // called. May be called from any thread. - bool InitialSyncEndedForAllEnabledTypes(); - - // Update tokens that we're using in Sync. Email must stay the same. - void UpdateCredentials(const SyncCredentials& credentials); - - // Called when the user disables or enables a sync type. - void UpdateEnabledTypes(); - - // Conditionally sets the flag in the Nigori node which instructs other - // clients to start syncing tabs. - void MaybeSetSyncTabsInNigoriNode(syncable::ModelTypeSet enabled_types); - - // Put the syncer in normal mode ready to perform nudges and polls. - void StartSyncingNormally(); - - // Attempts to re-encrypt encrypted data types using the passphrase provided. - // Notifies observers of the result of the operation via OnPassphraseAccepted - // or OnPassphraseRequired, updates the nigori node, and does re-encryption as - // appropriate. If an explicit password has been set previously, we drop - // subsequent requests to set a passphrase. If the cryptographer has pending - // keys, and a new implicit passphrase is provided, we try decrypting the - // pending keys with it, and if that fails, we cache the passphrase for - // re-encryption once the pending keys are decrypted. - void SetEncryptionPassphrase(const std::string& passphrase, bool is_explicit); - - // Provides a passphrase for decrypting the user's existing sync data. - // Notifies observers of the result of the operation via OnPassphraseAccepted - // or OnPassphraseRequired, updates the nigori node, and does re-encryption as - // appropriate if there is a previously cached encryption passphrase. It is an - // error to call this when we don't have pending keys. - void SetDecryptionPassphrase(const std::string& passphrase); - - // Puts the SyncScheduler into a mode where no normal nudge or poll traffic - // will occur, but calls to RequestConfig will be supported. If |callback| - // is provided, it will be invoked (from the internal SyncScheduler) when - // the thread has changed to configuration mode. - void StartConfigurationMode(const base::Closure& callback); - - // Switches the mode of operation to CONFIGURATION_MODE and - // schedules a config task to fetch updates for |types|. - void RequestConfig(syncable::ModelTypeSet types, - sync_api::ConfigureReason reason); - - void RequestCleanupDisabledTypes(); - - // Request a clearing of all data on the server - void RequestClearServerData(); - - // Adds a listener to be notified of sync events. - // NOTE: It is OK (in fact, it's probably a good idea) to call this before - // having received OnInitializationCompleted. - void AddObserver(Observer* observer); - - // Remove the given observer. Make sure to call this if the - // Observer is being destroyed so the SyncManager doesn't - // potentially dereference garbage. - void RemoveObserver(Observer* observer); - - // Status-related getter. May be called on any thread. - Status GetDetailedStatus() const; - - // Whether or not the Nigori node is encrypted using an explicit passphrase. - // May be called on any thread. - bool IsUsingExplicitPassphrase(); - - // Call periodically from a database-safe thread to persist recent changes - // to the syncapi model. - void SaveChanges(); - - // Initiates shutdown of various components in the sync engine. Must be - // called from the main thread to allow preempting ongoing tasks on the sync - // loop (that may be blocked on I/O). The semantics of |callback| are the - // same as with StartConfigurationMode. If provided and a scheduler / sync - // loop exists, it will be invoked from the sync loop by the scheduler to - // notify that all work has been flushed + cancelled, and it is idle. - // If no scheduler exists, the callback is run immediately (from the loop - // this was created on, which is the sync loop), as sync is effectively - // stopped. - void StopSyncingForShutdown(const base::Closure& callback); - - // Issue a final SaveChanges, and close sqlite handles. - void ShutdownOnSyncThread(); - - // May be called from any thread. - UserShare* GetUserShare() const; - - // Inform the cryptographer of the most recent passphrase and set of - // encrypted types (from nigori node), then ensure all data that - // needs encryption is encrypted with the appropriate passphrase. - // - // May trigger OnPassphraseRequired(). Otherwise, it will trigger - // OnEncryptedTypesChanged() if necessary (see comments for - // OnEncryptedTypesChanged()), and then OnEncryptionComplete(). - // - // Also updates or adds device information to the nigori node. - // - // Note: opens a transaction, so must only be called after syncapi - // has been initialized. - void RefreshNigori(const std::string& chrome_version, - const base::Closure& done_callback); - - // Enable encryption of all sync data. Once enabled, it can never be - // disabled without clearing the server data. - // - // This will trigger OnEncryptedTypesChanged() if necessary (see - // comments for OnEncryptedTypesChanged()). It then may trigger - // OnPassphraseRequired(), but otherwise it will trigger - // OnEncryptionComplete(). - void EnableEncryptEverything(); - - // Returns true if we are currently encrypting all sync data. May - // be called on any thread. - bool EncryptEverythingEnabledForTest() const; - - // Gets the set of encrypted types from the cryptographer - // Note: opens a transaction. May be called from any thread. - syncable::ModelTypeSet GetEncryptedDataTypesForTest() const; - - // Reads the nigori node to determine if any experimental types should be - // enabled. - // Note: opens a transaction. May be called on any thread. - bool ReceivedExperimentalTypes(syncable::ModelTypeSet* to_add) const; - - // Uses a read-only transaction to determine if the directory being synced has - // any remaining unsynced items. May be called on any thread. - bool HasUnsyncedItems() const; - - // Functions used for testing. - - void TriggerOnNotificationStateChangeForTest( - bool notifications_enabled); - - void TriggerOnIncomingNotificationForTest( - syncable::ModelTypeSet model_types); - - static const int kDefaultNudgeDelayMilliseconds; - static const int kPreferencesNudgeDelayMilliseconds; - static const int kPiggybackNudgeDelay; - - static const FilePath::CharType kSyncDatabaseFilename[]; - - private: - FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, NudgeDelayTest); - - // For unit tests. - base::TimeDelta GetNudgeDelayTimeDelta(const syncable::ModelType& model_type); - - base::ThreadChecker thread_checker_; - - // An opaque pointer to the nested private class. - SyncInternal* data_; - - DISALLOW_COPY_AND_ASSIGN(SyncManager); -}; - -bool InitialSyncEndedForTypes(syncable::ModelTypeSet types, UserShare* share); - -syncable::ModelTypeSet GetTypesWithEmptyProgressMarkerToken( - syncable::ModelTypeSet types, - sync_api::UserShare* share); - -const char* ConnectionStatusToString(ConnectionStatus status); - -// Returns the string representation of a PassphraseRequiredReason value. -const char* PassphraseRequiredReasonToString(PassphraseRequiredReason reason); - -} // namespace sync_api - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_SYNC_MANAGER_H_ diff --git a/chrome/browser/sync/internal_api/syncapi_internal.cc b/chrome/browser/sync/internal_api/syncapi_internal.cc deleted file mode 100644 index 57279f8..0000000 --- a/chrome/browser/sync/internal_api/syncapi_internal.cc +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/syncapi_internal.h" - -#include "base/memory/scoped_ptr.h" -#include "sync/protocol/password_specifics.pb.h" -#include "sync/protocol/sync.pb.h" -#include "sync/util/cryptographer.h" - -using browser_sync::Cryptographer; - -namespace sync_api { - -sync_pb::PasswordSpecificsData* DecryptPasswordSpecifics( - const sync_pb::EntitySpecifics& specifics, Cryptographer* crypto) { - if (!specifics.has_password()) - return NULL; - const sync_pb::PasswordSpecifics& password_specifics = specifics.password(); - if (!password_specifics.has_encrypted()) - return NULL; - const sync_pb::EncryptedData& encrypted = password_specifics.encrypted(); - scoped_ptr<sync_pb::PasswordSpecificsData> data( - new sync_pb::PasswordSpecificsData); - if (!crypto->Decrypt(encrypted, data.get())) - return NULL; - return data.release(); -} - -// The list of names which are reserved for use by the server. -static const char* kForbiddenServerNames[] = { "", ".", ".." }; - -// When taking a name from the syncapi, append a space if it matches the -// pattern of a server-illegal name followed by zero or more spaces. -void SyncAPINameToServerName(const std::string& sync_api_name, - std::string* out) { - *out = sync_api_name; - if (IsNameServerIllegalAfterTrimming(*out)) - out->append(" "); -} - -// Checks whether |name| is a server-illegal name followed by zero or more space -// characters. The three server-illegal names are the empty string, dot, and -// dot-dot. Very long names (>255 bytes in UTF-8 Normalization Form C) are -// also illegal, but are not considered here. -bool IsNameServerIllegalAfterTrimming(const std::string& name) { - size_t untrimmed_count = name.find_last_not_of(' ') + 1; - for (size_t i = 0; i < arraysize(kForbiddenServerNames); ++i) { - if (name.compare(0, untrimmed_count, kForbiddenServerNames[i]) == 0) - return true; - } - return false; -} - -// Compare the values of two EntitySpecifics, accounting for encryption. -bool AreSpecificsEqual(const browser_sync::Cryptographer* cryptographer, - const sync_pb::EntitySpecifics& left, - const sync_pb::EntitySpecifics& right) { - // Note that we can't compare encrypted strings directly as they are seeded - // with a random value. - std::string left_plaintext, right_plaintext; - if (left.has_encrypted()) { - if (!cryptographer->CanDecrypt(left.encrypted())) { - NOTREACHED() << "Attempting to compare undecryptable data."; - return false; - } - left_plaintext = cryptographer->DecryptToString(left.encrypted()); - } else { - left_plaintext = left.SerializeAsString(); - } - if (right.has_encrypted()) { - if (!cryptographer->CanDecrypt(right.encrypted())) { - NOTREACHED() << "Attempting to compare undecryptable data."; - return false; - } - right_plaintext = cryptographer->DecryptToString(right.encrypted()); - } else { - right_plaintext = right.SerializeAsString(); - } - if (left_plaintext == right_plaintext) { - return true; - } - return false; -} - -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/syncapi_internal.h b/chrome/browser/sync/internal_api/syncapi_internal.h deleted file mode 100644 index ffd2d4e..0000000 --- a/chrome/browser/sync/internal_api/syncapi_internal.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_SYNCAPI_INTERNAL_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_SYNCAPI_INTERNAL_H_ - -// The functions defined are shared among some of the classes that implement -// the internal sync_api. They are not to be used by clients of the API. - -#include <string> - -namespace browser_sync { -class Cryptographer; -} - -namespace sync_pb { -class EntitySpecifics; -class PasswordSpecificsData; -} - -namespace sync_api { -sync_pb::PasswordSpecificsData* DecryptPasswordSpecifics( - const sync_pb::EntitySpecifics& specifics, - browser_sync::Cryptographer* crypto); - -void SyncAPINameToServerName(const std::string& sync_api_name, - std::string* out); - -bool IsNameServerIllegalAfterTrimming(const std::string& name); - -bool AreSpecificsEqual(const browser_sync::Cryptographer* cryptographer, - const sync_pb::EntitySpecifics& left, - const sync_pb::EntitySpecifics& right); -} - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_SYNCAPI_INTERNAL_H_ diff --git a/chrome/browser/sync/internal_api/syncapi_server_connection_manager.cc b/chrome/browser/sync/internal_api/syncapi_server_connection_manager.cc deleted file mode 100644 index 2de56a4..0000000 --- a/chrome/browser/sync/internal_api/syncapi_server_connection_manager.cc +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/syncapi_server_connection_manager.h" - -#include "chrome/browser/sync/internal_api/http_post_provider_factory.h" -#include "chrome/browser/sync/internal_api/http_post_provider_interface.h" -#include "net/base/net_errors.h" -#include "net/http/http_status_code.h" - -using browser_sync::HttpResponse; - -namespace sync_api { - -SyncAPIBridgedConnection::SyncAPIBridgedConnection( - browser_sync::ServerConnectionManager* scm, - HttpPostProviderFactory* factory) - : Connection(scm), factory_(factory) { - post_provider_ = factory_->Create(); -} - -SyncAPIBridgedConnection::~SyncAPIBridgedConnection() { - DCHECK(post_provider_); - factory_->Destroy(post_provider_); - post_provider_ = NULL; -} - -bool SyncAPIBridgedConnection::Init(const char* path, - const std::string& auth_token, - const std::string& payload, - HttpResponse* response) { - std::string sync_server; - int sync_server_port = 0; - bool use_ssl = false; - GetServerParams(&sync_server, &sync_server_port, &use_ssl); - std::string connection_url = MakeConnectionURL(sync_server, path, use_ssl); - - HttpPostProviderInterface* http = post_provider_; - http->SetUserAgent(scm_->user_agent().c_str()); - http->SetURL(connection_url.c_str(), sync_server_port); - - if (!auth_token.empty()) { - const std::string& headers = - "Authorization: GoogleLogin auth=" + auth_token; - http->SetExtraRequestHeaders(headers.c_str()); - } - - // Must be octet-stream, or the payload may be parsed for a cookie. - http->SetPostPayload("application/octet-stream", payload.length(), - payload.data()); - - // Issue the POST, blocking until it finishes. - int error_code = 0; - int response_code = 0; - if (!http->MakeSynchronousPost(&error_code, &response_code)) { - DVLOG(1) << "Http POST failed, error returns: " << error_code; - response->server_status = error_code == net::ERR_ABORTED ? - HttpResponse::CONNECTION_UNAVAILABLE : HttpResponse::IO_ERROR; - return false; - } - - // We got a server response, copy over response codes and content. - response->response_code = response_code; - response->content_length = - static_cast<int64>(http->GetResponseContentLength()); - response->payload_length = - static_cast<int64>(http->GetResponseContentLength()); - if (response->response_code < 400) - response->server_status = HttpResponse::SERVER_CONNECTION_OK; - else if (response->response_code == net::HTTP_UNAUTHORIZED) - response->server_status = HttpResponse::SYNC_AUTH_ERROR; - else - response->server_status = HttpResponse::SYNC_SERVER_ERROR; - - response->update_client_auth_header = - http->GetResponseHeaderValue("Update-Client-Auth"); - - // Write the content into our buffer. - buffer_.assign(http->GetResponseContent(), http->GetResponseContentLength()); - return true; -} - -void SyncAPIBridgedConnection::Abort() { - DCHECK(post_provider_); - post_provider_->Abort(); -} - -SyncAPIServerConnectionManager::SyncAPIServerConnectionManager( - const std::string& server, - int port, - bool use_ssl, - const std::string& client_version, - HttpPostProviderFactory* factory) - : ServerConnectionManager(server, port, use_ssl, client_version), - post_provider_factory_(factory) { - DCHECK(post_provider_factory_.get()); -} - -SyncAPIServerConnectionManager::~SyncAPIServerConnectionManager() {} - -browser_sync::ServerConnectionManager::Connection* -SyncAPIServerConnectionManager::MakeConnection() { - return new SyncAPIBridgedConnection(this, post_provider_factory_.get()); -} - -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/syncapi_server_connection_manager.h b/chrome/browser/sync/internal_api/syncapi_server_connection_manager.h deleted file mode 100644 index 181b0b2..0000000 --- a/chrome/browser/sync/internal_api/syncapi_server_connection_manager.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_SYNCAPI_SERVER_CONNECTION_MANAGER_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_SYNCAPI_SERVER_CONNECTION_MANAGER_H_ -#pragma once - -#include <string> - -#include "base/compiler_specific.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "sync/engine/net/server_connection_manager.h" - -namespace sync_api { - -class HttpPostProviderFactory; -class HttpPostProviderInterface; - -// This provides HTTP Post functionality through the interface provided -// to the sync API by the application hosting the syncer backend. -class SyncAPIBridgedConnection - : public browser_sync::ServerConnectionManager::Connection { - public: - SyncAPIBridgedConnection(browser_sync::ServerConnectionManager* scm, - HttpPostProviderFactory* factory); - - virtual ~SyncAPIBridgedConnection(); - - virtual bool Init(const char* path, - const std::string& auth_token, - const std::string& payload, - browser_sync::HttpResponse* response) OVERRIDE; - - virtual void Abort() OVERRIDE; - - private: - // Pointer to the factory we use for creating HttpPostProviders. We do not - // own |factory_|. - HttpPostProviderFactory* factory_; - - HttpPostProviderInterface* post_provider_; - - DISALLOW_COPY_AND_ASSIGN(SyncAPIBridgedConnection); -}; - -// A ServerConnectionManager subclass used by the syncapi layer. We use a -// subclass so that we can override MakePost() to generate a POST object using -// an instance of the HttpPostProviderFactory class. -class SyncAPIServerConnectionManager - : public browser_sync::ServerConnectionManager { - public: - // Takes ownership of factory. - SyncAPIServerConnectionManager(const std::string& server, - int port, - bool use_ssl, - const std::string& client_version, - HttpPostProviderFactory* factory); - virtual ~SyncAPIServerConnectionManager(); - - // ServerConnectionManager overrides. - virtual Connection* MakeConnection() OVERRIDE; - - private: - FRIEND_TEST_ALL_PREFIXES(SyncAPIServerConnectionManagerTest, EarlyAbortPost); - FRIEND_TEST_ALL_PREFIXES(SyncAPIServerConnectionManagerTest, AbortPost); - - // A factory creating concrete HttpPostProviders for use whenever we need to - // issue a POST to sync servers. - scoped_ptr<HttpPostProviderFactory> post_provider_factory_; - - DISALLOW_COPY_AND_ASSIGN(SyncAPIServerConnectionManager); -}; - -} // namespace sync_api - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_SYNCAPI_SERVER_CONNECTION_MANAGER_H_ diff --git a/chrome/browser/sync/internal_api/syncapi_server_connection_manager_unittest.cc b/chrome/browser/sync/internal_api/syncapi_server_connection_manager_unittest.cc deleted file mode 100644 index 720b574..0000000 --- a/chrome/browser/sync/internal_api/syncapi_server_connection_manager_unittest.cc +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/syncapi_server_connection_manager.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/compiler_specific.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/test_timeouts.h" -#include "base/threading/thread.h" -#include "base/time.h" -#include "chrome/browser/sync/internal_api/http_post_provider_factory.h" -#include "chrome/browser/sync/internal_api/http_post_provider_interface.h" -#include "net/base/net_errors.h" -#include "testing/gtest/include/gtest/gtest.h" - -using base::TimeDelta; -using browser_sync::HttpResponse; -using browser_sync::ServerConnectionManager; -using browser_sync::ScopedServerStatusWatcher; - -namespace sync_api { -namespace { - -class BlockingHttpPost : public HttpPostProviderInterface { - public: - BlockingHttpPost() : wait_for_abort_(false, false) {} - virtual ~BlockingHttpPost() {} - - virtual void SetUserAgent(const char* user_agent) OVERRIDE {} - virtual void SetExtraRequestHeaders(const char* headers) OVERRIDE {} - virtual void SetURL(const char* url, int port) OVERRIDE {} - virtual void SetPostPayload(const char* content_type, - int content_length, - const char* content) OVERRIDE {} - virtual bool MakeSynchronousPost(int* error_code, int* response_code) - OVERRIDE { - wait_for_abort_.TimedWait(TimeDelta::FromMilliseconds( - TestTimeouts::action_max_timeout_ms())); - *error_code = net::ERR_ABORTED; - return false; - } - virtual int GetResponseContentLength() const OVERRIDE { - return 0; - } - virtual const char* GetResponseContent() const OVERRIDE { - return ""; - } - virtual const std::string GetResponseHeaderValue( - const std::string& name) const OVERRIDE { - return ""; - } - virtual void Abort() OVERRIDE { - wait_for_abort_.Signal(); - } - private: - base::WaitableEvent wait_for_abort_; -}; - -class BlockingHttpPostFactory : public HttpPostProviderFactory { - public: - virtual ~BlockingHttpPostFactory() {} - virtual HttpPostProviderInterface* Create() OVERRIDE { - return new BlockingHttpPost(); - } - virtual void Destroy(HttpPostProviderInterface* http) OVERRIDE { - delete http; - } -}; - -} // namespace - -TEST(SyncAPIServerConnectionManagerTest, EarlyAbortPost) { - SyncAPIServerConnectionManager server( - "server", 0, true, "1", new BlockingHttpPostFactory()); - - ServerConnectionManager::PostBufferParams params; - ScopedServerStatusWatcher watcher(&server, ¶ms.response); - - server.TerminateAllIO(); - bool result = server.PostBufferToPath( - ¶ms, "/testpath", "testauth", &watcher); - - EXPECT_FALSE(result); - EXPECT_EQ(HttpResponse::CONNECTION_UNAVAILABLE, - params.response.server_status); -} - -TEST(SyncAPIServerConnectionManagerTest, AbortPost) { - SyncAPIServerConnectionManager server( - "server", 0, true, "1", new BlockingHttpPostFactory()); - - ServerConnectionManager::PostBufferParams params; - ScopedServerStatusWatcher watcher(&server, ¶ms.response); - - base::Thread abort_thread("Test_AbortThread"); - ASSERT_TRUE(abort_thread.Start()); - abort_thread.message_loop()->PostDelayedTask( - FROM_HERE, - base::Bind(&ServerConnectionManager::TerminateAllIO, - base::Unretained(&server)), - TestTimeouts::tiny_timeout()); - - bool result = server.PostBufferToPath( - ¶ms, "/testpath", "testauth", &watcher); - - EXPECT_FALSE(result); - EXPECT_EQ(HttpResponse::CONNECTION_UNAVAILABLE, - params.response.server_status); - abort_thread.Stop(); -} - -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/syncapi_unittest.cc b/chrome/browser/sync/internal_api/syncapi_unittest.cc deleted file mode 100644 index 2464dcb..0000000 --- a/chrome/browser/sync/internal_api/syncapi_unittest.cc +++ /dev/null @@ -1,2519 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Unit tests for the SyncApi. Note that a lot of the underlying -// functionality is provided by the Syncable layer, which has its own -// unit tests. We'll test SyncApi specific things in this harness. - -#include <cstddef> -#include <map> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/format_macros.h" -#include "base/location.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop.h" -#include "base/message_loop_proxy.h" -#include "base/scoped_temp_dir.h" -#include "base/string_number_conversions.h" -#include "base/stringprintf.h" -#include "base/test/values_test_util.h" -#include "base/utf_string_conversions.h" -#include "base/values.h" -#include "chrome/browser/sync/internal_api/change_record.h" -#include "chrome/browser/sync/internal_api/http_post_provider_factory.h" -#include "chrome/browser/sync/internal_api/http_post_provider_interface.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/sync_manager.h" -#include "chrome/browser/sync/internal_api/syncapi_internal.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" -#include "chrome/browser/sync/test/engine/test_user_share.h" -#include "sync/engine/model_safe_worker.h" -#include "sync/engine/nigori_util.h" -#include "sync/engine/polling_constants.h" -#include "sync/js/js_arg_list.h" -#include "sync/js/js_backend.h" -#include "sync/js/js_event_handler.h" -#include "sync/js/js_reply_handler.h" -#include "sync/js/js_test_util.h" -#include "sync/notifier/sync_notifier.h" -#include "sync/notifier/sync_notifier_observer.h" -#include "sync/protocol/bookmark_specifics.pb.h" -#include "sync/protocol/encryption.pb.h" -#include "sync/protocol/extension_specifics.pb.h" -#include "sync/protocol/password_specifics.pb.h" -#include "sync/protocol/preference_specifics.pb.h" -#include "sync/protocol/proto_value_conversions.h" -#include "sync/protocol/sync.pb.h" -#include "sync/sessions/sync_session.h" -#include "sync/syncable/model_type_test_util.h" -#include "sync/syncable/syncable.h" -#include "sync/syncable/syncable_id.h" -#include "sync/test/fake_encryptor.h" -#include "sync/test/fake_extensions_activity_monitor.h" -#include "sync/util/cryptographer.h" -#include "sync/util/extensions_activity_monitor.h" -#include "sync/util/test_unrecoverable_error_handler.h" -#include "sync/util/time.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using base::ExpectDictStringValue; -using browser_sync::Cryptographer; -using browser_sync::FakeEncryptor; -using browser_sync::FakeExtensionsActivityMonitor; -using browser_sync::HasArgsAsList; -using browser_sync::HasDetailsAsDictionary; -using browser_sync::KeyParams; -using browser_sync::kNigoriTag; -using browser_sync::JsArgList; -using browser_sync::JsBackend; -using browser_sync::JsEventHandler; -using browser_sync::JsReplyHandler; -using browser_sync::MockJsEventHandler; -using browser_sync::MockJsReplyHandler; -using browser_sync::ModelSafeRoutingInfo; -using browser_sync::ModelSafeWorker; -using browser_sync::ModelSafeWorkerRegistrar; -using browser_sync::sessions::SyncSessionSnapshot; -using browser_sync::TestUnrecoverableErrorHandler; -using browser_sync::WeakHandle; -using syncable::IS_DEL; -using syncable::IS_UNSYNCED; -using syncable::kEncryptedString; -using syncable::ModelTypeSet; -using syncable::ModelType; -using syncable::NON_UNIQUE_NAME; -using syncable::SPECIFICS; -using testing::_; -using testing::AnyNumber; -using testing::AtLeast; -using testing::InSequence; -using testing::Invoke; -using testing::SaveArg; -using testing::StrictMock; - -namespace sync_api { - -namespace { - -const char kTestChromeVersion[] = "test chrome version"; - -void DoNothing() {} - -void ExpectInt64Value(int64 expected_value, - const DictionaryValue& value, const std::string& key) { - std::string int64_str; - EXPECT_TRUE(value.GetString(key, &int64_str)); - int64 val = 0; - EXPECT_TRUE(base::StringToInt64(int64_str, &val)); - EXPECT_EQ(expected_value, val); -} - -void ExpectTimeValue(const base::Time& expected_value, - const DictionaryValue& value, const std::string& key) { - std::string time_str; - EXPECT_TRUE(value.GetString(key, &time_str)); - EXPECT_EQ(browser_sync::GetTimeDebugString(expected_value), time_str); -} - -// Makes a non-folder child of the root node. Returns the id of the -// newly-created node. -int64 MakeNode(UserShare* share, - ModelType model_type, - const std::string& client_tag) { - WriteTransaction trans(FROM_HERE, share); - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - WriteNode node(&trans); - EXPECT_TRUE(node.InitUniqueByCreation(model_type, root_node, client_tag)); - node.SetIsFolder(false); - return node.GetId(); -} - -// Makes a non-folder child of a non-root node. Returns the id of the -// newly-created node. -int64 MakeNodeWithParent(UserShare* share, - ModelType model_type, - const std::string& client_tag, - int64 parent_id) { - WriteTransaction trans(FROM_HERE, share); - ReadNode parent_node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, parent_node.InitByIdLookup(parent_id)); - WriteNode node(&trans); - EXPECT_TRUE(node.InitUniqueByCreation(model_type, parent_node, client_tag)); - node.SetIsFolder(false); - return node.GetId(); -} - -// Makes a folder child of a non-root node. Returns the id of the -// newly-created node. -int64 MakeFolderWithParent(UserShare* share, - ModelType model_type, - int64 parent_id, - BaseNode* predecessor) { - WriteTransaction trans(FROM_HERE, share); - ReadNode parent_node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, parent_node.InitByIdLookup(parent_id)); - WriteNode node(&trans); - EXPECT_TRUE(node.InitByCreation(model_type, parent_node, predecessor)); - node.SetIsFolder(true); - return node.GetId(); -} - -// Creates the "synced" root node for a particular datatype. We use the syncable -// methods here so that the syncer treats these nodes as if they were already -// received from the server. -int64 MakeServerNodeForType(UserShare* share, - ModelType model_type) { - sync_pb::EntitySpecifics specifics; - syncable::AddDefaultFieldValue(model_type, &specifics); - syncable::WriteTransaction trans( - FROM_HERE, syncable::UNITTEST, share->directory.get()); - // Attempt to lookup by nigori tag. - std::string type_tag = syncable::ModelTypeToRootTag(model_type); - syncable::Id node_id = syncable::Id::CreateFromServerId(type_tag); - syncable::MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM, - node_id); - EXPECT_TRUE(entry.good()); - entry.Put(syncable::BASE_VERSION, 1); - entry.Put(syncable::SERVER_VERSION, 1); - entry.Put(syncable::IS_UNAPPLIED_UPDATE, false); - entry.Put(syncable::SERVER_PARENT_ID, syncable::GetNullId()); - entry.Put(syncable::SERVER_IS_DIR, true); - entry.Put(syncable::IS_DIR, true); - entry.Put(syncable::SERVER_SPECIFICS, specifics); - entry.Put(syncable::UNIQUE_SERVER_TAG, type_tag); - entry.Put(syncable::NON_UNIQUE_NAME, type_tag); - entry.Put(syncable::IS_DEL, false); - entry.Put(syncable::SPECIFICS, specifics); - return entry.Get(syncable::META_HANDLE); -} - -// Simulates creating a "synced" node as a child of the root datatype node. -int64 MakeServerNode(UserShare* share, ModelType model_type, - const std::string& client_tag, - const std::string& hashed_tag, - const sync_pb::EntitySpecifics& specifics) { - syncable::WriteTransaction trans( - FROM_HERE, syncable::UNITTEST, share->directory.get()); - syncable::Entry root_entry(&trans, syncable::GET_BY_SERVER_TAG, - syncable::ModelTypeToRootTag(model_type)); - EXPECT_TRUE(root_entry.good()); - syncable::Id root_id = root_entry.Get(syncable::ID); - syncable::Id node_id = syncable::Id::CreateFromServerId(client_tag); - syncable::MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM, - node_id); - EXPECT_TRUE(entry.good()); - entry.Put(syncable::BASE_VERSION, 1); - entry.Put(syncable::SERVER_VERSION, 1); - entry.Put(syncable::IS_UNAPPLIED_UPDATE, false); - entry.Put(syncable::SERVER_PARENT_ID, root_id); - entry.Put(syncable::PARENT_ID, root_id); - entry.Put(syncable::SERVER_IS_DIR, false); - entry.Put(syncable::IS_DIR, false); - entry.Put(syncable::SERVER_SPECIFICS, specifics); - entry.Put(syncable::NON_UNIQUE_NAME, client_tag); - entry.Put(syncable::UNIQUE_CLIENT_TAG, hashed_tag); - entry.Put(syncable::IS_DEL, false); - entry.Put(syncable::SPECIFICS, specifics); - return entry.Get(syncable::META_HANDLE); -} - -} // namespace - -class SyncApiTest : public testing::Test { - public: - virtual void SetUp() { - test_user_share_.SetUp(); - } - - virtual void TearDown() { - test_user_share_.TearDown(); - } - - protected: - MessageLoop message_loop_; - browser_sync::TestUserShare test_user_share_; -}; - -TEST_F(SyncApiTest, SanityCheckTest) { - { - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - EXPECT_TRUE(trans.GetWrappedTrans() != NULL); - } - { - WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); - EXPECT_TRUE(trans.GetWrappedTrans() != NULL); - } - { - // No entries but root should exist - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode node(&trans); - // Metahandle 1 can be root, sanity check 2 - EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_NOT_GOOD, node.InitByIdLookup(2)); - } -} - -TEST_F(SyncApiTest, BasicTagWrite) { - { - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - EXPECT_EQ(root_node.GetFirstChildId(), 0); - } - - ignore_result(MakeNode(test_user_share_.user_share(), - syncable::BOOKMARKS, "testtag")); - - { - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, "testtag")); - - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - EXPECT_NE(node.GetId(), 0); - EXPECT_EQ(node.GetId(), root_node.GetFirstChildId()); - } -} - -TEST_F(SyncApiTest, GenerateSyncableHash) { - EXPECT_EQ("OyaXV5mEzrPS4wbogmtKvRfekAI=", - BaseNode::GenerateSyncableHash(syncable::BOOKMARKS, "tag1")); - EXPECT_EQ("iNFQtRFQb+IZcn1kKUJEZDDkLs4=", - BaseNode::GenerateSyncableHash(syncable::PREFERENCES, "tag1")); - EXPECT_EQ("gO1cPZQXaM73sHOvSA+tKCKFs58=", - BaseNode::GenerateSyncableHash(syncable::AUTOFILL, "tag1")); - - EXPECT_EQ("A0eYIHXM1/jVwKDDp12Up20IkKY=", - BaseNode::GenerateSyncableHash(syncable::BOOKMARKS, "tag2")); - EXPECT_EQ("XYxkF7bhS4eItStFgiOIAU23swI=", - BaseNode::GenerateSyncableHash(syncable::PREFERENCES, "tag2")); - EXPECT_EQ("GFiWzo5NGhjLlN+OyCfhy28DJTQ=", - BaseNode::GenerateSyncableHash(syncable::AUTOFILL, "tag2")); -} - -TEST_F(SyncApiTest, ModelTypesSiloed) { - { - WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - EXPECT_EQ(root_node.GetFirstChildId(), 0); - } - - ignore_result(MakeNode(test_user_share_.user_share(), - syncable::BOOKMARKS, "collideme")); - ignore_result(MakeNode(test_user_share_.user_share(), - syncable::PREFERENCES, "collideme")); - ignore_result(MakeNode(test_user_share_.user_share(), - syncable::AUTOFILL, "collideme")); - - { - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - - ReadNode bookmarknode(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - bookmarknode.InitByClientTagLookup(syncable::BOOKMARKS, - "collideme")); - - ReadNode prefnode(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - prefnode.InitByClientTagLookup(syncable::PREFERENCES, - "collideme")); - - ReadNode autofillnode(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - autofillnode.InitByClientTagLookup(syncable::AUTOFILL, - "collideme")); - - EXPECT_NE(bookmarknode.GetId(), prefnode.GetId()); - EXPECT_NE(autofillnode.GetId(), prefnode.GetId()); - EXPECT_NE(bookmarknode.GetId(), autofillnode.GetId()); - } -} - -TEST_F(SyncApiTest, ReadMissingTagsFails) { - { - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_NOT_GOOD, - node.InitByClientTagLookup(syncable::BOOKMARKS, - "testtag")); - } - { - WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_NOT_GOOD, - node.InitByClientTagLookup(syncable::BOOKMARKS, - "testtag")); - } -} - -// TODO(chron): Hook this all up to the server and write full integration tests -// for update->undelete behavior. -TEST_F(SyncApiTest, TestDeleteBehavior) { - int64 node_id; - int64 folder_id; - std::string test_title("test1"); - - { - WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - - // we'll use this spare folder later - WriteNode folder_node(&trans); - EXPECT_TRUE(folder_node.InitByCreation(syncable::BOOKMARKS, - root_node, NULL)); - folder_id = folder_node.GetId(); - - WriteNode wnode(&trans); - EXPECT_TRUE(wnode.InitUniqueByCreation(syncable::BOOKMARKS, - root_node, "testtag")); - wnode.SetIsFolder(false); - wnode.SetTitle(UTF8ToWide(test_title)); - - node_id = wnode.GetId(); - } - - // Ensure we can delete something with a tag. - { - WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); - WriteNode wnode(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - wnode.InitByClientTagLookup(syncable::BOOKMARKS, - "testtag")); - EXPECT_FALSE(wnode.GetIsFolder()); - EXPECT_EQ(wnode.GetTitle(), test_title); - - wnode.Remove(); - } - - // Lookup of a node which was deleted should return failure, - // but have found some data about the node. - { - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_IS_DEL, - node.InitByClientTagLookup(syncable::BOOKMARKS, - "testtag")); - // Note that for proper function of this API this doesn't need to be - // filled, we're checking just to make sure the DB worked in this test. - EXPECT_EQ(node.GetTitle(), test_title); - } - - { - WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode folder_node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, folder_node.InitByIdLookup(folder_id)); - - WriteNode wnode(&trans); - // This will undelete the tag. - EXPECT_TRUE(wnode.InitUniqueByCreation(syncable::BOOKMARKS, - folder_node, "testtag")); - EXPECT_EQ(wnode.GetIsFolder(), false); - EXPECT_EQ(wnode.GetParentId(), folder_node.GetId()); - EXPECT_EQ(wnode.GetId(), node_id); - EXPECT_NE(wnode.GetTitle(), test_title); // Title should be cleared - wnode.SetTitle(UTF8ToWide(test_title)); - } - - // Now look up should work. - { - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, - "testtag")); - EXPECT_EQ(node.GetTitle(), test_title); - EXPECT_EQ(node.GetModelType(), syncable::BOOKMARKS); - } -} - -TEST_F(SyncApiTest, WriteAndReadPassword) { - KeyParams params = {"localhost", "username", "passphrase"}; - { - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - trans.GetCryptographer()->AddKey(params); - } - { - WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - - WriteNode password_node(&trans); - EXPECT_TRUE(password_node.InitUniqueByCreation(syncable::PASSWORDS, - root_node, "foo")); - sync_pb::PasswordSpecificsData data; - data.set_password_value("secret"); - password_node.SetPasswordSpecifics(data); - } - { - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - - ReadNode password_node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - password_node.InitByClientTagLookup(syncable::PASSWORDS, - "foo")); - const sync_pb::PasswordSpecificsData& data = - password_node.GetPasswordSpecifics(); - EXPECT_EQ("secret", data.password_value()); - } -} - -TEST_F(SyncApiTest, WriteEncryptedTitle) { - KeyParams params = {"localhost", "username", "passphrase"}; - { - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - trans.GetCryptographer()->AddKey(params); - trans.GetCryptographer()->set_encrypt_everything(); - } - { - WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - - WriteNode bookmark_node(&trans); - EXPECT_TRUE(bookmark_node.InitUniqueByCreation(syncable::BOOKMARKS, - root_node, "foo")); - bookmark_node.SetTitle(UTF8ToWide("foo")); - - WriteNode pref_node(&trans); - EXPECT_TRUE(pref_node.InitUniqueByCreation(syncable::PREFERENCES, - root_node, "bar")); - pref_node.SetTitle(UTF8ToWide("bar")); - } - { - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - - ReadNode bookmark_node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - bookmark_node.InitByClientTagLookup(syncable::BOOKMARKS, - "foo")); - EXPECT_EQ("foo", bookmark_node.GetTitle()); - EXPECT_EQ(kEncryptedString, - bookmark_node.GetEntry()->Get(syncable::NON_UNIQUE_NAME)); - - ReadNode pref_node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - pref_node.InitByClientTagLookup(syncable::PREFERENCES, - "bar")); - EXPECT_EQ(kEncryptedString, pref_node.GetTitle()); - } -} - -TEST_F(SyncApiTest, BaseNodeSetSpecifics) { - int64 child_id = MakeNode(test_user_share_.user_share(), - syncable::BOOKMARKS, "testtag"); - WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(child_id)); - - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_bookmark()->set_url("http://www.google.com"); - - EXPECT_NE(entity_specifics.SerializeAsString(), - node.GetEntitySpecifics().SerializeAsString()); - node.SetEntitySpecifics(entity_specifics); - EXPECT_EQ(entity_specifics.SerializeAsString(), - node.GetEntitySpecifics().SerializeAsString()); -} - -TEST_F(SyncApiTest, BaseNodeSetSpecificsPreservesUnknownFields) { - int64 child_id = MakeNode(test_user_share_.user_share(), - syncable::BOOKMARKS, "testtag"); - WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(child_id)); - EXPECT_TRUE(node.GetEntitySpecifics().unknown_fields().empty()); - - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_bookmark()->set_url("http://www.google.com"); - entity_specifics.mutable_unknown_fields()->AddFixed32(5, 100); - node.SetEntitySpecifics(entity_specifics); - EXPECT_FALSE(node.GetEntitySpecifics().unknown_fields().empty()); - - entity_specifics.mutable_unknown_fields()->Clear(); - node.SetEntitySpecifics(entity_specifics); - EXPECT_FALSE(node.GetEntitySpecifics().unknown_fields().empty()); -} - -namespace { - -void CheckNodeValue(const BaseNode& node, const DictionaryValue& value, - bool is_detailed) { - ExpectInt64Value(node.GetId(), value, "id"); - { - bool is_folder = false; - EXPECT_TRUE(value.GetBoolean("isFolder", &is_folder)); - EXPECT_EQ(node.GetIsFolder(), is_folder); - } - ExpectDictStringValue(node.GetTitle(), value, "title"); - { - ModelType expected_model_type = node.GetModelType(); - std::string type_str; - EXPECT_TRUE(value.GetString("type", &type_str)); - if (expected_model_type >= syncable::FIRST_REAL_MODEL_TYPE) { - ModelType model_type = - syncable::ModelTypeFromString(type_str); - EXPECT_EQ(expected_model_type, model_type); - } else if (expected_model_type == syncable::TOP_LEVEL_FOLDER) { - EXPECT_EQ("Top-level folder", type_str); - } else if (expected_model_type == syncable::UNSPECIFIED) { - EXPECT_EQ("Unspecified", type_str); - } else { - ADD_FAILURE(); - } - } - if (is_detailed) { - ExpectInt64Value(node.GetParentId(), value, "parentId"); - ExpectTimeValue(node.GetModificationTime(), value, "modificationTime"); - ExpectInt64Value(node.GetExternalId(), value, "externalId"); - ExpectInt64Value(node.GetPredecessorId(), value, "predecessorId"); - ExpectInt64Value(node.GetSuccessorId(), value, "successorId"); - ExpectInt64Value(node.GetFirstChildId(), value, "firstChildId"); - { - scoped_ptr<DictionaryValue> expected_entry(node.GetEntry()->ToValue()); - Value* entry = NULL; - EXPECT_TRUE(value.Get("entry", &entry)); - EXPECT_TRUE(Value::Equals(entry, expected_entry.get())); - } - EXPECT_EQ(11u, value.size()); - } else { - EXPECT_EQ(4u, value.size()); - } -} - -} // namespace - -TEST_F(SyncApiTest, BaseNodeGetSummaryAsValue) { - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode node(&trans); - node.InitByRootLookup(); - scoped_ptr<DictionaryValue> details(node.GetSummaryAsValue()); - if (details.get()) { - CheckNodeValue(node, *details, false); - } else { - ADD_FAILURE(); - } -} - -TEST_F(SyncApiTest, BaseNodeGetDetailsAsValue) { - ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode node(&trans); - node.InitByRootLookup(); - scoped_ptr<DictionaryValue> details(node.GetDetailsAsValue()); - if (details.get()) { - CheckNodeValue(node, *details, true); - } else { - ADD_FAILURE(); - } -} - -TEST_F(SyncApiTest, EmptyTags) { - WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - WriteNode node(&trans); - std::string empty_tag; - EXPECT_FALSE(node.InitUniqueByCreation( - syncable::TYPED_URLS, root_node, empty_tag)); - EXPECT_EQ(BaseNode::INIT_FAILED_PRECONDITION, - node.InitByTagLookup(empty_tag)); -} - -namespace { - -class TestHttpPostProviderInterface : public HttpPostProviderInterface { - public: - virtual ~TestHttpPostProviderInterface() {} - - virtual void SetUserAgent(const char* user_agent) OVERRIDE {} - virtual void SetExtraRequestHeaders(const char* headers) OVERRIDE {} - virtual void SetURL(const char* url, int port) OVERRIDE {} - virtual void SetPostPayload(const char* content_type, - int content_length, - const char* content) OVERRIDE {} - virtual bool MakeSynchronousPost(int* error_code, int* response_code) - OVERRIDE { - return false; - } - virtual int GetResponseContentLength() const OVERRIDE { - return 0; - } - virtual const char* GetResponseContent() const OVERRIDE { - return ""; - } - virtual const std::string GetResponseHeaderValue( - const std::string& name) const OVERRIDE { - return ""; - } - virtual void Abort() OVERRIDE {} -}; - -class TestHttpPostProviderFactory : public HttpPostProviderFactory { - public: - virtual ~TestHttpPostProviderFactory() {} - virtual HttpPostProviderInterface* Create() OVERRIDE { - return new TestHttpPostProviderInterface(); - } - virtual void Destroy(HttpPostProviderInterface* http) OVERRIDE { - delete http; - } -}; - -class SyncManagerObserverMock : public SyncManager::Observer { - public: - MOCK_METHOD1(OnSyncCycleCompleted, - void(const SyncSessionSnapshot*)); // NOLINT - MOCK_METHOD2(OnInitializationComplete, - void(const WeakHandle<JsBackend>&, bool)); // NOLINT - MOCK_METHOD1(OnConnectionStatusChange, void(ConnectionStatus)); // NOLINT - MOCK_METHOD2(OnPassphraseRequired, - void(sync_api::PassphraseRequiredReason, - const sync_pb::EncryptedData&)); // NOLINT - MOCK_METHOD0(OnPassphraseAccepted, void()); // NOLINT - MOCK_METHOD1(OnBootstrapTokenUpdated, void(const std::string&)); // NOLINT - MOCK_METHOD0(OnStopSyncingPermanently, void()); // NOLINT - MOCK_METHOD1(OnUpdatedToken, void(const std::string&)); // NOLINT - MOCK_METHOD0(OnClearServerDataFailed, void()); // NOLINT - MOCK_METHOD0(OnClearServerDataSucceeded, void()); // NOLINT - MOCK_METHOD2(OnEncryptedTypesChanged, - void(ModelTypeSet, bool)); // NOLINT - MOCK_METHOD0(OnEncryptionComplete, void()); // NOLINT - MOCK_METHOD1(OnActionableError, - void(const browser_sync::SyncProtocolError&)); // NOLINT -}; - -class SyncNotifierMock : public sync_notifier::SyncNotifier { - public: - MOCK_METHOD1(AddObserver, void(sync_notifier::SyncNotifierObserver*)); - MOCK_METHOD1(RemoveObserver, void(sync_notifier::SyncNotifierObserver*)); - MOCK_METHOD1(SetUniqueId, void(const std::string&)); - MOCK_METHOD1(SetState, void(const std::string&)); - MOCK_METHOD2(UpdateCredentials, - void(const std::string&, const std::string&)); - MOCK_METHOD1(UpdateEnabledTypes, - void(syncable::ModelTypeSet)); - MOCK_METHOD1(SendNotification, void(syncable::ModelTypeSet)); -}; - -} // namespace - -class SyncManagerTest : public testing::Test, - public ModelSafeWorkerRegistrar, - public SyncManager::ChangeDelegate { - protected: - enum NigoriStatus { - DONT_WRITE_NIGORI, - WRITE_TO_NIGORI - }; - - enum EncryptionStatus { - UNINITIALIZED, - DEFAULT_ENCRYPTION, - FULL_ENCRYPTION - }; - - SyncManagerTest() - : sync_notifier_mock_(NULL), - sync_manager_("Test sync manager"), - sync_notifier_observer_(NULL), - update_enabled_types_call_count_(0) {} - - virtual ~SyncManagerTest() { - EXPECT_FALSE(sync_notifier_mock_); - } - - // Test implementation. - void SetUp() { - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - - SyncCredentials credentials; - credentials.email = "foo@bar.com"; - credentials.sync_token = "sometoken"; - - sync_notifier_mock_ = new StrictMock<SyncNotifierMock>(); - EXPECT_CALL(*sync_notifier_mock_, AddObserver(_)). - WillOnce(Invoke(this, &SyncManagerTest::SyncNotifierAddObserver)); - EXPECT_CALL(*sync_notifier_mock_, SetUniqueId(_)); - EXPECT_CALL(*sync_notifier_mock_, SetState("")); - EXPECT_CALL(*sync_notifier_mock_, - UpdateCredentials(credentials.email, credentials.sync_token)); - EXPECT_CALL(*sync_notifier_mock_, UpdateEnabledTypes(_)). - Times(AtLeast(1)). - WillRepeatedly( - Invoke(this, &SyncManagerTest::SyncNotifierUpdateEnabledTypes)); - EXPECT_CALL(*sync_notifier_mock_, RemoveObserver(_)). - WillOnce(Invoke(this, &SyncManagerTest::SyncNotifierRemoveObserver)); - - sync_manager_.AddObserver(&observer_); - EXPECT_CALL(observer_, OnInitializationComplete(_, _)). - WillOnce(SaveArg<0>(&js_backend_)); - - EXPECT_FALSE(sync_notifier_observer_); - EXPECT_FALSE(js_backend_.IsInitialized()); - - // Takes ownership of |sync_notifier_mock_|. - sync_manager_.Init(temp_dir_.path(), - WeakHandle<JsEventHandler>(), - "bogus", 0, false, - base::MessageLoopProxy::current(), - new TestHttpPostProviderFactory(), this, - &extensions_activity_monitor_, this, "bogus", - credentials, - false /* enable_sync_tabs_for_other_clients */, - sync_notifier_mock_, "", - sync_api::SyncManager::TEST_IN_MEMORY, - &encryptor_, - &handler_, - NULL); - - EXPECT_TRUE(sync_notifier_observer_); - EXPECT_TRUE(js_backend_.IsInitialized()); - - EXPECT_EQ(1, update_enabled_types_call_count_); - - ModelSafeRoutingInfo routes; - GetModelSafeRoutingInfo(&routes); - for (ModelSafeRoutingInfo::iterator i = routes.begin(); i != routes.end(); - ++i) { - type_roots_[i->first] = MakeServerNodeForType( - sync_manager_.GetUserShare(), i->first); - } - PumpLoop(); - } - - void TearDown() { - sync_manager_.RemoveObserver(&observer_); - sync_manager_.ShutdownOnSyncThread(); - sync_notifier_mock_ = NULL; - EXPECT_FALSE(sync_notifier_observer_); - PumpLoop(); - } - - // ModelSafeWorkerRegistrar implementation. - virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) OVERRIDE { - NOTIMPLEMENTED(); - out->clear(); - } - virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) OVERRIDE { - (*out)[syncable::NIGORI] = browser_sync::GROUP_PASSIVE; - (*out)[syncable::BOOKMARKS] = browser_sync::GROUP_PASSIVE; - (*out)[syncable::THEMES] = browser_sync::GROUP_PASSIVE; - (*out)[syncable::SESSIONS] = browser_sync::GROUP_PASSIVE; - (*out)[syncable::PASSWORDS] = browser_sync::GROUP_PASSIVE; - (*out)[syncable::PREFERENCES] = browser_sync::GROUP_PASSIVE; - } - - virtual void OnChangesApplied( - syncable::ModelType model_type, - const BaseTransaction* trans, - const ImmutableChangeRecordList& changes) OVERRIDE {} - - virtual void OnChangesComplete(syncable::ModelType model_type) OVERRIDE {} - - // Helper methods. - bool SetUpEncryption(NigoriStatus nigori_status, - EncryptionStatus encryption_status) { - UserShare* share = sync_manager_.GetUserShare(); - share->directory->set_initial_sync_ended_for_type(syncable::NIGORI, true); - - // We need to create the nigori node as if it were an applied server update. - int64 nigori_id = GetIdForDataType(syncable::NIGORI); - if (nigori_id == kInvalidId) - return false; - - // Set the nigori cryptographer information. - WriteTransaction trans(FROM_HERE, share); - Cryptographer* cryptographer = trans.GetCryptographer(); - if (!cryptographer) - return false; - if (encryption_status != UNINITIALIZED) { - KeyParams params = {"localhost", "dummy", "foobar"}; - cryptographer->AddKey(params); - } else { - DCHECK_NE(nigori_status, WRITE_TO_NIGORI); - } - if (encryption_status == FULL_ENCRYPTION) - cryptographer->set_encrypt_everything(); - if (nigori_status == WRITE_TO_NIGORI) { - sync_pb::NigoriSpecifics nigori; - cryptographer->GetKeys(nigori.mutable_encrypted()); - cryptographer->UpdateNigoriFromEncryptedTypes(&nigori); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(nigori_id)); - node.SetNigoriSpecifics(nigori); - } - return cryptographer->is_ready(); - } - - int64 GetIdForDataType(ModelType type) { - if (type_roots_.count(type) == 0) - return 0; - return type_roots_[type]; - } - - void SyncNotifierAddObserver( - sync_notifier::SyncNotifierObserver* sync_notifier_observer) { - EXPECT_EQ(NULL, sync_notifier_observer_); - sync_notifier_observer_ = sync_notifier_observer; - } - - void SyncNotifierRemoveObserver( - sync_notifier::SyncNotifierObserver* sync_notifier_observer) { - EXPECT_EQ(sync_notifier_observer_, sync_notifier_observer); - sync_notifier_observer_ = NULL; - } - - void SyncNotifierUpdateEnabledTypes(syncable::ModelTypeSet types) { - ModelSafeRoutingInfo routes; - GetModelSafeRoutingInfo(&routes); - const syncable::ModelTypeSet expected_types = - GetRoutingInfoTypes(routes); - EXPECT_TRUE(types.Equals(expected_types)); - ++update_enabled_types_call_count_; - } - - void PumpLoop() { - message_loop_.RunAllPending(); - } - - void SendJsMessage(const std::string& name, const JsArgList& args, - const WeakHandle<JsReplyHandler>& reply_handler) { - js_backend_.Call(FROM_HERE, &JsBackend::ProcessJsMessage, - name, args, reply_handler); - PumpLoop(); - } - - void SetJsEventHandler(const WeakHandle<JsEventHandler>& event_handler) { - js_backend_.Call(FROM_HERE, &JsBackend::SetJsEventHandler, - event_handler); - PumpLoop(); - } - - // Looks up an entry by client tag and resets IS_UNSYNCED value to false. - // Returns true if entry was previously unsynced, false if IS_UNSYNCED was - // already false. - bool ResetUnsyncedEntry(syncable::ModelType type, - const std::string& client_tag) { - UserShare* share = sync_manager_.GetUserShare(); - syncable::WriteTransaction trans( - FROM_HERE, syncable::UNITTEST, share->directory.get()); - const std::string hash = BaseNode::GenerateSyncableHash(type, client_tag); - syncable::MutableEntry entry(&trans, syncable::GET_BY_CLIENT_TAG, - hash); - EXPECT_TRUE(entry.good()); - if (!entry.Get(IS_UNSYNCED)) - return false; - entry.Put(IS_UNSYNCED, false); - return true; - } - - private: - // Needed by |sync_manager_|. - MessageLoop message_loop_; - // Needed by |sync_manager_|. - ScopedTempDir temp_dir_; - // Sync Id's for the roots of the enabled datatypes. - std::map<ModelType, int64> type_roots_; - FakeExtensionsActivityMonitor extensions_activity_monitor_; - StrictMock<SyncNotifierMock>* sync_notifier_mock_; - - protected: - FakeEncryptor encryptor_; - TestUnrecoverableErrorHandler handler_; - SyncManager sync_manager_; - WeakHandle<JsBackend> js_backend_; - StrictMock<SyncManagerObserverMock> observer_; - sync_notifier::SyncNotifierObserver* sync_notifier_observer_; - int update_enabled_types_call_count_; -}; - -TEST_F(SyncManagerTest, UpdateEnabledTypes) { - EXPECT_EQ(1, update_enabled_types_call_count_); - // Triggers SyncNotifierUpdateEnabledTypes. - sync_manager_.UpdateEnabledTypes(); - EXPECT_EQ(2, update_enabled_types_call_count_); -} - -TEST_F(SyncManagerTest, DoNotSyncTabsInNigoriNode) { - const syncable::ModelTypeSet encrypted_types(syncable::TYPED_URLS); - sync_manager_.MaybeSetSyncTabsInNigoriNode(encrypted_types); - - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode node(&trans); - ASSERT_EQ(BaseNode::INIT_OK, - node.InitByIdLookup(GetIdForDataType(syncable::NIGORI))); - EXPECT_FALSE(node.GetNigoriSpecifics().sync_tabs()); -} - -TEST_F(SyncManagerTest, SyncTabsInNigoriNode) { - const syncable::ModelTypeSet encrypted_types(syncable::SESSIONS); - sync_manager_.MaybeSetSyncTabsInNigoriNode(encrypted_types); - - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode node(&trans); - ASSERT_EQ(BaseNode::INIT_OK, - node.InitByIdLookup(GetIdForDataType(syncable::NIGORI))); - EXPECT_TRUE(node.GetNigoriSpecifics().sync_tabs()); -} - -TEST_F(SyncManagerTest, ProcessJsMessage) { - const JsArgList kNoArgs; - - StrictMock<MockJsReplyHandler> reply_handler; - - ListValue false_args; - false_args.Append(Value::CreateBooleanValue(false)); - - EXPECT_CALL(reply_handler, - HandleJsReply("getNotificationState", - HasArgsAsList(false_args))); - - // This message should be dropped. - SendJsMessage("unknownMessage", kNoArgs, reply_handler.AsWeakHandle()); - - SendJsMessage("getNotificationState", kNoArgs, reply_handler.AsWeakHandle()); -} - -TEST_F(SyncManagerTest, ProcessJsMessageGetRootNodeDetails) { - const JsArgList kNoArgs; - - StrictMock<MockJsReplyHandler> reply_handler; - - JsArgList return_args; - - EXPECT_CALL(reply_handler, - HandleJsReply("getRootNodeDetails", _)) - .WillOnce(SaveArg<1>(&return_args)); - - SendJsMessage("getRootNodeDetails", kNoArgs, reply_handler.AsWeakHandle()); - - EXPECT_EQ(1u, return_args.Get().GetSize()); - DictionaryValue* node_info = NULL; - EXPECT_TRUE(return_args.Get().GetDictionary(0, &node_info)); - if (node_info) { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode node(&trans); - node.InitByRootLookup(); - CheckNodeValue(node, *node_info, true); - } else { - ADD_FAILURE(); - } -} - -void CheckGetNodesByIdReturnArgs(const SyncManager& sync_manager, - const JsArgList& return_args, - int64 id, - bool is_detailed) { - EXPECT_EQ(1u, return_args.Get().GetSize()); - ListValue* nodes = NULL; - ASSERT_TRUE(return_args.Get().GetList(0, &nodes)); - ASSERT_TRUE(nodes); - EXPECT_EQ(1u, nodes->GetSize()); - DictionaryValue* node_info = NULL; - EXPECT_TRUE(nodes->GetDictionary(0, &node_info)); - ASSERT_TRUE(node_info); - ReadTransaction trans(FROM_HERE, sync_manager.GetUserShare()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(id)); - CheckNodeValue(node, *node_info, is_detailed); -} - -class SyncManagerGetNodesByIdTest : public SyncManagerTest { - protected: - virtual ~SyncManagerGetNodesByIdTest() {} - - void RunGetNodesByIdTest(const char* message_name, bool is_detailed) { - int64 root_id = kInvalidId; - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - root_id = root_node.GetId(); - } - - int64 child_id = - MakeNode(sync_manager_.GetUserShare(), - syncable::BOOKMARKS, "testtag"); - - StrictMock<MockJsReplyHandler> reply_handler; - - JsArgList return_args; - - const int64 ids[] = { root_id, child_id }; - - EXPECT_CALL(reply_handler, - HandleJsReply(message_name, _)) - .Times(arraysize(ids)).WillRepeatedly(SaveArg<1>(&return_args)); - - for (size_t i = 0; i < arraysize(ids); ++i) { - ListValue args; - ListValue* id_values = new ListValue(); - args.Append(id_values); - id_values->Append(Value::CreateStringValue(base::Int64ToString(ids[i]))); - SendJsMessage(message_name, - JsArgList(&args), reply_handler.AsWeakHandle()); - - CheckGetNodesByIdReturnArgs(sync_manager_, return_args, - ids[i], is_detailed); - } - } - - void RunGetNodesByIdFailureTest(const char* message_name) { - StrictMock<MockJsReplyHandler> reply_handler; - - ListValue empty_list_args; - empty_list_args.Append(new ListValue()); - - EXPECT_CALL(reply_handler, - HandleJsReply(message_name, - HasArgsAsList(empty_list_args))) - .Times(6); - - { - ListValue args; - SendJsMessage(message_name, - JsArgList(&args), reply_handler.AsWeakHandle()); - } - - { - ListValue args; - args.Append(new ListValue()); - SendJsMessage(message_name, - JsArgList(&args), reply_handler.AsWeakHandle()); - } - - { - ListValue args; - ListValue* ids = new ListValue(); - args.Append(ids); - ids->Append(Value::CreateStringValue("")); - SendJsMessage(message_name, - JsArgList(&args), reply_handler.AsWeakHandle()); - } - - { - ListValue args; - ListValue* ids = new ListValue(); - args.Append(ids); - ids->Append(Value::CreateStringValue("nonsense")); - SendJsMessage(message_name, - JsArgList(&args), reply_handler.AsWeakHandle()); - } - - { - ListValue args; - ListValue* ids = new ListValue(); - args.Append(ids); - ids->Append(Value::CreateStringValue("0")); - SendJsMessage(message_name, - JsArgList(&args), reply_handler.AsWeakHandle()); - } - - { - ListValue args; - ListValue* ids = new ListValue(); - args.Append(ids); - ids->Append(Value::CreateStringValue("9999")); - SendJsMessage(message_name, - JsArgList(&args), reply_handler.AsWeakHandle()); - } - } -}; - -TEST_F(SyncManagerGetNodesByIdTest, GetNodeSummariesById) { - RunGetNodesByIdTest("getNodeSummariesById", false); -} - -TEST_F(SyncManagerGetNodesByIdTest, GetNodeDetailsById) { - RunGetNodesByIdTest("getNodeDetailsById", true); -} - -TEST_F(SyncManagerGetNodesByIdTest, GetNodeSummariesByIdFailure) { - RunGetNodesByIdFailureTest("getNodeSummariesById"); -} - -TEST_F(SyncManagerGetNodesByIdTest, GetNodeDetailsByIdFailure) { - RunGetNodesByIdFailureTest("getNodeDetailsById"); -} - -TEST_F(SyncManagerTest, GetChildNodeIds) { - StrictMock<MockJsReplyHandler> reply_handler; - - JsArgList return_args; - - EXPECT_CALL(reply_handler, - HandleJsReply("getChildNodeIds", _)) - .Times(1).WillRepeatedly(SaveArg<1>(&return_args)); - - { - ListValue args; - args.Append(Value::CreateStringValue("1")); - SendJsMessage("getChildNodeIds", - JsArgList(&args), reply_handler.AsWeakHandle()); - } - - EXPECT_EQ(1u, return_args.Get().GetSize()); - ListValue* nodes = NULL; - ASSERT_TRUE(return_args.Get().GetList(0, &nodes)); - ASSERT_TRUE(nodes); - EXPECT_EQ(6u, nodes->GetSize()); -} - -TEST_F(SyncManagerTest, GetChildNodeIdsFailure) { - StrictMock<MockJsReplyHandler> reply_handler; - - ListValue empty_list_args; - empty_list_args.Append(new ListValue()); - - EXPECT_CALL(reply_handler, - HandleJsReply("getChildNodeIds", - HasArgsAsList(empty_list_args))) - .Times(5); - - { - ListValue args; - SendJsMessage("getChildNodeIds", - JsArgList(&args), reply_handler.AsWeakHandle()); - } - - { - ListValue args; - args.Append(Value::CreateStringValue("")); - SendJsMessage("getChildNodeIds", - JsArgList(&args), reply_handler.AsWeakHandle()); - } - - { - ListValue args; - args.Append(Value::CreateStringValue("nonsense")); - SendJsMessage("getChildNodeIds", - JsArgList(&args), reply_handler.AsWeakHandle()); - } - - { - ListValue args; - args.Append(Value::CreateStringValue("0")); - SendJsMessage("getChildNodeIds", - JsArgList(&args), reply_handler.AsWeakHandle()); - } - - { - ListValue args; - args.Append(Value::CreateStringValue("9999")); - SendJsMessage("getChildNodeIds", - JsArgList(&args), reply_handler.AsWeakHandle()); - } -} - -TEST_F(SyncManagerTest, GetAllNodesTest) { - StrictMock<MockJsReplyHandler> reply_handler; - JsArgList return_args; - - EXPECT_CALL(reply_handler, - HandleJsReply("getAllNodes", _)) - .Times(1).WillRepeatedly(SaveArg<1>(&return_args)); - - { - ListValue args; - SendJsMessage("getAllNodes", - JsArgList(&args), reply_handler.AsWeakHandle()); - } - - // There's not much value in verifying every attribute on every node here. - // Most of the value of this test has already been achieved: we've verified we - // can call the above function without crashing or leaking memory. - // - // Let's just check the list size and a few of its elements. Anything more - // would make this test brittle without greatly increasing our chances of - // catching real bugs. - - ListValue* node_list; - DictionaryValue* first_result; - - // The resulting argument list should have one argument, a list of nodes. - ASSERT_EQ(1U, return_args.Get().GetSize()); - ASSERT_TRUE(return_args.Get().GetList(0, &node_list)); - - // The database creation logic depends on the routing info. - // Refer to setup methods for more information. - ModelSafeRoutingInfo routes; - GetModelSafeRoutingInfo(&routes); - size_t directory_size = routes.size() + 1; - - ASSERT_EQ(directory_size, node_list->GetSize()); - ASSERT_TRUE(node_list->GetDictionary(0, &first_result)); - EXPECT_TRUE(first_result->HasKey("ID")); - EXPECT_TRUE(first_result->HasKey("NON_UNIQUE_NAME")); -} - -TEST_F(SyncManagerTest, OnNotificationStateChange) { - InSequence dummy; - StrictMock<MockJsEventHandler> event_handler; - - DictionaryValue true_details; - true_details.SetBoolean("enabled", true); - DictionaryValue false_details; - false_details.SetBoolean("enabled", false); - - EXPECT_CALL(event_handler, - HandleJsEvent("onNotificationStateChange", - HasDetailsAsDictionary(true_details))); - EXPECT_CALL(event_handler, - HandleJsEvent("onNotificationStateChange", - HasDetailsAsDictionary(false_details))); - - sync_manager_.TriggerOnNotificationStateChangeForTest(true); - sync_manager_.TriggerOnNotificationStateChangeForTest(false); - - SetJsEventHandler(event_handler.AsWeakHandle()); - sync_manager_.TriggerOnNotificationStateChangeForTest(true); - sync_manager_.TriggerOnNotificationStateChangeForTest(false); - SetJsEventHandler(WeakHandle<JsEventHandler>()); - - sync_manager_.TriggerOnNotificationStateChangeForTest(true); - sync_manager_.TriggerOnNotificationStateChangeForTest(false); - - // Should trigger the replies. - PumpLoop(); -} - -TEST_F(SyncManagerTest, OnIncomingNotification) { - StrictMock<MockJsEventHandler> event_handler; - - const syncable::ModelTypeSet empty_model_types; - const syncable::ModelTypeSet model_types( - syncable::BOOKMARKS, syncable::THEMES); - - // Build expected_args to have a single argument with the string - // equivalents of model_types. - DictionaryValue expected_details; - { - ListValue* model_type_list = new ListValue(); - expected_details.SetString("source", "REMOTE_NOTIFICATION"); - expected_details.Set("changedTypes", model_type_list); - for (syncable::ModelTypeSet::Iterator it = model_types.First(); - it.Good(); it.Inc()) { - model_type_list->Append( - Value::CreateStringValue( - syncable::ModelTypeToString(it.Get()))); - } - } - - EXPECT_CALL(event_handler, - HandleJsEvent("onIncomingNotification", - HasDetailsAsDictionary(expected_details))); - - sync_manager_.TriggerOnIncomingNotificationForTest(empty_model_types); - sync_manager_.TriggerOnIncomingNotificationForTest(model_types); - - SetJsEventHandler(event_handler.AsWeakHandle()); - sync_manager_.TriggerOnIncomingNotificationForTest(model_types); - SetJsEventHandler(WeakHandle<JsEventHandler>()); - - sync_manager_.TriggerOnIncomingNotificationForTest(empty_model_types); - sync_manager_.TriggerOnIncomingNotificationForTest(model_types); - - // Should trigger the replies. - PumpLoop(); -} - -TEST_F(SyncManagerTest, RefreshEncryptionReady) { - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - EXPECT_CALL(observer_, OnEncryptionComplete()); - - sync_manager_.RefreshNigori(kTestChromeVersion, base::Bind(&DoNothing)); - PumpLoop(); - - const syncable::ModelTypeSet encrypted_types = - sync_manager_.GetEncryptedDataTypesForTest(); - EXPECT_TRUE(encrypted_types.Has(syncable::PASSWORDS)); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByIdLookup(GetIdForDataType(syncable::NIGORI))); - sync_pb::NigoriSpecifics nigori = node.GetNigoriSpecifics(); - EXPECT_TRUE(nigori.has_encrypted()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - EXPECT_TRUE(cryptographer->CanDecrypt(nigori.encrypted())); - } -} - -// Attempt to refresh encryption when nigori not downloaded. -TEST_F(SyncManagerTest, RefreshEncryptionNotReady) { - // Don't set up encryption (no nigori node created). - - // Should fail. - sync_manager_.RefreshNigori(kTestChromeVersion, base::Bind(&DoNothing)); - PumpLoop(); - - const syncable::ModelTypeSet encrypted_types = - sync_manager_.GetEncryptedDataTypesForTest(); - EXPECT_TRUE(encrypted_types.Has(syncable::PASSWORDS)); // Hardcoded. - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); -} - -// Attempt to refresh encryption when nigori is empty. -TEST_F(SyncManagerTest, RefreshEncryptionEmptyNigori) { - EXPECT_TRUE(SetUpEncryption(DONT_WRITE_NIGORI, DEFAULT_ENCRYPTION)); - EXPECT_CALL(observer_, OnEncryptionComplete()); - - // Should write to nigori. - sync_manager_.RefreshNigori(kTestChromeVersion, base::Bind(&DoNothing)); - PumpLoop(); - - const syncable::ModelTypeSet encrypted_types = - sync_manager_.GetEncryptedDataTypesForTest(); - EXPECT_TRUE(encrypted_types.Has(syncable::PASSWORDS)); // Hardcoded. - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByIdLookup(GetIdForDataType(syncable::NIGORI))); - sync_pb::NigoriSpecifics nigori = node.GetNigoriSpecifics(); - EXPECT_TRUE(nigori.has_encrypted()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - EXPECT_TRUE(cryptographer->CanDecrypt(nigori.encrypted())); - } -} - -TEST_F(SyncManagerTest, EncryptDataTypesWithNoData) { - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - EXPECT_CALL(observer_, - OnEncryptedTypesChanged( - HasModelTypes(syncable::ModelTypeSet::All()), true)); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.EnableEncryptEverything(); - EXPECT_TRUE(sync_manager_.EncryptEverythingEnabledForTest()); -} - -TEST_F(SyncManagerTest, EncryptDataTypesWithData) { - size_t batch_size = 5; - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - - // Create some unencrypted unsynced data. - int64 folder = MakeFolderWithParent(sync_manager_.GetUserShare(), - syncable::BOOKMARKS, - GetIdForDataType(syncable::BOOKMARKS), - NULL); - // First batch_size nodes are children of folder. - size_t i; - for (i = 0; i < batch_size; ++i) { - MakeNodeWithParent(sync_manager_.GetUserShare(), syncable::BOOKMARKS, - base::StringPrintf("%"PRIuS"", i), folder); - } - // Next batch_size nodes are a different type and on their own. - for (; i < 2*batch_size; ++i) { - MakeNodeWithParent(sync_manager_.GetUserShare(), syncable::SESSIONS, - base::StringPrintf("%"PRIuS"", i), - GetIdForDataType(syncable::SESSIONS)); - } - // Last batch_size nodes are a third type that will not need encryption. - for (; i < 3*batch_size; ++i) { - MakeNodeWithParent(sync_manager_.GetUserShare(), syncable::THEMES, - base::StringPrintf("%"PRIuS"", i), - GetIdForDataType(syncable::THEMES)); - } - - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - EXPECT_TRUE(GetEncryptedTypes(&trans).Equals( - Cryptographer::SensitiveTypes())); - EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest( - trans.GetWrappedTrans(), - trans.GetCryptographer(), - syncable::BOOKMARKS, - false /* not encrypted */)); - EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest( - trans.GetWrappedTrans(), - trans.GetCryptographer(), - syncable::SESSIONS, - false /* not encrypted */)); - EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest( - trans.GetWrappedTrans(), - trans.GetCryptographer(), - syncable::THEMES, - false /* not encrypted */)); - } - - EXPECT_CALL(observer_, - OnEncryptedTypesChanged( - HasModelTypes(syncable::ModelTypeSet::All()), true)); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.EnableEncryptEverything(); - EXPECT_TRUE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - EXPECT_TRUE(GetEncryptedTypes(&trans).Equals( - syncable::ModelTypeSet::All())); - EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest( - trans.GetWrappedTrans(), - trans.GetCryptographer(), - syncable::BOOKMARKS, - true /* is encrypted */)); - EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest( - trans.GetWrappedTrans(), - trans.GetCryptographer(), - syncable::SESSIONS, - true /* is encrypted */)); - EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest( - trans.GetWrappedTrans(), - trans.GetCryptographer(), - syncable::THEMES, - true /* is encrypted */)); - } - - // Trigger's a ReEncryptEverything with new passphrase. - testing::Mock::VerifyAndClearExpectations(&observer_); - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetEncryptionPassphrase("new_passphrase", true); - EXPECT_TRUE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - EXPECT_TRUE(GetEncryptedTypes(&trans).Equals( - syncable::ModelTypeSet::All())); - EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest( - trans.GetWrappedTrans(), - trans.GetCryptographer(), - syncable::BOOKMARKS, - true /* is encrypted */)); - EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest( - trans.GetWrappedTrans(), - trans.GetCryptographer(), - syncable::SESSIONS, - true /* is encrypted */)); - EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest( - trans.GetWrappedTrans(), - trans.GetCryptographer(), - syncable::THEMES, - true /* is encrypted */)); - } - // Calling EncryptDataTypes with an empty encrypted types should not trigger - // a reencryption and should just notify immediately. - // TODO(zea): add logic to ensure nothing was written. - testing::Mock::VerifyAndClearExpectations(&observer_); - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)).Times(0); - EXPECT_CALL(observer_, OnPassphraseAccepted()).Times(0); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.EnableEncryptEverything(); -} - -// Test that when there are no pending keys and the cryptographer is not -// initialized, we add a key based on the current GAIA password. -// (case 1 in SyncManager::SyncInternal::SetEncryptionPassphrase) -TEST_F(SyncManagerTest, SetInitialGaiaPass) { - EXPECT_FALSE(SetUpEncryption(DONT_WRITE_NIGORI, UNINITIALIZED)); - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetEncryptionPassphrase("new_passphrase", false); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node.InitByTagLookup(kNigoriTag)); - sync_pb::NigoriSpecifics nigori = node.GetNigoriSpecifics(); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - EXPECT_TRUE(cryptographer->CanDecrypt(nigori.encrypted())); - } -} - -// Test that when there are no pending keys and we have on the old GAIA -// password, we update and re-encrypt everything with the new GAIA password. -// (case 1 in SyncManager::SyncInternal::SetEncryptionPassphrase) -TEST_F(SyncManagerTest, UpdateGaiaPass) { - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - Cryptographer verifier(&encryptor_); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - std::string bootstrap_token; - cryptographer->GetBootstrapToken(&bootstrap_token); - verifier.Bootstrap(bootstrap_token); - } - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetEncryptionPassphrase("new_passphrase", false); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - // Verify the default key has changed. - sync_pb::EncryptedData encrypted; - cryptographer->GetKeys(&encrypted); - EXPECT_FALSE(verifier.CanDecrypt(encrypted)); - } -} - -// Sets a new explicit passphrase. This should update the bootstrap token -// and re-encrypt everything. -// (case 2 in SyncManager::SyncInternal::SetEncryptionPassphrase) -TEST_F(SyncManagerTest, SetPassphraseWithPassword) { - Cryptographer verifier(&encryptor_); - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - // Store the default (soon to be old) key. - Cryptographer* cryptographer = trans.GetCryptographer(); - std::string bootstrap_token; - cryptographer->GetBootstrapToken(&bootstrap_token); - verifier.Bootstrap(bootstrap_token); - - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - - WriteNode password_node(&trans); - EXPECT_TRUE(password_node.InitUniqueByCreation(syncable::PASSWORDS, - root_node, "foo")); - sync_pb::PasswordSpecificsData data; - data.set_password_value("secret"); - password_node.SetPasswordSpecifics(data); - } - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetEncryptionPassphrase("new_passphrase", true); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - // Verify the default key has changed. - sync_pb::EncryptedData encrypted; - cryptographer->GetKeys(&encrypted); - EXPECT_FALSE(verifier.CanDecrypt(encrypted)); - - ReadNode password_node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - password_node.InitByClientTagLookup(syncable::PASSWORDS, - "foo")); - const sync_pb::PasswordSpecificsData& data = - password_node.GetPasswordSpecifics(); - EXPECT_EQ("secret", data.password_value()); - } -} - -// Manually set the pending keys in the cryptographer/nigori to reflect the data -// being encrypted with a new (unprovided) GAIA password, then supply the -// password. -// (case 7 in SyncManager::SyncInternal::SetDecryptionPassphrase) -TEST_F(SyncManagerTest, SupplyPendingGAIAPass) { - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - Cryptographer other_cryptographer(&encryptor_); - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - std::string bootstrap_token; - cryptographer->GetBootstrapToken(&bootstrap_token); - other_cryptographer.Bootstrap(bootstrap_token); - - // Now update the nigori to reflect the new keys, and update the - // cryptographer to have pending keys. - KeyParams params = {"localhost", "dummy", "passphrase2"}; - other_cryptographer.AddKey(params); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node.InitByTagLookup(kNigoriTag)); - sync_pb::NigoriSpecifics nigori; - other_cryptographer.GetKeys(nigori.mutable_encrypted()); - cryptographer->Update(nigori); - EXPECT_TRUE(cryptographer->has_pending_keys()); - node.SetNigoriSpecifics(nigori); - } - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetDecryptionPassphrase("passphrase2"); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - // Verify we're encrypting with the new key. - sync_pb::EncryptedData encrypted; - cryptographer->GetKeys(&encrypted); - EXPECT_TRUE(other_cryptographer.CanDecrypt(encrypted)); - } -} - -// Manually set the pending keys in the cryptographer/nigori to reflect the data -// being encrypted with an old (unprovided) GAIA password. Attempt to supply -// the current GAIA password and verify the bootstrap token is updated. Then -// supply the old GAIA password, and verify we re-encrypt all data with the -// new GAIA password. -// (cases 4 and 5 in SyncManager::SyncInternal::SetEncryptionPassphrase) -TEST_F(SyncManagerTest, SupplyPendingOldGAIAPass) { - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - Cryptographer other_cryptographer(&encryptor_); - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - std::string bootstrap_token; - cryptographer->GetBootstrapToken(&bootstrap_token); - other_cryptographer.Bootstrap(bootstrap_token); - - // Now update the nigori to reflect the new keys, and update the - // cryptographer to have pending keys. - KeyParams params = {"localhost", "dummy", "old_gaia"}; - other_cryptographer.AddKey(params); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node.InitByTagLookup(kNigoriTag)); - sync_pb::NigoriSpecifics nigori; - other_cryptographer.GetKeys(nigori.mutable_encrypted()); - node.SetNigoriSpecifics(nigori); - cryptographer->Update(nigori); - - // other_cryptographer now contains all encryption keys, and is encrypting - // with the newest gaia. - KeyParams new_params = {"localhost", "dummy", "new_gaia"}; - other_cryptographer.AddKey(new_params); - } - // The bootstrap token should have been updated. Save it to ensure it's based - // on the new GAIA password. - std::string bootstrap_token; - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)) - .WillOnce(SaveArg<0>(&bootstrap_token)); - EXPECT_CALL(observer_, OnPassphraseRequired(_,_)); - sync_manager_.SetEncryptionPassphrase("new_gaia", false); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - testing::Mock::VerifyAndClearExpectations(&observer_); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_initialized()); - EXPECT_FALSE(cryptographer->is_ready()); - // Verify we're encrypting with the new key, even though we have pending - // keys. - sync_pb::EncryptedData encrypted; - other_cryptographer.GetKeys(&encrypted); - EXPECT_TRUE(cryptographer->CanDecrypt(encrypted)); - } - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetEncryptionPassphrase("old_gaia", false); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - - // Verify we're encrypting with the new key. - sync_pb::EncryptedData encrypted; - other_cryptographer.GetKeys(&encrypted); - EXPECT_TRUE(cryptographer->CanDecrypt(encrypted)); - - // Verify the saved bootstrap token is based on the new gaia password. - Cryptographer temp_cryptographer(&encryptor_); - temp_cryptographer.Bootstrap(bootstrap_token); - EXPECT_TRUE(temp_cryptographer.CanDecrypt(encrypted)); - } -} - -// Manually set the pending keys in the cryptographer/nigori to reflect the data -// being encrypted with an explicit (unprovided) passphrase, then supply the -// passphrase. -// (case 9 in SyncManager::SyncInternal::SetDecryptionPassphrase) -TEST_F(SyncManagerTest, SupplyPendingExplicitPass) { - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - Cryptographer other_cryptographer(&encryptor_); - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - std::string bootstrap_token; - cryptographer->GetBootstrapToken(&bootstrap_token); - other_cryptographer.Bootstrap(bootstrap_token); - - // Now update the nigori to reflect the new keys, and update the - // cryptographer to have pending keys. - KeyParams params = {"localhost", "dummy", "explicit"}; - other_cryptographer.AddKey(params); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node.InitByTagLookup(kNigoriTag)); - sync_pb::NigoriSpecifics nigori; - other_cryptographer.GetKeys(nigori.mutable_encrypted()); - cryptographer->Update(nigori); - EXPECT_TRUE(cryptographer->has_pending_keys()); - nigori.set_using_explicit_passphrase(true); - node.SetNigoriSpecifics(nigori); - } - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetDecryptionPassphrase("explicit"); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - // Verify we're encrypting with the new key. - sync_pb::EncryptedData encrypted; - cryptographer->GetKeys(&encrypted); - EXPECT_TRUE(other_cryptographer.CanDecrypt(encrypted)); - } -} - -// Manually set the pending keys in the cryptographer/nigori to reflect the data -// being encrypted with a new (unprovided) GAIA password, then supply the -// password as a user-provided password. -// This is the android case 7/8. -TEST_F(SyncManagerTest, SupplyPendingGAIAPassUserProvided) { - EXPECT_FALSE(SetUpEncryption(DONT_WRITE_NIGORI, UNINITIALIZED)); - Cryptographer other_cryptographer(&encryptor_); - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - // Now update the nigori to reflect the new keys, and update the - // cryptographer to have pending keys. - KeyParams params = {"localhost", "dummy", "passphrase"}; - other_cryptographer.AddKey(params); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node.InitByTagLookup(kNigoriTag)); - sync_pb::NigoriSpecifics nigori; - other_cryptographer.GetKeys(nigori.mutable_encrypted()); - node.SetNigoriSpecifics(nigori); - cryptographer->Update(nigori); - EXPECT_FALSE(cryptographer->is_ready()); - } - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetEncryptionPassphrase("passphrase", false); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - } -} - -TEST_F(SyncManagerTest, SetPassphraseWithEmptyPasswordNode) { - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - int64 node_id = 0; - std::string tag = "foo"; - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - - WriteNode password_node(&trans); - EXPECT_TRUE(password_node.InitUniqueByCreation(syncable::PASSWORDS, - root_node, tag)); - node_id = password_node.GetId(); - } - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetEncryptionPassphrase("new_passphrase", true); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode password_node(&trans); - EXPECT_EQ(BaseNode::INIT_FAILED_DECRYPT_IF_NECESSARY, - password_node.InitByClientTagLookup(syncable::PASSWORDS, - tag)); - } - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode password_node(&trans); - EXPECT_EQ(BaseNode::INIT_FAILED_DECRYPT_IF_NECESSARY, - password_node.InitByIdLookup(node_id)); - } -} - -TEST_F(SyncManagerTest, NudgeDelayTest) { - EXPECT_EQ(sync_manager_.GetNudgeDelayTimeDelta(syncable::BOOKMARKS), - base::TimeDelta::FromMilliseconds( - SyncManager::kDefaultNudgeDelayMilliseconds)); - - EXPECT_EQ(sync_manager_.GetNudgeDelayTimeDelta(syncable::AUTOFILL), - base::TimeDelta::FromSeconds( - browser_sync::kDefaultShortPollIntervalSeconds)); - - EXPECT_EQ(sync_manager_.GetNudgeDelayTimeDelta(syncable::PREFERENCES), - base::TimeDelta::FromMilliseconds( - SyncManager::kPreferencesNudgeDelayMilliseconds)); -} - -// Friended by WriteNode, so can't be in an anonymouse namespace. -TEST_F(SyncManagerTest, EncryptBookmarksWithLegacyData) { - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - std::string title; - SyncAPINameToServerName("Google", &title); - std::string url = "http://www.google.com"; - std::string raw_title2 = ".."; // An invalid cosmo title. - std::string title2; - SyncAPINameToServerName(raw_title2, &title2); - std::string url2 = "http://www.bla.com"; - - // Create a bookmark using the legacy format. - int64 node_id1 = MakeNode(sync_manager_.GetUserShare(), - syncable::BOOKMARKS, - "testtag"); - int64 node_id2 = MakeNode(sync_manager_.GetUserShare(), - syncable::BOOKMARKS, - "testtag2"); - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(node_id1)); - - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_bookmark()->set_url(url); - node.SetEntitySpecifics(entity_specifics); - - // Set the old style title. - syncable::MutableEntry* node_entry = node.entry_; - node_entry->Put(syncable::NON_UNIQUE_NAME, title); - - WriteNode node2(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node2.InitByIdLookup(node_id2)); - - sync_pb::EntitySpecifics entity_specifics2; - entity_specifics2.mutable_bookmark()->set_url(url2); - node2.SetEntitySpecifics(entity_specifics2); - - // Set the old style title. - syncable::MutableEntry* node_entry2 = node2.entry_; - node_entry2->Put(syncable::NON_UNIQUE_NAME, title2); - } - - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(node_id1)); - EXPECT_EQ(syncable::BOOKMARKS, node.GetModelType()); - EXPECT_EQ(title, node.GetTitle()); - EXPECT_EQ(title, node.GetBookmarkSpecifics().title()); - EXPECT_EQ(url, node.GetBookmarkSpecifics().url()); - - ReadNode node2(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node2.InitByIdLookup(node_id2)); - EXPECT_EQ(syncable::BOOKMARKS, node2.GetModelType()); - // We should de-canonicalize the title in GetTitle(), but the title in the - // specifics should be stored in the server legal form. - EXPECT_EQ(raw_title2, node2.GetTitle()); - EXPECT_EQ(title2, node2.GetBookmarkSpecifics().title()); - EXPECT_EQ(url2, node2.GetBookmarkSpecifics().url()); - } - - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest( - trans.GetWrappedTrans(), - trans.GetCryptographer(), - syncable::BOOKMARKS, - false /* not encrypted */)); - } - - EXPECT_CALL(observer_, - OnEncryptedTypesChanged( - HasModelTypes(syncable::ModelTypeSet::All()), true)); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.EnableEncryptEverything(); - EXPECT_TRUE(sync_manager_.EncryptEverythingEnabledForTest()); - - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - EXPECT_TRUE(GetEncryptedTypes(&trans).Equals( - syncable::ModelTypeSet::All())); - EXPECT_TRUE(syncable::VerifyDataTypeEncryptionForTest( - trans.GetWrappedTrans(), - trans.GetCryptographer(), - syncable::BOOKMARKS, - true /* is encrypted */)); - - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(node_id1)); - EXPECT_EQ(syncable::BOOKMARKS, node.GetModelType()); - EXPECT_EQ(title, node.GetTitle()); - EXPECT_EQ(title, node.GetBookmarkSpecifics().title()); - EXPECT_EQ(url, node.GetBookmarkSpecifics().url()); - - ReadNode node2(&trans); - EXPECT_EQ(BaseNode::INIT_OK, node2.InitByIdLookup(node_id2)); - EXPECT_EQ(syncable::BOOKMARKS, node2.GetModelType()); - // We should de-canonicalize the title in GetTitle(), but the title in the - // specifics should be stored in the server legal form. - EXPECT_EQ(raw_title2, node2.GetTitle()); - EXPECT_EQ(title2, node2.GetBookmarkSpecifics().title()); - EXPECT_EQ(url2, node2.GetBookmarkSpecifics().url()); - } -} - -// Create a bookmark and set the title/url, then verify the data was properly -// set. This replicates the unique way bookmarks have of creating sync nodes. -// See BookmarkChangeProcessor::PlaceSyncNode(..). -TEST_F(SyncManagerTest, CreateLocalBookmark) { - std::string title = "title"; - GURL url("url"); - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - WriteNode node(&trans); - ASSERT_TRUE(node.InitByCreation(syncable::BOOKMARKS, root_node, NULL)); - node.SetIsFolder(false); - node.SetTitle(UTF8ToWide(title)); - node.SetURL(url); - } - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode root_node(&trans); - root_node.InitByRootLookup(); - int64 child_id = root_node.GetFirstChildId(); - - ReadNode node(&trans); - ASSERT_EQ(BaseNode::INIT_OK, node.InitByIdLookup(child_id)); - EXPECT_FALSE(node.GetIsFolder()); - EXPECT_EQ(title, node.GetTitle()); - EXPECT_EQ(url, node.GetURL()); - } -} - -// Verifies WriteNode::UpdateEntryWithEncryption does not make unnecessary -// changes. -TEST_F(SyncManagerTest, UpdateEntryWithEncryption) { - std::string client_tag = "title"; - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_bookmark()->set_url("url"); - entity_specifics.mutable_bookmark()->set_title("title"); - MakeServerNode(sync_manager_.GetUserShare(), syncable::BOOKMARKS, client_tag, - BaseNode::GenerateSyncableHash(syncable::BOOKMARKS, - client_tag), - entity_specifics); - // New node shouldn't start off unsynced. - EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); - // Manually change to the same data. Should not set is_unsynced. - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); - node.SetEntitySpecifics(entity_specifics); - } - EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); - - // Encrypt the datatatype, should set is_unsynced. - EXPECT_CALL(observer_, - OnEncryptedTypesChanged( - HasModelTypes(syncable::ModelTypeSet::All()), true)); - EXPECT_CALL(observer_, OnEncryptionComplete()); - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, FULL_ENCRYPTION)); - - sync_manager_.RefreshNigori(kTestChromeVersion, base::Bind(&DoNothing)); - PumpLoop(); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); - const syncable::Entry* node_entry = node.GetEntry(); - const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); - EXPECT_TRUE(specifics.has_encrypted()); - EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey( - specifics.encrypted())); - } - EXPECT_TRUE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); - - // Set a new passphrase. Should set is_unsynced. - testing::Mock::VerifyAndClearExpectations(&observer_); - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetEncryptionPassphrase("new_passphrase", true); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); - const syncable::Entry* node_entry = node.GetEntry(); - const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); - EXPECT_TRUE(specifics.has_encrypted()); - EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey( - specifics.encrypted())); - } - EXPECT_TRUE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); - - // Force a re-encrypt everything. Should not set is_unsynced. - testing::Mock::VerifyAndClearExpectations(&observer_); - EXPECT_CALL(observer_, OnEncryptionComplete()); - - sync_manager_.RefreshNigori(kTestChromeVersion, base::Bind(&DoNothing)); - PumpLoop(); - - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); - const syncable::Entry* node_entry = node.GetEntry(); - const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); - EXPECT_TRUE(specifics.has_encrypted()); - EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey( - specifics.encrypted())); - } - EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); - - // Manually change to the same data. Should not set is_unsynced. - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); - node.SetEntitySpecifics(entity_specifics); - const syncable::Entry* node_entry = node.GetEntry(); - const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); - EXPECT_TRUE(specifics.has_encrypted()); - EXPECT_FALSE(node_entry->Get(IS_UNSYNCED)); - EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey( - specifics.encrypted())); - } - EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); - - // Manually change to different data. Should set is_unsynced. - { - entity_specifics.mutable_bookmark()->set_url("url2"); - entity_specifics.mutable_bookmark()->set_title("title2"); - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); - node.SetEntitySpecifics(entity_specifics); - const syncable::Entry* node_entry = node.GetEntry(); - const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); - EXPECT_TRUE(specifics.has_encrypted()); - EXPECT_TRUE(node_entry->Get(IS_UNSYNCED)); - EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->CanDecryptUsingDefaultKey( - specifics.encrypted())); - } -} - -// Passwords have their own handling for encryption. Verify it does not result -// in unnecessary writes via SetEntitySpecifics. -TEST_F(SyncManagerTest, UpdatePasswordSetEntitySpecificsNoChange) { - std::string client_tag = "title"; - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - sync_pb::EntitySpecifics entity_specifics; - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - sync_pb::PasswordSpecificsData data; - data.set_password_value("secret"); - cryptographer->Encrypt( - data, - entity_specifics.mutable_password()-> - mutable_encrypted()); - } - MakeServerNode(sync_manager_.GetUserShare(), syncable::PASSWORDS, client_tag, - BaseNode::GenerateSyncableHash(syncable::PASSWORDS, - client_tag), - entity_specifics); - // New node shouldn't start off unsynced. - EXPECT_FALSE(ResetUnsyncedEntry(syncable::PASSWORDS, client_tag)); - - // Manually change to the same data via SetEntitySpecifics. Should not set - // is_unsynced. - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::PASSWORDS, client_tag)); - node.SetEntitySpecifics(entity_specifics); - } - EXPECT_FALSE(ResetUnsyncedEntry(syncable::PASSWORDS, client_tag)); -} - -// Passwords have their own handling for encryption. Verify it does not result -// in unnecessary writes via SetPasswordSpecifics. -TEST_F(SyncManagerTest, UpdatePasswordSetPasswordSpecifics) { - std::string client_tag = "title"; - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - sync_pb::EntitySpecifics entity_specifics; - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - sync_pb::PasswordSpecificsData data; - data.set_password_value("secret"); - cryptographer->Encrypt( - data, - entity_specifics.mutable_password()-> - mutable_encrypted()); - } - MakeServerNode(sync_manager_.GetUserShare(), syncable::PASSWORDS, client_tag, - BaseNode::GenerateSyncableHash(syncable::PASSWORDS, - client_tag), - entity_specifics); - // New node shouldn't start off unsynced. - EXPECT_FALSE(ResetUnsyncedEntry(syncable::PASSWORDS, client_tag)); - - // Manually change to the same data via SetPasswordSpecifics. Should not set - // is_unsynced. - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::PASSWORDS, client_tag)); - node.SetPasswordSpecifics(node.GetPasswordSpecifics()); - } - EXPECT_FALSE(ResetUnsyncedEntry(syncable::PASSWORDS, client_tag)); - - // Manually change to different data. Should set is_unsynced. - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::PASSWORDS, client_tag)); - Cryptographer* cryptographer = trans.GetCryptographer(); - sync_pb::PasswordSpecificsData data; - data.set_password_value("secret2"); - cryptographer->Encrypt( - data, - entity_specifics.mutable_password()->mutable_encrypted()); - node.SetPasswordSpecifics(data); - const syncable::Entry* node_entry = node.GetEntry(); - EXPECT_TRUE(node_entry->Get(IS_UNSYNCED)); - } -} - -// Passwords have their own handling for encryption. Verify setting a new -// passphrase updates the data. -TEST_F(SyncManagerTest, UpdatePasswordNewPassphrase) { - std::string client_tag = "title"; - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - sync_pb::EntitySpecifics entity_specifics; - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - sync_pb::PasswordSpecificsData data; - data.set_password_value("secret"); - cryptographer->Encrypt( - data, - entity_specifics.mutable_password()->mutable_encrypted()); - } - MakeServerNode(sync_manager_.GetUserShare(), syncable::PASSWORDS, client_tag, - BaseNode::GenerateSyncableHash(syncable::PASSWORDS, - client_tag), - entity_specifics); - // New node shouldn't start off unsynced. - EXPECT_FALSE(ResetUnsyncedEntry(syncable::PASSWORDS, client_tag)); - - // Set a new passphrase. Should set is_unsynced. - testing::Mock::VerifyAndClearExpectations(&observer_); - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetEncryptionPassphrase("new_passphrase", true); - EXPECT_TRUE(ResetUnsyncedEntry(syncable::PASSWORDS, client_tag)); -} - -// Passwords have their own handling for encryption. Verify it does not result -// in unnecessary writes via ReencryptEverything. -TEST_F(SyncManagerTest, UpdatePasswordReencryptEverything) { - std::string client_tag = "title"; - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - sync_pb::EntitySpecifics entity_specifics; - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - sync_pb::PasswordSpecificsData data; - data.set_password_value("secret"); - cryptographer->Encrypt( - data, - entity_specifics.mutable_password()->mutable_encrypted()); - } - MakeServerNode(sync_manager_.GetUserShare(), syncable::PASSWORDS, client_tag, - BaseNode::GenerateSyncableHash(syncable::PASSWORDS, - client_tag), - entity_specifics); - // New node shouldn't start off unsynced. - EXPECT_FALSE(ResetUnsyncedEntry(syncable::PASSWORDS, client_tag)); - - // Force a re-encrypt everything. Should not set is_unsynced. - testing::Mock::VerifyAndClearExpectations(&observer_); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.RefreshNigori(kTestChromeVersion, base::Bind(&DoNothing)); - PumpLoop(); - EXPECT_FALSE(ResetUnsyncedEntry(syncable::PASSWORDS, client_tag)); -} - -// Verify SetTitle(..) doesn't unnecessarily set IS_UNSYNCED for bookmarks -// when we write the same data, but does set it when we write new data. -TEST_F(SyncManagerTest, SetBookmarkTitle) { - std::string client_tag = "title"; - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_bookmark()->set_url("url"); - entity_specifics.mutable_bookmark()->set_title("title"); - MakeServerNode(sync_manager_.GetUserShare(), syncable::BOOKMARKS, client_tag, - BaseNode::GenerateSyncableHash(syncable::BOOKMARKS, - client_tag), - entity_specifics); - // New node shouldn't start off unsynced. - EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); - - // Manually change to the same title. Should not set is_unsynced. - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); - node.SetTitle(UTF8ToWide(client_tag)); - } - EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); - - // Manually change to new title. Should set is_unsynced. - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); - node.SetTitle(UTF8ToWide("title2")); - } - EXPECT_TRUE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); -} - -// Verify SetTitle(..) doesn't unnecessarily set IS_UNSYNCED for encrypted -// bookmarks when we write the same data, but does set it when we write new -// data. -TEST_F(SyncManagerTest, SetBookmarkTitleWithEncryption) { - std::string client_tag = "title"; - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_bookmark()->set_url("url"); - entity_specifics.mutable_bookmark()->set_title("title"); - MakeServerNode(sync_manager_.GetUserShare(), syncable::BOOKMARKS, client_tag, - BaseNode::GenerateSyncableHash(syncable::BOOKMARKS, - client_tag), - entity_specifics); - // New node shouldn't start off unsynced. - EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); - - // Encrypt the datatatype, should set is_unsynced. - EXPECT_CALL(observer_, - OnEncryptedTypesChanged( - HasModelTypes(syncable::ModelTypeSet::All()), true)); - EXPECT_CALL(observer_, OnEncryptionComplete()); - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, FULL_ENCRYPTION)); - sync_manager_.RefreshNigori(kTestChromeVersion, base::Bind(&DoNothing)); - PumpLoop(); - EXPECT_TRUE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); - - // Manually change to the same title. Should not set is_unsynced. - // NON_UNIQUE_NAME should be kEncryptedString. - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); - node.SetTitle(UTF8ToWide(client_tag)); - const syncable::Entry* node_entry = node.GetEntry(); - const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); - EXPECT_TRUE(specifics.has_encrypted()); - EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); - } - EXPECT_FALSE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); - - // Manually change to new title. Should set is_unsynced. NON_UNIQUE_NAME - // should still be kEncryptedString. - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); - node.SetTitle(UTF8ToWide("title2")); - const syncable::Entry* node_entry = node.GetEntry(); - const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); - EXPECT_TRUE(specifics.has_encrypted()); - EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); - } - EXPECT_TRUE(ResetUnsyncedEntry(syncable::BOOKMARKS, client_tag)); -} - -// Verify SetTitle(..) doesn't unnecessarily set IS_UNSYNCED for non-bookmarks -// when we write the same data, but does set it when we write new data. -TEST_F(SyncManagerTest, SetNonBookmarkTitle) { - std::string client_tag = "title"; - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_preference()->set_name("name"); - entity_specifics.mutable_preference()->set_value("value"); - MakeServerNode(sync_manager_.GetUserShare(), - syncable::PREFERENCES, - client_tag, - BaseNode::GenerateSyncableHash(syncable::PREFERENCES, - client_tag), - entity_specifics); - // New node shouldn't start off unsynced. - EXPECT_FALSE(ResetUnsyncedEntry(syncable::PREFERENCES, client_tag)); - - // Manually change to the same title. Should not set is_unsynced. - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::PREFERENCES, client_tag)); - node.SetTitle(UTF8ToWide(client_tag)); - } - EXPECT_FALSE(ResetUnsyncedEntry(syncable::PREFERENCES, client_tag)); - - // Manually change to new title. Should set is_unsynced. - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::PREFERENCES, client_tag)); - node.SetTitle(UTF8ToWide("title2")); - } - EXPECT_TRUE(ResetUnsyncedEntry(syncable::PREFERENCES, client_tag)); -} - -// Verify SetTitle(..) doesn't unnecessarily set IS_UNSYNCED for encrypted -// non-bookmarks when we write the same data or when we write new data -// data (should remained kEncryptedString). -TEST_F(SyncManagerTest, SetNonBookmarkTitleWithEncryption) { - std::string client_tag = "title"; - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_preference()->set_name("name"); - entity_specifics.mutable_preference()->set_value("value"); - MakeServerNode(sync_manager_.GetUserShare(), - syncable::PREFERENCES, - client_tag, - BaseNode::GenerateSyncableHash(syncable::PREFERENCES, - client_tag), - entity_specifics); - // New node shouldn't start off unsynced. - EXPECT_FALSE(ResetUnsyncedEntry(syncable::PREFERENCES, client_tag)); - - // Encrypt the datatatype, should set is_unsynced. - EXPECT_CALL(observer_, - OnEncryptedTypesChanged( - HasModelTypes(syncable::ModelTypeSet::All()), true)); - EXPECT_CALL(observer_, OnEncryptionComplete()); - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, FULL_ENCRYPTION)); - sync_manager_.RefreshNigori(kTestChromeVersion, base::Bind(&DoNothing)); - PumpLoop(); - EXPECT_TRUE(ResetUnsyncedEntry(syncable::PREFERENCES, client_tag)); - - // Manually change to the same title. Should not set is_unsynced. - // NON_UNIQUE_NAME should be kEncryptedString. - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::PREFERENCES, client_tag)); - node.SetTitle(UTF8ToWide(client_tag)); - const syncable::Entry* node_entry = node.GetEntry(); - const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); - EXPECT_TRUE(specifics.has_encrypted()); - EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); - } - EXPECT_FALSE(ResetUnsyncedEntry(syncable::PREFERENCES, client_tag)); - - // Manually change to new title. Should not set is_unsynced because the - // NON_UNIQUE_NAME should still be kEncryptedString. - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::PREFERENCES, client_tag)); - node.SetTitle(UTF8ToWide("title2")); - const syncable::Entry* node_entry = node.GetEntry(); - const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); - EXPECT_TRUE(specifics.has_encrypted()); - EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); - EXPECT_FALSE(node_entry->Get(IS_UNSYNCED)); - } -} - -// Create an encrypted entry when the cryptographer doesn't think the type is -// marked for encryption. Ensure reads/writes don't break and don't unencrypt -// the data. -TEST_F(SyncManagerTest, SetPreviouslyEncryptedSpecifics) { - std::string client_tag = "tag"; - std::string url = "url"; - std::string url2 = "new_url"; - std::string title = "title"; - sync_pb::EntitySpecifics entity_specifics; - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - browser_sync::Cryptographer* crypto = trans.GetCryptographer(); - sync_pb::EntitySpecifics bm_specifics; - bm_specifics.mutable_bookmark()->set_title("title"); - bm_specifics.mutable_bookmark()->set_url("url"); - sync_pb::EncryptedData encrypted; - crypto->Encrypt(bm_specifics, &encrypted); - entity_specifics.mutable_encrypted()->CopyFrom(encrypted); - syncable::AddDefaultFieldValue(syncable::BOOKMARKS, &entity_specifics); - } - MakeServerNode(sync_manager_.GetUserShare(), syncable::BOOKMARKS, client_tag, - BaseNode::GenerateSyncableHash(syncable::BOOKMARKS, - client_tag), - entity_specifics); - - { - // Verify the data. - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); - EXPECT_EQ(title, node.GetTitle()); - EXPECT_EQ(GURL(url), node.GetURL()); - } - - { - // Overwrite the url (which overwrites the specifics). - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - WriteNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); - node.SetURL(GURL(url2)); - } - - { - // Verify it's still encrypted and it has the most recent url. - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode node(&trans); - EXPECT_EQ(BaseNode::INIT_OK, - node.InitByClientTagLookup(syncable::BOOKMARKS, client_tag)); - EXPECT_EQ(title, node.GetTitle()); - EXPECT_EQ(GURL(url2), node.GetURL()); - const syncable::Entry* node_entry = node.GetEntry(); - EXPECT_EQ(kEncryptedString, node_entry->Get(NON_UNIQUE_NAME)); - const sync_pb::EntitySpecifics& specifics = node_entry->Get(SPECIFICS); - EXPECT_TRUE(specifics.has_encrypted()); - } -} - -} // namespace browser_sync diff --git a/chrome/browser/sync/internal_api/user_share.cc b/chrome/browser/sync/internal_api/user_share.cc deleted file mode 100644 index 4bdacc1..0000000 --- a/chrome/browser/sync/internal_api/user_share.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/user_share.h" - -#include "sync/syncable/syncable.h" - -namespace sync_api { - -UserShare::UserShare() {} - -UserShare::~UserShare() {} - -} diff --git a/chrome/browser/sync/internal_api/user_share.h b/chrome/browser/sync/internal_api/user_share.h deleted file mode 100644 index 472aa07..0000000 --- a/chrome/browser/sync/internal_api/user_share.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_USER_SHARE_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_USER_SHARE_H_ -#pragma once - -#include <string> - -#include "base/memory/scoped_ptr.h" - -namespace syncable { -class Directory; -} - -namespace sync_api { - -// A UserShare encapsulates the syncable pieces that represent an authenticated -// user and their data (share). -// This encompasses all pieces required to build transaction objects on the -// syncable share. -struct UserShare { - UserShare(); - ~UserShare(); - - // The Directory itself, which is the parent of Transactions. - scoped_ptr<syncable::Directory> directory; - - // The username of the sync user. - std::string name; -}; - -} - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_USER_SHARE_H_ diff --git a/chrome/browser/sync/internal_api/write_node.cc b/chrome/browser/sync/internal_api/write_node.cc deleted file mode 100644 index ef47f9d..0000000 --- a/chrome/browser/sync/internal_api/write_node.cc +++ /dev/null @@ -1,503 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/write_node.h" - -#include "base/utf_string_conversions.h" -#include "base/values.h" -#include "chrome/browser/sync/internal_api/syncapi_internal.h" -#include "chrome/browser/sync/internal_api/base_transaction.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" -#include "sync/engine/nigori_util.h" -#include "sync/protocol/app_specifics.pb.h" -#include "sync/protocol/autofill_specifics.pb.h" -#include "sync/protocol/bookmark_specifics.pb.h" -#include "sync/protocol/extension_specifics.pb.h" -#include "sync/protocol/password_specifics.pb.h" -#include "sync/protocol/session_specifics.pb.h" -#include "sync/protocol/theme_specifics.pb.h" -#include "sync/protocol/typed_url_specifics.pb.h" -#include "sync/syncable/syncable.h" -#include "sync/util/cryptographer.h" - -using browser_sync::Cryptographer; -using std::string; -using std::vector; -using syncable::kEncryptedString; -using syncable::SPECIFICS; - -namespace sync_api { - -static const char kDefaultNameForNewNodes[] = " "; - -void WriteNode::SetIsFolder(bool folder) { - if (entry_->Get(syncable::IS_DIR) == folder) - return; // Skip redundant changes. - - entry_->Put(syncable::IS_DIR, folder); - MarkForSyncing(); -} - -void WriteNode::SetTitle(const std::wstring& title) { - DCHECK_NE(GetModelType(), syncable::UNSPECIFIED); - syncable::ModelType type = GetModelType(); - Cryptographer* cryptographer = GetTransaction()->GetCryptographer(); - // It's possible the nigori lost the set of encrypted types. If the current - // specifics are already encrypted, we want to ensure we continue encrypting. - bool needs_encryption = cryptographer->GetEncryptedTypes().Has(type) || - entry_->Get(SPECIFICS).has_encrypted(); - - // If this datatype is encrypted and is not a bookmark, we disregard the - // specified title in favor of kEncryptedString. For encrypted bookmarks the - // NON_UNIQUE_NAME will still be kEncryptedString, but we store the real title - // into the specifics. All strings compared are server legal strings. - std::string new_legal_title; - if (type != syncable::BOOKMARKS && needs_encryption) { - new_legal_title = kEncryptedString; - } else { - SyncAPINameToServerName(WideToUTF8(title), &new_legal_title); - } - - std::string current_legal_title; - if (syncable::BOOKMARKS == type && - entry_->Get(syncable::SPECIFICS).has_encrypted()) { - // Encrypted bookmarks only have their title in the unencrypted specifics. - current_legal_title = GetBookmarkSpecifics().title(); - } else { - // Non-bookmarks and legacy bookmarks (those with no title in their - // specifics) store their title in NON_UNIQUE_NAME. Non-legacy bookmarks - // store their title in specifics as well as NON_UNIQUE_NAME. - current_legal_title = entry_->Get(syncable::NON_UNIQUE_NAME); - } - - bool title_matches = (current_legal_title == new_legal_title); - bool encrypted_without_overwriting_name = (needs_encryption && - entry_->Get(syncable::NON_UNIQUE_NAME) != kEncryptedString); - - // If the title matches and the NON_UNIQUE_NAME is properly overwritten as - // necessary, nothing needs to change. - if (title_matches && !encrypted_without_overwriting_name) { - DVLOG(2) << "Title matches, dropping change."; - return; - } - - // For bookmarks, we also set the title field in the specifics. - // TODO(zea): refactor bookmarks to not need this functionality. - if (GetModelType() == syncable::BOOKMARKS) { - sync_pb::EntitySpecifics specifics = GetEntitySpecifics(); - specifics.mutable_bookmark()->set_title(new_legal_title); - SetEntitySpecifics(specifics); // Does it's own encryption checking. - } - - // For bookmarks, this has to happen after we set the title in the specifics, - // because the presence of a title in the NON_UNIQUE_NAME is what controls - // the logic deciding whether this is an empty node or a legacy bookmark. - // See BaseNode::GetUnencryptedSpecific(..). - if (needs_encryption) - entry_->Put(syncable::NON_UNIQUE_NAME, kEncryptedString); - else - entry_->Put(syncable::NON_UNIQUE_NAME, new_legal_title); - - DVLOG(1) << "Overwriting title of type " - << syncable::ModelTypeToString(type) - << " and marking for syncing."; - MarkForSyncing(); -} - -void WriteNode::SetURL(const GURL& url) { - sync_pb::BookmarkSpecifics new_value = GetBookmarkSpecifics(); - new_value.set_url(url.spec()); - SetBookmarkSpecifics(new_value); -} - -void WriteNode::SetAppSpecifics( - const sync_pb::AppSpecifics& new_value) { - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_app()->CopyFrom(new_value); - SetEntitySpecifics(entity_specifics); -} - -void WriteNode::SetAutofillSpecifics( - const sync_pb::AutofillSpecifics& new_value) { - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_autofill()->CopyFrom(new_value); - SetEntitySpecifics(entity_specifics); -} - -void WriteNode::SetAutofillProfileSpecifics( - const sync_pb::AutofillProfileSpecifics& new_value) { - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_autofill_profile()-> - CopyFrom(new_value); - SetEntitySpecifics(entity_specifics); -} - -void WriteNode::SetBookmarkSpecifics( - const sync_pb::BookmarkSpecifics& new_value) { - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_bookmark()->CopyFrom(new_value); - SetEntitySpecifics(entity_specifics); -} - -void WriteNode::SetNigoriSpecifics( - const sync_pb::NigoriSpecifics& new_value) { - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_nigori()->CopyFrom(new_value); - SetEntitySpecifics(entity_specifics); -} - -void WriteNode::SetPasswordSpecifics( - const sync_pb::PasswordSpecificsData& data) { - DCHECK_EQ(syncable::PASSWORDS, GetModelType()); - - Cryptographer* cryptographer = GetTransaction()->GetCryptographer(); - - // We have to do the idempotency check here (vs in UpdateEntryWithEncryption) - // because Passwords have their encrypted data within the PasswordSpecifics, - // vs within the EntitySpecifics like all the other types. - const sync_pb::EntitySpecifics& old_specifics = GetEntry()->Get(SPECIFICS); - sync_pb::EntitySpecifics entity_specifics; - // Copy over the old specifics if they exist. - if (syncable::GetModelTypeFromSpecifics(old_specifics) == - syncable::PASSWORDS) { - entity_specifics.CopyFrom(old_specifics); - } else { - syncable::AddDefaultFieldValue(syncable::PASSWORDS, - &entity_specifics); - } - sync_pb::PasswordSpecifics* password_specifics = - entity_specifics.mutable_password(); - // This will only update password_specifics if the underlying unencrypted blob - // was different from |data| or was not encrypted with the proper passphrase. - if (!cryptographer->Encrypt(data, password_specifics->mutable_encrypted())) { - NOTREACHED() << "Failed to encrypt password, possibly due to sync node " - << "corruption"; - return; - } - SetEntitySpecifics(entity_specifics); -} - -void WriteNode::SetThemeSpecifics( - const sync_pb::ThemeSpecifics& new_value) { - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_theme()->CopyFrom(new_value); - SetEntitySpecifics(entity_specifics); -} - -void WriteNode::SetSessionSpecifics( - const sync_pb::SessionSpecifics& new_value) { - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_session()->CopyFrom(new_value); - SetEntitySpecifics(entity_specifics); -} - -void WriteNode::SetEntitySpecifics( - const sync_pb::EntitySpecifics& new_value) { - syncable::ModelType new_specifics_type = - syncable::GetModelTypeFromSpecifics(new_value); - DCHECK_NE(new_specifics_type, syncable::UNSPECIFIED); - DVLOG(1) << "Writing entity specifics of type " - << syncable::ModelTypeToString(new_specifics_type); - // GetModelType() can be unspecified if this is the first time this - // node is being initialized (see PutModelType()). Otherwise, it - // should match |new_specifics_type|. - if (GetModelType() != syncable::UNSPECIFIED) { - DCHECK_EQ(new_specifics_type, GetModelType()); - } - browser_sync::Cryptographer* cryptographer = - GetTransaction()->GetCryptographer(); - - // Preserve unknown fields. - const sync_pb::EntitySpecifics& old_specifics = entry_->Get(SPECIFICS); - sync_pb::EntitySpecifics new_specifics; - new_specifics.CopyFrom(new_value); - new_specifics.mutable_unknown_fields()->MergeFrom( - old_specifics.unknown_fields()); - - // Will update the entry if encryption was necessary. - if (!UpdateEntryWithEncryption(cryptographer, new_specifics, entry_)) { - return; - } - if (entry_->Get(SPECIFICS).has_encrypted()) { - // EncryptIfNecessary already updated the entry for us and marked for - // syncing if it was needed. Now we just make a copy of the unencrypted - // specifics so that if this node is updated, we do not have to decrypt the - // old data. Note that this only modifies the node's local data, not the - // entry itself. - SetUnencryptedSpecifics(new_value); - } - - DCHECK_EQ(new_specifics_type, GetModelType()); -} - -void WriteNode::ResetFromSpecifics() { - SetEntitySpecifics(GetEntitySpecifics()); -} - -void WriteNode::SetTypedUrlSpecifics( - const sync_pb::TypedUrlSpecifics& new_value) { - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_typed_url()->CopyFrom(new_value); - SetEntitySpecifics(entity_specifics); -} - -void WriteNode::SetExtensionSpecifics( - const sync_pb::ExtensionSpecifics& new_value) { - sync_pb::EntitySpecifics entity_specifics; - entity_specifics.mutable_extension()->CopyFrom(new_value); - SetEntitySpecifics(entity_specifics); -} - -void WriteNode::SetExternalId(int64 id) { - if (GetExternalId() != id) - entry_->Put(syncable::LOCAL_EXTERNAL_ID, id); -} - -WriteNode::WriteNode(WriteTransaction* transaction) - : entry_(NULL), transaction_(transaction) { - DCHECK(transaction); -} - -WriteNode::~WriteNode() { - delete entry_; -} - -// Find an existing node matching the ID |id|, and bind this WriteNode to it. -// Return true on success. -BaseNode::InitByLookupResult WriteNode::InitByIdLookup(int64 id) { - DCHECK(!entry_) << "Init called twice"; - DCHECK_NE(id, kInvalidId); - entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), - syncable::GET_BY_HANDLE, id); - if (!entry_->good()) - return INIT_FAILED_ENTRY_NOT_GOOD; - if (entry_->Get(syncable::IS_DEL)) - return INIT_FAILED_ENTRY_IS_DEL; - return DecryptIfNecessary() ? INIT_OK : INIT_FAILED_DECRYPT_IF_NECESSARY; -} - -// Find a node by client tag, and bind this WriteNode to it. -// Return true if the write node was found, and was not deleted. -// Undeleting a deleted node is possible by ClientTag. -BaseNode::InitByLookupResult WriteNode::InitByClientTagLookup( - syncable::ModelType model_type, - const std::string& tag) { - DCHECK(!entry_) << "Init called twice"; - if (tag.empty()) - return INIT_FAILED_PRECONDITION; - - const std::string hash = GenerateSyncableHash(model_type, tag); - - entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), - syncable::GET_BY_CLIENT_TAG, hash); - if (!entry_->good()) - return INIT_FAILED_ENTRY_NOT_GOOD; - if (entry_->Get(syncable::IS_DEL)) - return INIT_FAILED_ENTRY_IS_DEL; - return DecryptIfNecessary() ? INIT_OK : INIT_FAILED_DECRYPT_IF_NECESSARY; -} - -BaseNode::InitByLookupResult WriteNode::InitByTagLookup( - const std::string& tag) { - DCHECK(!entry_) << "Init called twice"; - if (tag.empty()) - return INIT_FAILED_PRECONDITION; - entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), - syncable::GET_BY_SERVER_TAG, tag); - if (!entry_->good()) - return INIT_FAILED_ENTRY_NOT_GOOD; - if (entry_->Get(syncable::IS_DEL)) - return INIT_FAILED_ENTRY_IS_DEL; - syncable::ModelType model_type = GetModelType(); - DCHECK_EQ(syncable::NIGORI, model_type); - return INIT_OK; -} - -void WriteNode::PutModelType(syncable::ModelType model_type) { - // Set an empty specifics of the appropriate datatype. The presence - // of the specific field will identify the model type. - DCHECK(GetModelType() == model_type || - GetModelType() == syncable::UNSPECIFIED); // Immutable once set. - - sync_pb::EntitySpecifics specifics; - syncable::AddDefaultFieldValue(model_type, &specifics); - SetEntitySpecifics(specifics); -} - -// Create a new node with default properties, and bind this WriteNode to it. -// Return true on success. -bool WriteNode::InitByCreation(syncable::ModelType model_type, - const BaseNode& parent, - const BaseNode* predecessor) { - DCHECK(!entry_) << "Init called twice"; - // |predecessor| must be a child of |parent| or NULL. - if (predecessor && predecessor->GetParentId() != parent.GetId()) { - DCHECK(false); - return false; - } - - syncable::Id parent_id = parent.GetEntry()->Get(syncable::ID); - - // Start out with a dummy name. We expect - // the caller to set a meaningful name after creation. - string dummy(kDefaultNameForNewNodes); - - entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), - syncable::CREATE, parent_id, dummy); - - if (!entry_->good()) - return false; - - // Entries are untitled folders by default. - entry_->Put(syncable::IS_DIR, true); - - PutModelType(model_type); - - // Now set the predecessor, which sets IS_UNSYNCED as necessary. - return PutPredecessor(predecessor); -} - -// Create a new node with default properties and a client defined unique tag, -// and bind this WriteNode to it. -// Return true on success. If the tag exists in the database, then -// we will attempt to undelete the node. -// TODO(chron): Code datatype into hash tag. -// TODO(chron): Is model type ever lost? -bool WriteNode::InitUniqueByCreation(syncable::ModelType model_type, - const BaseNode& parent, - const std::string& tag) { - DCHECK(!entry_) << "Init called twice"; - if (tag.empty()) { - LOG(WARNING) << "InitUniqueByCreation failed due to empty tag."; - return false; - } - - const std::string hash = GenerateSyncableHash(model_type, tag); - - syncable::Id parent_id = parent.GetEntry()->Get(syncable::ID); - - // Start out with a dummy name. We expect - // the caller to set a meaningful name after creation. - string dummy(kDefaultNameForNewNodes); - - // Check if we have this locally and need to undelete it. - scoped_ptr<syncable::MutableEntry> existing_entry( - new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), - syncable::GET_BY_CLIENT_TAG, hash)); - - if (existing_entry->good()) { - if (existing_entry->Get(syncable::IS_DEL)) { - // Rules for undelete: - // BASE_VERSION: Must keep the same. - // ID: Essential to keep the same. - // META_HANDLE: Must be the same, so we can't "split" the entry. - // IS_DEL: Must be set to false, will cause reindexing. - // This one is weird because IS_DEL is true for "update only" - // items. It should be OK to undelete an update only. - // MTIME/CTIME: Seems reasonable to just leave them alone. - // IS_UNSYNCED: Must set this to true or face database insurrection. - // We do this below this block. - // IS_UNAPPLIED_UPDATE: Either keep it the same or also set BASE_VERSION - // to SERVER_VERSION. We keep it the same here. - // IS_DIR: We'll leave it the same. - // SPECIFICS: Reset it. - - existing_entry->Put(syncable::IS_DEL, false); - - // Client tags are immutable and must be paired with the ID. - // If a server update comes down with an ID and client tag combo, - // and it already exists, always overwrite it and store only one copy. - // We have to undelete entries because we can't disassociate IDs from - // tags and updates. - - existing_entry->Put(syncable::NON_UNIQUE_NAME, dummy); - existing_entry->Put(syncable::PARENT_ID, parent_id); - entry_ = existing_entry.release(); - } else { - return false; - } - } else { - entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), - syncable::CREATE, parent_id, dummy); - if (!entry_->good()) { - return false; - } - - // Only set IS_DIR for new entries. Don't bitflip undeleted ones. - entry_->Put(syncable::UNIQUE_CLIENT_TAG, hash); - } - - // We don't support directory and tag combinations. - entry_->Put(syncable::IS_DIR, false); - - // Will clear specifics data. - PutModelType(model_type); - - // Now set the predecessor, which sets IS_UNSYNCED as necessary. - return PutPredecessor(NULL); -} - -bool WriteNode::SetPosition(const BaseNode& new_parent, - const BaseNode* predecessor) { - // |predecessor| must be a child of |new_parent| or NULL. - if (predecessor && predecessor->GetParentId() != new_parent.GetId()) { - DCHECK(false); - return false; - } - - syncable::Id new_parent_id = new_parent.GetEntry()->Get(syncable::ID); - - // Filter out redundant changes if both the parent and the predecessor match. - if (new_parent_id == entry_->Get(syncable::PARENT_ID)) { - const syncable::Id& old = entry_->Get(syncable::PREV_ID); - if ((!predecessor && old.IsRoot()) || - (predecessor && (old == predecessor->GetEntry()->Get(syncable::ID)))) { - return true; - } - } - - // Atomically change the parent. This will fail if it would - // introduce a cycle in the hierarchy. - if (!entry_->Put(syncable::PARENT_ID, new_parent_id)) - return false; - - // Now set the predecessor, which sets IS_UNSYNCED as necessary. - return PutPredecessor(predecessor); -} - -const syncable::Entry* WriteNode::GetEntry() const { - return entry_; -} - -const BaseTransaction* WriteNode::GetTransaction() const { - return transaction_; -} - -void WriteNode::Remove() { - entry_->Put(syncable::IS_DEL, true); - MarkForSyncing(); -} - -bool WriteNode::PutPredecessor(const BaseNode* predecessor) { - syncable::Id predecessor_id = predecessor ? - predecessor->GetEntry()->Get(syncable::ID) : syncable::Id(); - if (!entry_->PutPredecessor(predecessor_id)) - return false; - // Mark this entry as unsynced, to wake up the syncer. - MarkForSyncing(); - - return true; -} - -void WriteNode::SetFaviconBytes(const vector<unsigned char>& bytes) { - sync_pb::BookmarkSpecifics new_value = GetBookmarkSpecifics(); - new_value.set_favicon(bytes.empty() ? NULL : &bytes[0], bytes.size()); - SetBookmarkSpecifics(new_value); -} - -void WriteNode::MarkForSyncing() { - syncable::MarkForSyncing(entry_); -} - -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/write_node.h b/chrome/browser/sync/internal_api/write_node.h deleted file mode 100644 index 7c55ddd..0000000 --- a/chrome/browser/sync/internal_api/write_node.h +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_INTERNAL_API_WRITE_NODE_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_WRITE_NODE_H_ -#pragma once - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "chrome/browser/sync/internal_api/base_node.h" -#include "sync/syncable/model_type.h" - -namespace browser_sync { -class Cryptographer; -class TestBookmarkModelAssociator; -} - -namespace syncable { -class Entry; -class MutableEntry; -} - -namespace sync_pb { -class AppSpecifics; -class AutofillSpecifics; -class AutofillProfileSpecifics; -class BookmarkSpecifics; -class EntitySpecifics; -class ExtensionSpecifics; -class SessionSpecifics; -class NigoriSpecifics; -class PasswordSpecificsData; -class ThemeSpecifics; -class TypedUrlSpecifics; -} - -namespace sync_api { - -class WriteTransaction; - -// WriteNode extends BaseNode to add mutation, and wraps -// syncable::MutableEntry. A WriteTransaction is needed to create a WriteNode. -class WriteNode : public BaseNode { - public: - // Create a WriteNode using the given transaction. - explicit WriteNode(WriteTransaction* transaction); - virtual ~WriteNode(); - - // A client must use one (and only one) of the following Init variants to - // populate the node. - - // BaseNode implementation. - virtual InitByLookupResult InitByIdLookup(int64 id) OVERRIDE; - virtual InitByLookupResult InitByClientTagLookup( - syncable::ModelType model_type, - const std::string& tag) OVERRIDE; - - // Create a new node with the specified parent and predecessor. |model_type| - // dictates the type of the item, and controls which EntitySpecifics proto - // extension can be used with this item. Use a NULL |predecessor| - // to indicate that this is to be the first child. - // |predecessor| must be a child of |new_parent| or NULL. Returns false on - // failure. - bool InitByCreation(syncable::ModelType model_type, - const BaseNode& parent, - const BaseNode* predecessor); - - // Create nodes using this function if they're unique items that - // you want to fetch using client_tag. Note that the behavior of these - // items is slightly different than that of normal items. - // Most importantly, if it exists locally, this function will - // actually undelete it - // Client unique tagged nodes must NOT be folders. - bool InitUniqueByCreation(syncable::ModelType model_type, - const BaseNode& parent, - const std::string& client_tag); - - // Each server-created permanent node is tagged with a unique string. - // Look up the node with the particular tag. If it does not exist, - // return false. - InitByLookupResult InitByTagLookup(const std::string& tag); - - // These Set() functions correspond to the Get() functions of BaseNode. - void SetIsFolder(bool folder); - void SetTitle(const std::wstring& title); - - // External ID is a client-only field, so setting it doesn't cause the item to - // be synced again. - void SetExternalId(int64 external_id); - - // Remove this node and its children. - void Remove(); - - // Set a new parent and position. Position is specified by |predecessor|; if - // it is NULL, the node is moved to the first position. |predecessor| must - // be a child of |new_parent| or NULL. Returns false on failure.. - bool SetPosition(const BaseNode& new_parent, const BaseNode* predecessor); - - // Set the bookmark specifics (url and favicon). - // Should only be called if GetModelType() == BOOKMARK. - void SetBookmarkSpecifics(const sync_pb::BookmarkSpecifics& specifics); - - // Legacy, bookmark-specific setters that wrap SetBookmarkSpecifics() above. - // Should only be called if GetModelType() == BOOKMARK. - // TODO(ncarter): Remove these two datatype-specific accessors. - void SetURL(const GURL& url); - void SetFaviconBytes(const std::vector<unsigned char>& bytes); - - // Generic set specifics method. Will extract the model type from |specifics|. - void SetEntitySpecifics(const sync_pb::EntitySpecifics& specifics); - - // Resets the EntitySpecifics for this node based on the unencrypted data. - // Will encrypt if necessary. - void ResetFromSpecifics(); - - // TODO(sync): Remove the setters below when the corresponding data - // types are ported to the new sync service API. - - // Set the app specifics (id, update url, enabled state, etc). - // Should only be called if GetModelType() == APPS. - void SetAppSpecifics(const sync_pb::AppSpecifics& specifics); - - // Set the autofill specifics (name and value). - // Should only be called if GetModelType() == AUTOFILL. - void SetAutofillSpecifics(const sync_pb::AutofillSpecifics& specifics); - - void SetAutofillProfileSpecifics( - const sync_pb::AutofillProfileSpecifics& specifics); - - // Set the nigori specifics. - // Should only be called if GetModelType() == NIGORI. - void SetNigoriSpecifics(const sync_pb::NigoriSpecifics& specifics); - - // Set the password specifics. - // Should only be called if GetModelType() == PASSWORD. - void SetPasswordSpecifics(const sync_pb::PasswordSpecificsData& specifics); - - // Set the theme specifics (name and value). - // Should only be called if GetModelType() == THEME. - void SetThemeSpecifics(const sync_pb::ThemeSpecifics& specifics); - - // Set the typed_url specifics (url, title, typed_count, etc). - // Should only be called if GetModelType() == TYPED_URLS. - void SetTypedUrlSpecifics(const sync_pb::TypedUrlSpecifics& specifics); - - // Set the extension specifics (id, update url, enabled state, etc). - // Should only be called if GetModelType() == EXTENSIONS. - void SetExtensionSpecifics(const sync_pb::ExtensionSpecifics& specifics); - - // Set the session specifics (windows, tabs, navigations etc.). - // Should only be called if GetModelType() == SESSIONS. - void SetSessionSpecifics(const sync_pb::SessionSpecifics& specifics); - - // Implementation of BaseNode's abstract virtual accessors. - virtual const syncable::Entry* GetEntry() const OVERRIDE; - - virtual const BaseTransaction* GetTransaction() const OVERRIDE; - - private: - friend class browser_sync::TestBookmarkModelAssociator; - FRIEND_TEST_ALL_PREFIXES(SyncManagerTest, EncryptBookmarksWithLegacyData); - - void* operator new(size_t size); // Node is meant for stack use only. - - // Helper to set model type. This will clear any specifics data. - void PutModelType(syncable::ModelType model_type); - - // Helper to set the previous node. - bool PutPredecessor(const BaseNode* predecessor) WARN_UNUSED_RESULT; - - // Sets IS_UNSYNCED and SYNCING to ensure this entry is considered in an - // upcoming commit pass. - void MarkForSyncing(); - - // The underlying syncable object which this class wraps. - syncable::MutableEntry* entry_; - - // The sync API transaction that is the parent of this node. - WriteTransaction* transaction_; - - DISALLOW_COPY_AND_ASSIGN(WriteNode); -}; - -} // namespace sync_api - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_WRITE_NODE_H_ diff --git a/chrome/browser/sync/internal_api/write_transaction.cc b/chrome/browser/sync/internal_api/write_transaction.cc deleted file mode 100644 index 6ce4cbb..0000000 --- a/chrome/browser/sync/internal_api/write_transaction.cc +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/internal_api/write_transaction.h" - -#include "sync/syncable/syncable.h" - -namespace sync_api { - -////////////////////////////////////////////////////////////////////////// -// WriteTransaction member definitions -WriteTransaction::WriteTransaction(const tracked_objects::Location& from_here, - UserShare* share) - : BaseTransaction(share), - transaction_(NULL) { - transaction_ = new syncable::WriteTransaction(from_here, syncable::SYNCAPI, - share->directory.get()); -} - -WriteTransaction::~WriteTransaction() { - delete transaction_; -} - -syncable::BaseTransaction* WriteTransaction::GetWrappedTrans() const { - return transaction_; -} - -} // namespace sync_api diff --git a/chrome/browser/sync/internal_api/write_transaction.h b/chrome/browser/sync/internal_api/write_transaction.h deleted file mode 100644 index 0c2a1ad..0000000 --- a/chrome/browser/sync/internal_api/write_transaction.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2011 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_SYNC_INTERNAL_API_WRITE_TRANSACTION_H_ -#define CHROME_BROWSER_SYNC_INTERNAL_API_WRITE_TRANSACTION_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "chrome/browser/sync/internal_api/base_transaction.h" - -namespace syncable { -class BaseTransaction; -class WriteTransaction; -} // namespace syncable - -namespace tracked_objects { -class Location; -} // namespace tracked_objects - -namespace sync_api { - -// Sync API's WriteTransaction is a read/write BaseTransaction. It wraps -// a syncable::WriteTransaction. -// -// NOTE: Only a single model type can be mutated for a given -// WriteTransaction. -class WriteTransaction : public BaseTransaction { - public: - // Start a new read/write transaction. - WriteTransaction(const tracked_objects::Location& from_here, - UserShare* share); - virtual ~WriteTransaction(); - - // Provide access to the syncable.h transaction from the API WriteNode. - virtual syncable::BaseTransaction* GetWrappedTrans() const OVERRIDE; - syncable::WriteTransaction* GetWrappedWriteTrans() { return transaction_; } - - protected: - WriteTransaction() {} - - void SetTransaction(syncable::WriteTransaction* trans) { - transaction_ = trans; - } - - private: - void* operator new(size_t size); // Transaction is meant for stack use only. - - // The underlying syncable object which this class wraps. - syncable::WriteTransaction* transaction_; - - DISALLOW_COPY_AND_ASSIGN(WriteTransaction); -}; - -} // namespace sync_api - -#endif // CHROME_BROWSER_SYNC_INTERNAL_API_WRITE_TRANSACTION_H_ diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index 27e3e56..3cc619b 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc @@ -39,8 +39,6 @@ #include "chrome/browser/sync/glue/session_data_type_controller.h" #include "chrome/browser/sync/glue/session_model_associator.h" #include "chrome/browser/sync/glue/typed_url_data_type_controller.h" -#include "chrome/browser/sync/internal_api/configure_reason.h" -#include "chrome/browser/sync/internal_api/sync_manager.h" #include "chrome/browser/sync/profile_sync_components_factory_impl.h" #include "chrome/browser/sync/sync_global_error.h" #include "chrome/browser/sync/user_selectable_sync_type.h" @@ -61,6 +59,7 @@ #include "content/public/browser/notification_source.h" #include "grit/generated_resources.h" #include "net/cookies/cookie_monster.h" +#include "sync/internal_api/configure_reason.h" #include "sync/js/js_arg_list.h" #include "sync/js/js_event_details.h" #include "sync/util/cryptographer.h" diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h index 3b37103..bfbeb92 100644 --- a/chrome/browser/sync/profile_sync_service.h +++ b/chrome/browser/sync/profile_sync_service.h @@ -25,7 +25,6 @@ #include "chrome/browser/sync/glue/data_type_controller.h" #include "chrome/browser/sync/glue/data_type_manager.h" #include "chrome/browser/sync/glue/sync_backend_host.h" -#include "chrome/browser/sync/internal_api/sync_manager.h" #include "chrome/browser/sync/profile_sync_service_observer.h" #include "chrome/browser/sync/sync_prefs.h" #include "chrome/common/net/gaia/google_service_auth_error.h" diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc index b3301fe..25bb06b 100644 --- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc @@ -32,10 +32,6 @@ #include "chrome/browser/sync/glue/data_type_controller.h" #include "chrome/browser/sync/glue/generic_change_processor.h" #include "chrome/browser/sync/glue/shared_change_processor.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/profile_sync_components_factory.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/profile_sync_test_util.h" @@ -51,6 +47,10 @@ #include "content/public/browser/notification_source.h" #include "content/test/test_browser_thread.h" #include "sync/engine/model_changing_syncer_command.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/read_transaction.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/autofill_specifics.pb.h" #include "sync/syncable/model_type.h" #include "sync/syncable/syncable.h" diff --git a/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc b/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc index 7353037..856e85f 100644 --- a/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc @@ -27,15 +27,15 @@ #include "chrome/browser/sync/glue/bookmark_model_associator.h" #include "chrome/browser/sync/glue/data_type_error_handler.h" #include "chrome/browser/sync/glue/data_type_error_handler_mock.h" -#include "chrome/browser/sync/internal_api/change_record.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" -#include "chrome/browser/sync/test/engine/test_user_share.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/testing_profile.h" #include "content/test/test_browser_thread.h" +#include "sync/internal_api/change_record.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/read_transaction.h" +#include "sync/internal_api/test_user_share.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/test/engine/test_id_factory.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/sync/profile_sync_service_password_unittest.cc b/chrome/browser/sync/profile_sync_service_password_unittest.cc index 5577184..7185ea9 100644 --- a/chrome/browser/sync/profile_sync_service_password_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_password_unittest.cc @@ -23,10 +23,6 @@ #include "chrome/browser/sync/glue/password_change_processor.h" #include "chrome/browser/sync/glue/password_data_type_controller.h" #include "chrome/browser/sync/glue/password_model_associator.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/profile_sync_components_factory.h" #include "chrome/browser/sync/profile_sync_components_factory_mock.h" #include "chrome/browser/sync/profile_sync_service.h" @@ -39,6 +35,10 @@ #include "content/public/browser/notification_source.h" #include "content/test/notification_observer_mock.h" #include "content/test/test_browser_thread.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/read_transaction.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/password_specifics.pb.h" #include "sync/syncable/syncable.h" #include "sync/test/engine/test_id_factory.h" diff --git a/chrome/browser/sync/profile_sync_service_preference_unittest.cc b/chrome/browser/sync/profile_sync_service_preference_unittest.cc index 4ddd687..efd63db 100644 --- a/chrome/browser/sync/profile_sync_service_preference_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_preference_unittest.cc @@ -23,17 +23,17 @@ #include "chrome/browser/sync/glue/generic_change_processor.h" #include "chrome/browser/sync/glue/sync_backend_host.h" #include "chrome/browser/sync/glue/ui_data_type_controller.h" -#include "chrome/browser/sync/internal_api/change_record.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/profile_sync_test_util.h" #include "chrome/browser/sync/test_profile_sync_service.h" #include "chrome/common/net/gaia/gaia_constants.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_pref_service.h" #include "chrome/test/base/testing_profile.h" +#include "sync/internal_api/change_record.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/read_transaction.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/preference_specifics.pb.h" #include "sync/syncable/model_type.h" #include "testing/gmock/include/gmock/gmock.h" diff --git a/chrome/browser/sync/profile_sync_service_session_unittest.cc b/chrome/browser/sync/profile_sync_service_session_unittest.cc index 2a32d8d..2991b0d 100644 --- a/chrome/browser/sync/profile_sync_service_session_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_session_unittest.cc @@ -23,11 +23,6 @@ #include "chrome/browser/sync/glue/session_data_type_controller.h" #include "chrome/browser/sync/glue/session_model_associator.h" #include "chrome/browser/sync/glue/sync_backend_host.h" -#include "chrome/browser/sync/internal_api/change_record.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/profile_sync_components_factory_mock.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/profile_sync_test_util.h" @@ -42,6 +37,11 @@ #include "content/public/browser/notification_service.h" #include "content/test/test_browser_thread.h" #include "googleurl/src/gurl.h" +#include "sync/internal_api/change_record.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/read_transaction.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/session_specifics.pb.h" #include "sync/protocol/sync.pb.h" #include "sync/syncable/model_type.h" diff --git a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc index c4862ea..953592b 100644 --- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc @@ -27,10 +27,6 @@ #include "chrome/browser/sync/glue/typed_url_change_processor.h" #include "chrome/browser/sync/glue/typed_url_data_type_controller.h" #include "chrome/browser/sync/glue/typed_url_model_associator.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" -#include "chrome/browser/sync/internal_api/write_node.h" -#include "chrome/browser/sync/internal_api/write_transaction.h" #include "chrome/browser/sync/profile_sync_components_factory.h" #include "chrome/browser/sync/profile_sync_components_factory_mock.h" #include "chrome/browser/sync/profile_sync_service.h" @@ -42,6 +38,10 @@ #include "chrome/test/base/testing_profile.h" #include "content/public/browser/notification_service.h" #include "googleurl/src/gurl.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/read_transaction.h" +#include "sync/internal_api/write_node.h" +#include "sync/internal_api/write_transaction.h" #include "sync/protocol/typed_url_specifics.pb.h" #include "sync/syncable/syncable.h" #include "sync/test/engine/test_id_factory.h" diff --git a/chrome/browser/sync/test/engine/test_user_share.cc b/chrome/browser/sync/test/engine/test_user_share.cc deleted file mode 100644 index 630c6c7..0000000 --- a/chrome/browser/sync/test/engine/test_user_share.cc +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/test/engine/test_user_share.h" - -#include "base/compiler_specific.h" - -namespace browser_sync { - -TestUserShare::TestUserShare() {} - -TestUserShare::~TestUserShare() { - if (user_share_.get()) - ADD_FAILURE() << "Should have called TestUserShare::TearDown()"; -} - -void TestUserShare::SetUp() { - user_share_.reset(new sync_api::UserShare()); - dir_maker_.SetUp(); - - // The pointer is owned by dir_maker_, we should not be storing it in a - // scoped_ptr. We must be careful to ensure the scoped_ptr never deletes it. - user_share_->directory.reset(dir_maker_.directory()); -} - -void TestUserShare::TearDown() { - // Ensure the scoped_ptr doesn't delete the memory we don't own. - ignore_result(user_share_->directory.release()); - - user_share_.reset(); - dir_maker_.TearDown(); -} - -sync_api::UserShare* TestUserShare::user_share() { - return user_share_.get(); -} - -} // namespace browser_sync diff --git a/chrome/browser/sync/test/engine/test_user_share.h b/chrome/browser/sync/test/engine/test_user_share.h deleted file mode 100644 index dc16c2b..0000000 --- a/chrome/browser/sync/test/engine/test_user_share.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// A handy class that takes care of setting up and destroying a -// sync_api::UserShare instance for unit tests that require one. -// -// The expected usage is to make this a component of your test fixture: -// -// class AwesomenessTest : public testing::Test { -// public: -// virtual void SetUp() { -// test_user_share_.SetUp(); -// } -// virtual void TearDown() { -// test_user_share_.TearDown(); -// } -// protected: -// TestUserShare test_user_share_; -// }; -// -// Then, in your tests: -// -// TEST_F(AwesomenessTest, IsMaximal) { -// sync_api::ReadTransaction trans(test_user_share_.user_share()); -// ... -// } -// - -#ifndef CHROME_BROWSER_SYNC_TEST_ENGINE_TEST_USER_SHARE_H_ -#define CHROME_BROWSER_SYNC_TEST_ENGINE_TEST_USER_SHARE_H_ -#pragma once - -#include "base/basictypes.h" -#include "chrome/browser/sync/internal_api/user_share.h" -#include "sync/test/engine/test_directory_setter_upper.h" - -namespace browser_sync { - -class TestUserShare { - public: - TestUserShare(); - ~TestUserShare(); - - // Sets up the UserShare instance. Clears any existing database - // backing files that might exist on disk. - void SetUp(); - - // Undo everything done by SetUp(): closes the UserShare and deletes - // the backing files. Before closing the directory, this will run - // the directory invariant checks and perform the SaveChanges action - // on the user share's directory. - void TearDown(); - - // Non-NULL iff called between a call to SetUp() and TearDown(). - sync_api::UserShare* user_share(); - - private: - TestDirectorySetterUpper dir_maker_; - scoped_ptr<sync_api::UserShare> user_share_; - - DISALLOW_COPY_AND_ASSIGN(TestUserShare); -}; - -} // namespace browser_sync - -#endif // CHROME_BROWSER_SYNC_TEST_ENGINE_TEST_USER_SHARE_H_ diff --git a/chrome/browser/sync/test/integration/enable_disable_test.cc b/chrome/browser/sync/test/integration/enable_disable_test.cc index 29b6275..3fd4769 100644 --- a/chrome/browser/sync/test/integration/enable_disable_test.cc +++ b/chrome/browser/sync/test/integration/enable_disable_test.cc @@ -4,9 +4,9 @@ #include "chrome/browser/sync/test/integration/sync_test.h" -#include "chrome/browser/sync/internal_api/read_node.h" -#include "chrome/browser/sync/internal_api/read_transaction.h" #include "chrome/browser/sync/profile_sync_service_harness.h" +#include "sync/internal_api/read_node.h" +#include "sync/internal_api/read_transaction.h" #include "sync/syncable/model_type.h" // This file contains tests that exercise enabling and disabling data diff --git a/chrome/browser/sync/test/test_http_bridge_factory.h b/chrome/browser/sync/test/test_http_bridge_factory.h index d39f72c..302528b 100644 --- a/chrome/browser/sync/test/test_http_bridge_factory.h +++ b/chrome/browser/sync/test/test_http_bridge_factory.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -7,8 +7,8 @@ #pragma once #include "base/compiler_specific.h" -#include "chrome/browser/sync/internal_api/http_post_provider_interface.h" -#include "chrome/browser/sync/internal_api/http_post_provider_factory.h" +#include "sync/internal_api/http_post_provider_factory.h" +#include "sync/internal_api/http_post_provider_interface.h" namespace browser_sync { diff --git a/chrome/browser/sync/test_profile_sync_service.cc b/chrome/browser/sync/test_profile_sync_service.cc index 40977f8a..83e04c5 100644 --- a/chrome/browser/sync/test_profile_sync_service.cc +++ b/chrome/browser/sync/test_profile_sync_service.cc @@ -8,10 +8,10 @@ #include "chrome/browser/sync/abstract_profile_sync_service_test.h" #include "chrome/browser/sync/glue/data_type_controller.h" #include "chrome/browser/sync/glue/sync_backend_host.h" -#include "chrome/browser/sync/internal_api/user_share.h" #include "chrome/browser/sync/profile_sync_components_factory.h" #include "chrome/browser/sync/test/test_http_bridge_factory.h" #include "chrome/common/chrome_notification_types.h" +#include "sync/internal_api/user_share.h" #include "sync/js/js_reply_handler.h" #include "sync/protocol/encryption.pb.h" #include "sync/sessions/session_state.h" |