#include "sync/internal_api/public/internal_components_factory.h"
#include "sync/internal_api/public/read_node.h"
#include "sync/internal_api/public/read_transaction.h"
+#include "sync/internal_api/public/sync_core_proxy.h"
#include "sync/internal_api/public/user_share.h"
#include "sync/internal_api/public/util/experiments.h"
#include "sync/internal_api/public/write_node.h"
#include "sync/internal_api/public/write_transaction.h"
+#include "sync/internal_api/sync_core.h"
+#include "sync/internal_api/sync_core_proxy_impl.h"
#include "sync/internal_api/syncapi_internal.h"
#include "sync/internal_api/syncapi_server_connection_manager.h"
-#include "sync/js/js_arg_list.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/invalidation_util.h"
#include "sync/notifier/invalidator.h"
+#include "sync/notifier/object_id_invalidation_map.h"
#include "sync/protocol/proto_value_conversions.h"
#include "sync/protocol/sync.pb.h"
+#include "sync/sessions/directory_type_debug_info_emitter.h"
#include "sync/syncable/directory.h"
#include "sync/syncable/entry.h"
#include "sync/syncable/in_memory_directory_backing_store.h"
static const int kSyncRefreshDelayMsec = 500;
static const int kSyncSchedulerDelayMsec = 250;
-// Maximum count and size for traffic recorder.
-static const unsigned int kMaxMessagesToRecord = 10;
-static const unsigned int kMaxMessageSizeToRecord = 5 * 1024;
-
GetUpdatesCallerInfo::GetUpdatesSource GetSourceFromReason(
ConfigureReason reason) {
switch (reason) {
initialized_(false),
observing_network_connectivity_changes_(false),
invalidator_state_(DEFAULT_INVALIDATION_ERROR),
- traffic_recorder_(kMaxMessagesToRecord, kMaxMessageSizeToRecord),
- encryptor_(NULL),
report_unrecoverable_error_function_(NULL),
weak_ptr_factory_(this) {
// Pre-fill |notification_info_map_|.
notification_info_map_.insert(
std::make_pair(ModelTypeFromInt(i), NotificationInfo()));
}
-
- // Bind message handlers.
- BindJsMessageHandler(
- "getNotificationState",
- &SyncManagerImpl::GetNotificationState);
- BindJsMessageHandler(
- "getNotificationInfo",
- &SyncManagerImpl::GetNotificationInfo);
- BindJsMessageHandler(
- "getRootNodeDetails",
- &SyncManagerImpl::GetRootNodeDetails);
- BindJsMessageHandler(
- "getNodeSummariesById",
- &SyncManagerImpl::GetNodeSummariesById);
- BindJsMessageHandler(
- "getNodeDetailsById",
- &SyncManagerImpl::GetNodeDetailsById);
- BindJsMessageHandler(
- "getAllNodes",
- &SyncManagerImpl::GetAllNodes);
- BindJsMessageHandler(
- "getChildNodeIds",
- &SyncManagerImpl::GetChildNodeIds);
- BindJsMessageHandler(
- "getClientServerTraffic",
- &SyncManagerImpl::GetClientServerTraffic);
}
SyncManagerImpl::~SyncManagerImpl() {
ConfigurationParams params(GetSourceFromReason(reason),
to_download,
new_routing_info,
- ready_task);
+ ready_task,
+ retry_task);
scheduler_->Start(SyncScheduler::CONFIGURATION_MODE);
- if (!scheduler_->ScheduleConfiguration(params))
- retry_task.Run();
+ scheduler_->ScheduleConfiguration(params);
}
void SyncManagerImpl::Init(
int port,
bool use_ssl,
scoped_ptr<HttpPostProviderFactory> post_factory,
- const std::vector<ModelSafeWorker*>& workers,
+ const std::vector<scoped_refptr<ModelSafeWorker> >& workers,
ExtensionsActivity* extensions_activity,
SyncManager::ChangeDelegate* change_delegate,
const SyncCredentials& credentials,
database_path_ = database_location.Append(
syncable::Directory::kSyncDatabaseFilename);
- encryptor_ = encryptor;
unrecoverable_error_handler_ = unrecoverable_error_handler.Pass();
report_unrecoverable_error_function_ = report_unrecoverable_error_function;
std::string sync_id = directory()->cache_guid();
+ DVLOG(1) << "Setting sync client ID: " << sync_id;
allstatus_.SetSyncId(sync_id);
+ DVLOG(1) << "Setting invalidator client ID: " << invalidator_client_id;
allstatus_.SetInvalidatorClientId(invalidator_client_id);
- DVLOG(1) << "Setting sync client ID: " << sync_id;
- DVLOG(1) << "Setting invalidator client ID: " << invalidator_client_id;
+ model_type_registry_.reset(new ModelTypeRegistry(workers, directory()));
+
+ sync_core_.reset(new SyncCore(model_type_registry_.get()));
+
+ // Bind the SyncCore WeakPtr to this thread. This helps us crash earlier if
+ // the pointer is misused in debug mode.
+ base::WeakPtr<SyncCore> weak_core = sync_core_->AsWeakPtr();
+ weak_core.get();
+
+ sync_core_proxy_.reset(
+ new SyncCoreProxyImpl(base::MessageLoopProxy::current(), weak_core));
// Build a SyncSessionContext and store the worker in it.
DVLOG(1) << "Sync is bringing up SyncSessionContext.";
session_context_ = internal_components_factory->BuildContext(
connection_manager_.get(),
directory(),
- workers,
extensions_activity,
listeners,
&debug_info_event_listener_,
- &traffic_recorder_,
+ model_type_registry_.get(),
invalidator_client_id).Pass();
session_context_->set_account_name(credentials.email);
scheduler_ = internal_components_factory->BuildScheduler(
// appropriately set and that it's only modified when switching to normal
// mode.
DCHECK(thread_checker_.CalledOnValidThread());
- session_context_->set_routing_info(routing_info);
+ session_context_->SetRoutingInfo(routing_info);
scheduler_->Start(SyncScheduler::NORMAL_MODE);
}
scheduler_.reset();
session_context_.reset();
+ model_type_registry_.reset();
if (sync_encryption_handler_) {
sync_encryption_handler_->RemoveObserver(&debug_info_event_listener_);
base::TimeDelta nudge_delay = NudgeStrategy::GetNudgeDelayTimeDelta(
types.First().Get(),
this);
- allstatus_.IncrementNudgeCounter(NUDGE_SOURCE_LOCAL);
scheduler_->ScheduleLocalNudge(nudge_delay,
types,
nudge_location);
}
-void SyncManagerImpl::OnSyncEngineEvent(const SyncEngineEvent& event) {
+void SyncManagerImpl::OnSyncCycleEvent(const SyncCycleEvent& 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
//
// 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) {
+ if (event.what_happened == SyncCycleEvent::SYNC_CYCLE_ENDED) {
if (!initialized_) {
- LOG(INFO) << "OnSyncCycleCompleted not sent because sync api is not "
- << "initialized";
+ DVLOG(1) << "OnSyncCycleCompleted not sent because sync api is not "
+ << "initialized";
return;
}
FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
OnSyncCycleCompleted(event.snapshot));
}
-
- if (event.what_happened == SyncEngineEvent::STOP_SYNCING_PERMANENTLY) {
- FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
- OnStopSyncingPermanently());
- return;
- }
-
- if (event.what_happened == SyncEngineEvent::ACTIONABLE_ERROR) {
- FOR_EACH_OBSERVER(
- SyncManager::Observer, observers_,
- OnActionableError(
- event.snapshot.model_neutral_state().sync_protocol_error));
- return;
- }
}
-void SyncManagerImpl::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_);
- js_sync_encryption_handler_observer_.SetJsEventHandler(js_event_handler_);
-}
-
-void SyncManagerImpl::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 SyncManagerImpl::OnActionableError(const SyncProtocolError& error) {
+ FOR_EACH_OBSERVER(
+ SyncManager::Observer, observers_,
+ OnActionableError(error));
}
-void SyncManagerImpl::BindJsMessageHandler(
- const std::string& name,
- UnboundJsMessageHandler unbound_message_handler) {
- js_message_handlers_[name] =
- base::Bind(unbound_message_handler, base::Unretained(this));
-}
-
-base::DictionaryValue* SyncManagerImpl::NotificationInfoToValue(
- const NotificationInfoMap& notification_info) {
- base::DictionaryValue* value = new base::DictionaryValue();
-
- for (NotificationInfoMap::const_iterator it = notification_info.begin();
- it != notification_info.end(); ++it) {
- const std::string model_type_str = ModelTypeToString(it->first);
- value->Set(model_type_str, it->second.ToValue());
- }
-
- return value;
-}
-
-std::string SyncManagerImpl::NotificationInfoToString(
- const NotificationInfoMap& notification_info) {
- scoped_ptr<base::DictionaryValue> value(
- NotificationInfoToValue(notification_info));
- std::string str;
- base::JSONWriter::Write(value.get(), &str);
- return str;
-}
-
-JsArgList SyncManagerImpl::GetNotificationState(
- const JsArgList& args) {
- const std::string& notification_state =
- InvalidatorStateToString(invalidator_state_);
- DVLOG(1) << "GetNotificationState: " << notification_state;
- base::ListValue return_args;
- return_args.Append(new base::StringValue(notification_state));
- return JsArgList(&return_args);
-}
-
-JsArgList SyncManagerImpl::GetNotificationInfo(
- const JsArgList& args) {
- DVLOG(1) << "GetNotificationInfo: "
- << NotificationInfoToString(notification_info_map_);
- base::ListValue return_args;
- return_args.Append(NotificationInfoToValue(notification_info_map_));
- return JsArgList(&return_args);
-}
-
-JsArgList SyncManagerImpl::GetRootNodeDetails(
- const JsArgList& args) {
- ReadTransaction trans(FROM_HERE, GetUserShare());
- ReadNode root(&trans);
- root.InitByRootLookup();
- base::ListValue return_args;
- return_args.Append(root.GetDetailsAsValue());
- return JsArgList(&return_args);
-}
-
-JsArgList SyncManagerImpl::GetClientServerTraffic(
- const JsArgList& args) {
- base::ListValue return_args;
- base::ListValue* value = traffic_recorder_.ToValue();
- if (value != NULL)
- return_args.Append(value);
- return JsArgList(&return_args);
-}
-
-namespace {
-
-int64 GetId(const base::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,
- base::DictionaryValue* (BaseNode::*info_getter)() const) {
- CHECK(info_getter);
- base::ListValue return_args;
- base::ListValue* node_summaries = new base::ListValue();
- return_args.Append(node_summaries);
- const base::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) != BaseNode::INIT_OK) {
- continue;
- }
- node_summaries->Append((node.*info_getter)());
- }
- }
- return JsArgList(&return_args);
-}
+void SyncManagerImpl::OnRetryTimeChanged(base::Time) {}
-} // namespace
+void SyncManagerImpl::OnThrottledTypesChanged(ModelTypeSet) {}
-JsArgList SyncManagerImpl::GetNodeSummariesById(const JsArgList& args) {
- return GetNodeInfoById(args, GetUserShare(), &BaseNode::GetSummaryAsValue);
+void SyncManagerImpl::OnMigrationRequested(ModelTypeSet types) {
+ FOR_EACH_OBSERVER(
+ SyncManager::Observer, observers_,
+ OnMigrationRequested(types));
}
-JsArgList SyncManagerImpl::GetNodeDetailsById(const JsArgList& args) {
- return GetNodeInfoById(args, GetUserShare(), &BaseNode::GetDetailsAsValue);
+void SyncManagerImpl::OnProtocolEvent(const ProtocolEvent& event) {
+ protocol_event_buffer_.RecordProtocolEvent(event);
+ FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+ OnProtocolEvent(event));
}
-JsArgList SyncManagerImpl::GetAllNodes(const JsArgList& args) {
- base::ListValue return_args;
- base::ListValue* result = new base::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(trans.GetCryptographer()));
+void SyncManagerImpl::SetJsEventHandler(
+ const WeakHandle<JsEventHandler>& event_handler) {
+ js_sync_manager_observer_.SetJsEventHandler(event_handler);
+ js_mutation_event_observer_.SetJsEventHandler(event_handler);
+ js_sync_encryption_handler_observer_.SetJsEventHandler(event_handler);
+}
+
+scoped_ptr<base::ListValue> SyncManagerImpl::GetAllNodesForType(
+ syncer::ModelType type) {
+ DirectoryTypeDebugInfoEmitterMap* emitter_map =
+ model_type_registry_->directory_type_debug_info_emitter_map();
+ DirectoryTypeDebugInfoEmitterMap::iterator it = emitter_map->find(type);
+
+ if (it == emitter_map->end()) {
+ // This can happen in some cases. The UI thread makes requests of us
+ // when it doesn't really know which types are enabled or disabled.
+ DLOG(WARNING) << "Asked to return debug info for invalid type "
+ << ModelTypeToString(type);
+ return scoped_ptr<base::ListValue>();
}
- return JsArgList(&return_args);
-}
-
-JsArgList SyncManagerImpl::GetChildNodeIds(const JsArgList& args) {
- base::ListValue return_args;
- base::ListValue* child_ids = new base::ListValue();
- return_args.Append(child_ids);
- int64 id = GetId(args.Get(), 0);
- if (id != kInvalidId) {
- ReadTransaction trans(FROM_HERE, GetUserShare());
- syncable::Directory::Metahandles child_handles;
- trans.GetDirectory()->GetChildHandlesByHandle(trans.GetWrappedTrans(),
- id, &child_handles);
- for (syncable::Directory::Metahandles::const_iterator it =
- child_handles.begin(); it != child_handles.end(); ++it) {
- child_ids->Append(new base::StringValue(base::Int64ToString(*it)));
- }
- }
- return JsArgList(&return_args);
-}
-
-void SyncManagerImpl::UpdateNotificationInfo(
- const ObjectIdInvalidationMap& invalidation_map) {
- ObjectIdSet ids = invalidation_map.GetObjectIds();
- for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
- ModelType type = UNSPECIFIED;
- if (!ObjectIdToRealModelType(*it, &type)) {
- continue;
- }
- const SingleObjectInvalidationSet& type_invalidations =
- invalidation_map.ForObject(*it);
- for (SingleObjectInvalidationSet::const_iterator inv_it =
- type_invalidations.begin(); inv_it != type_invalidations.end();
- ++inv_it) {
- NotificationInfo* info = ¬ification_info_map_[type];
- info->total_count++;
- std::string payload =
- inv_it->is_unknown_version() ? "UNKNOWN" : inv_it->payload();
- info->payload = payload;
- }
- }
+ return it->second->GetAllNodes();
}
void SyncManagerImpl::OnInvalidatorStateChange(InvalidatorState state) {
(invalidator_state_ == INVALIDATIONS_ENABLED);
allstatus_.SetNotificationsEnabled(notifications_enabled);
scheduler_->SetNotificationsEnabled(notifications_enabled);
-
- if (js_event_handler_.IsInitialized()) {
- base::DictionaryValue details;
- details.SetString("state", state_str);
- js_event_handler_.Call(FROM_HERE,
- &JsEventHandler::HandleJsEvent,
- "onNotificationStateChange",
- JsEventDetails(&details));
- }
}
void SyncManagerImpl::OnIncomingInvalidation(
if (invalidation_map.Empty()) {
LOG(WARNING) << "Sync received invalidation without any type information.";
} else {
- allstatus_.IncrementNudgeCounter(NUDGE_SOURCE_NOTIFICATION);
scheduler_->ScheduleInvalidationNudge(
TimeDelta::FromMilliseconds(kSyncSchedulerDelayMsec),
invalidation_map, FROM_HERE);
- allstatus_.IncrementNotificationsReceived();
- UpdateNotificationInfo(invalidation_map);
debug_info_event_listener_.OnIncomingNotification(invalidation_map);
}
-
- if (js_event_handler_.IsInitialized()) {
- base::DictionaryValue details;
- base::ListValue* changed_types = new base::ListValue();
- details.Set("changedTypes", changed_types);
-
- ObjectIdSet id_set = invalidation_map.GetObjectIds();
- ModelTypeSet nudged_types = ObjectIdSetToModelTypeSet(id_set);
- DCHECK(!nudged_types.Empty());
- for (ModelTypeSet::Iterator it = nudged_types.First();
- it.Good(); it.Inc()) {
- const std::string model_type_str = ModelTypeToString(it.Get());
- changed_types->Append(new base::StringValue(model_type_str));
- }
- details.SetString("source", "REMOTE_INVALIDATION");
- js_event_handler_.Call(FROM_HERE,
- &JsEventHandler::HandleJsEvent,
- "onIncomingNotification",
- JsEventDetails(&details));
- }
}
+std::string SyncManagerImpl::GetOwnerName() const { return "SyncManagerImpl"; }
+
void SyncManagerImpl::RefreshTypes(ModelTypeSet types) {
DCHECK(thread_checker_.CalledOnValidThread());
if (types.Empty()) {
LOG(WARNING) << "Sync received refresh request with no types specified.";
} else {
- allstatus_.IncrementNudgeCounter(NUDGE_SOURCE_LOCAL_REFRESH);
scheduler_->ScheduleLocalRefreshRequest(
TimeDelta::FromMilliseconds(kSyncRefreshDelayMsec),
types, FROM_HERE);
}
-
- if (js_event_handler_.IsInitialized()) {
- base::DictionaryValue details;
- base::ListValue* changed_types = new base::ListValue();
- details.Set("changedTypes", changed_types);
- for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
- const std::string& model_type_str =
- ModelTypeToString(it.Get());
- changed_types->Append(new base::StringValue(model_type_str));
- }
- details.SetString("source", "LOCAL_INVALIDATION");
- js_event_handler_.Call(FROM_HERE,
- &JsEventHandler::HandleJsEvent,
- "onIncomingNotification",
- JsEventDetails(&details));
- }
}
SyncStatus SyncManagerImpl::GetDetailedStatus() const {
return &share_;
}
+syncer::SyncCoreProxy* SyncManagerImpl::GetSyncCoreProxy() {
+ DCHECK(initialized_);
+ return sync_core_proxy_.get();
+}
+
const std::string SyncManagerImpl::cache_guid() {
DCHECK(initialized_);
return directory()->cache_guid();
}
bool found_experiment = false;
- ReadNode autofill_culling_node(&trans);
- if (autofill_culling_node.InitByClientTagLookup(
- syncer::EXPERIMENTS,
- syncer::kAutofillCullingTag) == BaseNode::INIT_OK &&
- autofill_culling_node.GetExperimentsSpecifics().
- autofill_culling().enabled()) {
- experiments->autofill_culling = true;
- found_experiment = true;
- }
-
ReadNode favicon_sync_node(&trans);
if (favicon_sync_node.InitByClientTagLookup(
syncer::EXPERIMENTS,
// know about this.
}
+ ReadNode gcm_channel_node(&trans);
+ if (gcm_channel_node.InitByClientTagLookup(
+ syncer::EXPERIMENTS,
+ syncer::kGCMChannelTag) == BaseNode::INIT_OK &&
+ gcm_channel_node.GetExperimentsSpecifics().gcm_channel().has_enabled()) {
+ experiments->gcm_channel_state =
+ (gcm_channel_node.GetExperimentsSpecifics().gcm_channel().enabled() ?
+ syncer::Experiments::ENABLED : syncer::Experiments::SUPPRESSED);
+ found_experiment = true;
+ }
+
+ ReadNode enhanced_bookmarks_node(&trans);
+ if (enhanced_bookmarks_node.InitByClientTagLookup(
+ syncer::EXPERIMENTS, syncer::kEnhancedBookmarksTag) ==
+ BaseNode::INIT_OK &&
+ enhanced_bookmarks_node.GetExperimentsSpecifics()
+ .has_enhanced_bookmarks()) {
+ const sync_pb::EnhancedBookmarksFlags& enhanced_bookmarks =
+ enhanced_bookmarks_node.GetExperimentsSpecifics().enhanced_bookmarks();
+ if (enhanced_bookmarks.has_enabled())
+ experiments->enhanced_bookmarks_enabled = enhanced_bookmarks.enabled();
+ if (enhanced_bookmarks.has_extension_id()) {
+ experiments->enhanced_bookmarks_ext_id =
+ enhanced_bookmarks.extension_id();
+ }
+ found_experiment = true;
+ }
+
+ ReadNode gcm_invalidations_node(&trans);
+ if (gcm_invalidations_node.InitByClientTagLookup(
+ syncer::EXPERIMENTS, syncer::kGCMInvalidationsTag) ==
+ BaseNode::INIT_OK) {
+ const sync_pb::GcmInvalidationsFlags& gcm_invalidations =
+ gcm_invalidations_node.GetExperimentsSpecifics().gcm_invalidations();
+ if (gcm_invalidations.has_enabled()) {
+ experiments->gcm_invalidations_enabled = gcm_invalidations.enabled();
+ found_experiment = true;
+ }
+ }
+
return found_experiment;
}
return sync_encryption_handler_.get();
}
+ScopedVector<syncer::ProtocolEvent>
+ SyncManagerImpl::GetBufferedProtocolEvents() {
+ return protocol_event_buffer_.GetBufferedProtocolEvents();
+}
+
+void SyncManagerImpl::RegisterDirectoryTypeDebugInfoObserver(
+ syncer::TypeDebugInfoObserver* observer) {
+ model_type_registry_->RegisterDirectoryTypeDebugInfoObserver(observer);
+}
+
+void SyncManagerImpl::UnregisterDirectoryTypeDebugInfoObserver(
+ syncer::TypeDebugInfoObserver* observer) {
+ model_type_registry_->UnregisterDirectoryTypeDebugInfoObserver(observer);
+}
+
+bool SyncManagerImpl::HasDirectoryTypeDebugInfoObserver(
+ syncer::TypeDebugInfoObserver* observer) {
+ return model_type_registry_->HasDirectoryTypeDebugInfoObserver(observer);
+}
+
+void SyncManagerImpl::RequestEmitDebugInfo() {
+ model_type_registry_->RequestEmitDebugInfo();
+}
+
// static.
int SyncManagerImpl::GetDefaultNudgeDelay() {
return kDefaultNudgeDelayMilliseconds;