Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / sync / internal_api / sync_manager_impl.cc
index 336e57b..c2894b4 100644 (file)
 #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"
@@ -65,10 +66,6 @@ static const int kPreferencesNudgeDelayMilliseconds = 2000;
 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) {
@@ -172,8 +169,6 @@ SyncManagerImpl::SyncManagerImpl(const std::string& name)
       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_|.
@@ -181,32 +176,6 @@ SyncManagerImpl::SyncManagerImpl(const std::string& name)
     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() {
@@ -330,11 +299,11 @@ void SyncManagerImpl::ConfigureSyncer(
   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(
@@ -344,7 +313,7 @@ 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,
@@ -375,7 +344,6 @@ void SyncManagerImpl::Init(
 
   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;
 
@@ -422,11 +390,22 @@ void SyncManagerImpl::Init(
 
   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.";
@@ -436,11 +415,10 @@ void SyncManagerImpl::Init(
   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(
@@ -525,7 +503,7 @@ void SyncManagerImpl::StartSyncingNormally(
   // 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);
 }
 
@@ -637,6 +615,7 @@ void SyncManagerImpl::ShutdownOnSyncThread() {
 
   scheduler_.reset();
   session_context_.reset();
+  model_type_registry_.reset();
 
   if (sync_encryption_handler_) {
     sync_encryption_handler_->RemoveObserver(&debug_info_event_listener_);
@@ -916,13 +895,12 @@ void SyncManagerImpl::RequestNudgeForDataTypes(
   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
@@ -931,10 +909,10 @@ void SyncManagerImpl::OnSyncEngineEvent(const SyncEngineEvent& event) {
   //
   // 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;
     }
 
@@ -942,230 +920,52 @@ void SyncManagerImpl::OnSyncEngineEvent(const SyncEngineEvent& event) {
     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 = &notification_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) {
@@ -1178,15 +978,6 @@ 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(
@@ -1205,62 +996,24 @@ 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 {
@@ -1276,6 +1029,11 @@ UserShare* SyncManagerImpl::GetUserShare() {
   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();
@@ -1290,16 +1048,6 @@ bool SyncManagerImpl::ReceivedExperiment(Experiments* experiments) {
   }
   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,
@@ -1321,6 +1069,46 @@ bool SyncManagerImpl::ReceivedExperiment(Experiments* 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;
 }
 
@@ -1333,6 +1121,30 @@ SyncEncryptionHandler* SyncManagerImpl::GetEncryptionHandler() {
   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;