OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/sync/engine/syncapi.h" | 5 #include "chrome/browser/sync/engine/syncapi.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <bitset> | 8 #include <bitset> |
9 #include <iomanip> | 9 #include <iomanip> |
10 #include <list> | 10 #include <list> |
11 #include <map> | 11 #include <map> |
12 #include <queue> | 12 #include <queue> |
13 #include <string> | 13 #include <string> |
14 #include <vector> | 14 #include <vector> |
15 | 15 |
16 #include "base/base64.h" | 16 #include "base/base64.h" |
17 #include "base/bind.h" | 17 #include "base/bind.h" |
18 #include "base/callback.h" | 18 #include "base/callback.h" |
19 #include "base/command_line.h" | 19 #include "base/command_line.h" |
20 #include "base/compiler_specific.h" | 20 #include "base/compiler_specific.h" |
21 #include "base/json/json_writer.h" | 21 #include "base/json/json_writer.h" |
22 #include "base/logging.h" | 22 #include "base/logging.h" |
23 #include "base/memory/scoped_ptr.h" | 23 #include "base/memory/scoped_ptr.h" |
24 #include "base/message_loop.h" | 24 #include "base/message_loop.h" |
25 #include "base/observer_list.h" | 25 #include "base/observer_list.h" |
26 #include "base/sha1.h" | 26 #include "base/sha1.h" |
27 #include "base/string_number_conversions.h" | 27 #include "base/string_number_conversions.h" |
28 #include "base/string_util.h" | 28 #include "base/string_util.h" |
29 #include "base/synchronization/lock.h" | |
30 #include "base/task.h" | 29 #include "base/task.h" |
31 #include "base/time.h" | 30 #include "base/time.h" |
32 #include "base/utf_string_conversions.h" | 31 #include "base/utf_string_conversions.h" |
33 #include "base/values.h" | 32 #include "base/values.h" |
34 #include "chrome/browser/sync/engine/all_status.h" | 33 #include "chrome/browser/sync/engine/all_status.h" |
35 #include "chrome/browser/sync/engine/change_reorder_buffer.h" | 34 #include "chrome/browser/sync/engine/change_reorder_buffer.h" |
36 #include "chrome/browser/sync/engine/model_safe_worker.h" | 35 #include "chrome/browser/sync/engine/model_safe_worker.h" |
37 #include "chrome/browser/sync/engine/nudge_source.h" | 36 #include "chrome/browser/sync/engine/nudge_source.h" |
38 #include "chrome/browser/sync/engine/net/server_connection_manager.h" | 37 #include "chrome/browser/sync/engine/net/server_connection_manager.h" |
39 #include "chrome/browser/sync/engine/net/syncapi_server_connection_manager.h" | 38 #include "chrome/browser/sync/engine/net/syncapi_server_connection_manager.h" |
(...skipping 1212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1252 bool HaveObservers() const; | 1251 bool HaveObservers() const; |
1253 void AddObserver(SyncManager::Observer* observer); | 1252 void AddObserver(SyncManager::Observer* observer); |
1254 void RemoveObserver(SyncManager::Observer* observer); | 1253 void RemoveObserver(SyncManager::Observer* observer); |
1255 | 1254 |
1256 // Accessors for the private members. | 1255 // Accessors for the private members. |
1257 DirectoryManager* dir_manager() { return share_.dir_manager.get(); } | 1256 DirectoryManager* dir_manager() { return share_.dir_manager.get(); } |
1258 SyncAPIServerConnectionManager* connection_manager() { | 1257 SyncAPIServerConnectionManager* connection_manager() { |
1259 return connection_manager_.get(); | 1258 return connection_manager_.get(); |
1260 } | 1259 } |
1261 SyncScheduler* scheduler() { return scheduler_.get(); } | 1260 SyncScheduler* scheduler() { return scheduler_.get(); } |
1262 UserShare* GetUserShare() { return &share_; } | 1261 UserShare* GetUserShare() { |
1262 DCHECK(initialized_); | |
1263 return &share_; | |
1264 } | |
1263 | 1265 |
1264 // Return the currently active (validated) username for use with syncable | 1266 // Return the currently active (validated) username for use with syncable |
1265 // types. | 1267 // types. |
1266 const std::string& username_for_share() const { | 1268 const std::string& username_for_share() const { |
1267 return share_.name; | 1269 return share_.name; |
1268 } | 1270 } |
1269 | 1271 |
1270 Status GetStatus(); | 1272 Status GetStatus(); |
1271 | 1273 |
1272 void RequestNudge(const tracked_objects::Location& nudge_location); | 1274 void RequestNudge(const tracked_objects::Location& nudge_location); |
1273 | 1275 |
1274 void RequestNudgeWithDataTypes(const TimeDelta& delay, | 1276 void RequestNudgeWithDataTypes(const TimeDelta& delay, |
1275 browser_sync::NudgeSource source, const ModelTypeBitSet& types, | 1277 browser_sync::NudgeSource source, const ModelTypeBitSet& types, |
1276 const tracked_objects::Location& nudge_location); | 1278 const tracked_objects::Location& nudge_location); |
1277 | 1279 |
1278 void RequestEarlyExit(); | 1280 void RequestEarlyExit(); |
1279 | 1281 |
1280 // See SyncManager::Shutdown for information. | 1282 // See SyncManager::Shutdown for information. |
1281 void Shutdown(); | 1283 void Shutdown(); |
1282 | 1284 |
1283 // Whether we're initialized to the point of being able to accept changes | |
1284 // (and hence allow transaction creation). See initialized_ for details. | |
1285 bool initialized() const { | |
1286 base::AutoLock lock(initialized_mutex_); | |
1287 return initialized_; | |
1288 } | |
1289 | |
1290 // If this is a deletion for a password, sets the legacy | 1285 // If this is a deletion for a password, sets the legacy |
1291 // ExtraPasswordChangeRecordData field of |buffer|. Otherwise sets | 1286 // ExtraPasswordChangeRecordData field of |buffer|. Otherwise sets |
1292 // |buffer|'s specifics field to contain the unencrypted data. | 1287 // |buffer|'s specifics field to contain the unencrypted data. |
1293 void SetExtraChangeRecordData(int64 id, | 1288 void SetExtraChangeRecordData(int64 id, |
1294 syncable::ModelType type, | 1289 syncable::ModelType type, |
1295 ChangeReorderBuffer* buffer, | 1290 ChangeReorderBuffer* buffer, |
1296 Cryptographer* cryptographer, | 1291 Cryptographer* cryptographer, |
1297 const syncable::EntryKernel& original, | 1292 const syncable::EntryKernel& original, |
1298 bool existed_before, | 1293 bool existed_before, |
1299 bool exists_now); | 1294 bool exists_now); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1393 (SyncManager::SyncInternal::*UnboundJsMessageHandler)( | 1388 (SyncManager::SyncInternal::*UnboundJsMessageHandler)( |
1394 const browser_sync::JsArgList&); | 1389 const browser_sync::JsArgList&); |
1395 typedef base::Callback<browser_sync::JsArgList(browser_sync::JsArgList)> | 1390 typedef base::Callback<browser_sync::JsArgList(browser_sync::JsArgList)> |
1396 JsMessageHandler; | 1391 JsMessageHandler; |
1397 typedef std::map<std::string, JsMessageHandler> JsMessageHandlerMap; | 1392 typedef std::map<std::string, JsMessageHandler> JsMessageHandlerMap; |
1398 | 1393 |
1399 // Helper to call OnAuthError when no authentication credentials are | 1394 // Helper to call OnAuthError when no authentication credentials are |
1400 // available. | 1395 // available. |
1401 void RaiseAuthNeededEvent(); | 1396 void RaiseAuthNeededEvent(); |
1402 | 1397 |
1403 // Helper to set initialized_ to true and raise an event to clients to notify | |
1404 // that initialization is complete and it is safe to send us changes. If | |
1405 // already initialized, this is a no-op. | |
1406 void MarkAndNotifyInitializationComplete(); | |
1407 | |
1408 // Sends notifications to peers. | 1398 // Sends notifications to peers. |
1409 void SendNotification(); | 1399 void SendNotification(); |
1410 | 1400 |
1411 // Determine if the parents or predecessors differ between the old and new | 1401 // Determine if the parents or predecessors differ between the old and new |
1412 // versions of an entry stored in |a| and |b|. Note that a node's index may | 1402 // versions of an entry stored in |a| and |b|. Note that a node's index may |
1413 // change without its NEXT_ID changing if the node at NEXT_ID also moved (but | 1403 // change without its NEXT_ID changing if the node at NEXT_ID also moved (but |
1414 // the relative order is unchanged). To handle such cases, we rely on the | 1404 // the relative order is unchanged). To handle such cases, we rely on the |
1415 // caller to treat a position update on any sibling as updating the positions | 1405 // caller to treat a position update on any sibling as updating the positions |
1416 // of all siblings. | 1406 // of all siblings. |
1417 static bool VisiblePositionsDiffer(const syncable::EntryKernel& a, | 1407 static bool VisiblePositionsDiffer(const syncable::EntryKernel& a, |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1576 // Event listener hookup for the ServerConnectionManager. | 1566 // Event listener hookup for the ServerConnectionManager. |
1577 scoped_ptr<EventListenerHookup> connection_manager_hookup_; | 1567 scoped_ptr<EventListenerHookup> connection_manager_hookup_; |
1578 | 1568 |
1579 // The sync dir_manager to which we belong. | 1569 // The sync dir_manager to which we belong. |
1580 SyncManager* const sync_manager_; | 1570 SyncManager* const sync_manager_; |
1581 | 1571 |
1582 // The entity that provides us with information about which types to sync. | 1572 // The entity that provides us with information about which types to sync. |
1583 // The instance is shared between the SyncManager and the Syncer. | 1573 // The instance is shared between the SyncManager and the Syncer. |
1584 ModelSafeWorkerRegistrar* registrar_; | 1574 ModelSafeWorkerRegistrar* registrar_; |
1585 | 1575 |
1586 // Set to true once Init has been called, and we know of an | 1576 // Set to true once Init has been called. |
1587 // authenticated valid) username either from a fresh authentication | |
1588 // attempt (as in first-use case) or from a previous attempt stored | |
1589 // in our UserSettings (as in the steady-state), and the | |
1590 // syncable::Directory has been opened, meaning we are ready to | |
1591 // accept changes. Protected by initialized_mutex_ as it can get | |
1592 // read/set by both the SyncScheduler and the AuthWatcherThread. | |
1593 bool initialized_; | 1577 bool initialized_; |
1594 mutable base::Lock initialized_mutex_; | |
1595 | 1578 |
1596 // True if the SyncManager should be running in test mode (no sync | 1579 // True if the SyncManager should be running in test mode (no sync |
1597 // scheduler actually communicating with the server). | 1580 // scheduler actually communicating with the server). |
1598 bool setup_for_test_mode_; | 1581 bool setup_for_test_mode_; |
1599 | 1582 |
1600 ScopedRunnableMethodFactory<SyncManager::SyncInternal> method_factory_; | 1583 ScopedRunnableMethodFactory<SyncManager::SyncInternal> method_factory_; |
1601 | 1584 |
1602 // Map used to store the notification info to be displayed in | 1585 // Map used to store the notification info to be displayed in |
1603 // about:sync page. | 1586 // about:sync page. |
1604 NotificationInfoMap notification_info_map_; | 1587 NotificationInfoMap notification_info_map_; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1736 const std::string& sync_server_and_path, | 1719 const std::string& sync_server_and_path, |
1737 int port, | 1720 int port, |
1738 bool use_ssl, | 1721 bool use_ssl, |
1739 HttpPostProviderFactory* post_factory, | 1722 HttpPostProviderFactory* post_factory, |
1740 ModelSafeWorkerRegistrar* model_safe_worker_registrar, | 1723 ModelSafeWorkerRegistrar* model_safe_worker_registrar, |
1741 const char* user_agent, | 1724 const char* user_agent, |
1742 const SyncCredentials& credentials, | 1725 const SyncCredentials& credentials, |
1743 sync_notifier::SyncNotifier* sync_notifier, | 1726 sync_notifier::SyncNotifier* sync_notifier, |
1744 const std::string& restored_key_for_bootstrapping, | 1727 const std::string& restored_key_for_bootstrapping, |
1745 bool setup_for_test_mode) { | 1728 bool setup_for_test_mode) { |
1729 CHECK(!initialized_); | |
1746 | 1730 |
1747 VLOG(1) << "Starting SyncInternal initialization."; | 1731 VLOG(1) << "Starting SyncInternal initialization."; |
1748 | 1732 |
1749 sync_loop_ = MessageLoop::current(); | 1733 sync_loop_ = MessageLoop::current(); |
1750 DCHECK(sync_loop_); | 1734 DCHECK(sync_loop_); |
1751 registrar_ = model_safe_worker_registrar; | 1735 registrar_ = model_safe_worker_registrar; |
1752 setup_for_test_mode_ = setup_for_test_mode; | 1736 setup_for_test_mode_ = setup_for_test_mode; |
1753 | 1737 |
1754 sync_notifier_ = sync_notifier; | 1738 sync_notifier_ = sync_notifier; |
1755 sync_notifier_->AddObserver(this); | 1739 sync_notifier_->AddObserver(this); |
(...skipping 29 matching lines...) Expand all Loading... | |
1785 scheduler_.reset(new SyncScheduler(name_, context, new Syncer())); | 1769 scheduler_.reset(new SyncScheduler(name_, context, new Syncer())); |
1786 } | 1770 } |
1787 | 1771 |
1788 bool signed_in = SignIn(credentials); | 1772 bool signed_in = SignIn(credentials); |
1789 | 1773 |
1790 if (signed_in && scheduler()) { | 1774 if (signed_in && scheduler()) { |
1791 scheduler()->Start( | 1775 scheduler()->Start( |
1792 browser_sync::SyncScheduler::CONFIGURATION_MODE, NULL); | 1776 browser_sync::SyncScheduler::CONFIGURATION_MODE, NULL); |
1793 } | 1777 } |
1794 | 1778 |
1779 initialized_ = true; | |
1780 | |
1795 // Do this once the directory is opened. | 1781 // Do this once the directory is opened. |
1796 BootstrapEncryption(restored_key_for_bootstrapping); | 1782 BootstrapEncryption(restored_key_for_bootstrapping); |
1797 MarkAndNotifyInitializationComplete(); | 1783 |
1784 // Notify that initialization is complete. | |
1785 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
1786 OnInitializationComplete()); | |
tim (not reviewing)
2011/06/10 01:53:20
So, in the reviews yesterday to make our observers
akalin
2011/06/14 17:10:25
The races occurred because the observer add/remove
akalin
2011/06/14 21:27:23
Oh, I see what you were saying. That was just a m
| |
1787 | |
1798 return signed_in; | 1788 return signed_in; |
1799 } | 1789 } |
1800 | 1790 |
1801 void SyncManager::SyncInternal::BootstrapEncryption( | 1791 void SyncManager::SyncInternal::BootstrapEncryption( |
1802 const std::string& restored_key_for_bootstrapping) { | 1792 const std::string& restored_key_for_bootstrapping) { |
1803 syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); | 1793 syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); |
1804 if (!lookup.good()) { | 1794 if (!lookup.good()) { |
1805 LOG(INFO) << "BootstrapEncryption: lookup not good so bailing out"; | 1795 LOG(INFO) << "BootstrapEncryption: lookup not good so bailing out"; |
1806 NOTREACHED(); | 1796 NOTREACHED(); |
1807 return; | 1797 return; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1847 } | 1837 } |
1848 | 1838 |
1849 void SyncManager::SyncInternal::StartSyncingNormally() { | 1839 void SyncManager::SyncInternal::StartSyncingNormally() { |
1850 // Start the sync scheduler. This won't actually result in any | 1840 // Start the sync scheduler. This won't actually result in any |
1851 // syncing until at least the DirectoryManager broadcasts the OPENED | 1841 // syncing until at least the DirectoryManager broadcasts the OPENED |
1852 // event, and a valid server connection is detected. | 1842 // event, and a valid server connection is detected. |
1853 if (scheduler()) // NULL during certain unittests. | 1843 if (scheduler()) // NULL during certain unittests. |
1854 scheduler()->Start(SyncScheduler::NORMAL_MODE, NULL); | 1844 scheduler()->Start(SyncScheduler::NORMAL_MODE, NULL); |
1855 } | 1845 } |
1856 | 1846 |
1857 void SyncManager::SyncInternal::MarkAndNotifyInitializationComplete() { | |
1858 // There is only one real time we need this mutex. If we get an auth | |
1859 // success, and before the initial sync ends we get an auth failure. In this | |
1860 // case we'll be listening to both the AuthWatcher and Syncer, and it's a race | |
1861 // between their respective threads to call MarkAndNotify. We need to make | |
1862 // sure the observer is notified once and only once. | |
1863 { | |
1864 base::AutoLock lock(initialized_mutex_); | |
1865 if (initialized_) | |
1866 return; | |
1867 initialized_ = true; | |
1868 } | |
1869 | |
1870 // Notify that initialization is complete. | |
1871 ObserverList<SyncManager::Observer> temp_obs_list; | |
1872 CopyObservers(&temp_obs_list); | |
1873 FOR_EACH_OBSERVER(SyncManager::Observer, temp_obs_list, | |
1874 OnInitializationComplete()); | |
1875 } | |
1876 | |
1877 void SyncManager::SyncInternal::SendNotification() { | 1847 void SyncManager::SyncInternal::SendNotification() { |
1878 DCHECK_EQ(MessageLoop::current(), sync_loop_); | 1848 DCHECK_EQ(MessageLoop::current(), sync_loop_); |
1879 if (!sync_notifier_) { | 1849 if (!sync_notifier_) { |
1880 VLOG(1) << "Not sending notification: sync_notifier_ is NULL"; | 1850 VLOG(1) << "Not sending notification: sync_notifier_ is NULL"; |
1881 return; | 1851 return; |
1882 } | 1852 } |
1883 sync_notifier_->SendNotification(); | 1853 sync_notifier_->SendNotification(); |
1884 } | 1854 } |
1885 | 1855 |
1886 bool SyncManager::SyncInternal::OpenDirectory() { | 1856 bool SyncManager::SyncInternal::OpenDirectory() { |
1887 DCHECK(!initialized()) << "Should only happen once"; | 1857 DCHECK(!initialized_) << "Should only happen once"; |
1888 | 1858 |
1889 bool share_opened = dir_manager()->Open(username_for_share()); | 1859 bool share_opened = dir_manager()->Open(username_for_share()); |
1890 DCHECK(share_opened); | 1860 DCHECK(share_opened); |
1891 if (!share_opened) { | 1861 if (!share_opened) { |
1892 ObserverList<SyncManager::Observer> temp_obs_list; | 1862 ObserverList<SyncManager::Observer> temp_obs_list; |
1893 CopyObservers(&temp_obs_list); | 1863 CopyObservers(&temp_obs_list); |
1894 FOR_EACH_OBSERVER(SyncManager::Observer, temp_obs_list, | 1864 FOR_EACH_OBSERVER(SyncManager::Observer, temp_obs_list, |
1895 OnStopSyncingPermanently()); | 1865 OnStopSyncingPermanently()); |
1896 | 1866 |
1897 LOG(ERROR) << "Could not open share for:" << username_for_share(); | 1867 LOG(ERROR) << "Could not open share for:" << username_for_share(); |
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2554 FOR_EACH_OBSERVER(SyncManager::Observer, temp_obs_list, | 2524 FOR_EACH_OBSERVER(SyncManager::Observer, temp_obs_list, |
2555 OnPassphraseRequired(sync_api::REASON_ENCRYPTION)); | 2525 OnPassphraseRequired(sync_api::REASON_ENCRYPTION)); |
2556 } | 2526 } |
2557 // If everything is in order(we have the passphrase) then there is no | 2527 // If everything is in order(we have the passphrase) then there is no |
2558 // need to inform the listeners. They will just wait for sync | 2528 // need to inform the listeners. They will just wait for sync |
2559 // completion event and if no errors have been raised it means | 2529 // completion event and if no errors have been raised it means |
2560 // encryption was succesful. | 2530 // encryption was succesful. |
2561 } | 2531 } |
2562 } | 2532 } |
2563 | 2533 |
2564 if (!initialized()) { | 2534 if (!initialized_) { |
2565 LOG(INFO) << "OnSyncCycleCompleted not sent because sync api is not " | 2535 LOG(INFO) << "OnSyncCycleCompleted not sent because sync api is not " |
2566 << "initialized"; | 2536 << "initialized"; |
2567 return; | 2537 return; |
2568 } | 2538 } |
2569 | 2539 |
2570 if (!event.snapshot->has_more_to_sync) { | 2540 if (!event.snapshot->has_more_to_sync) { |
2571 VLOG(1) << "OnSyncCycleCompleted sent"; | 2541 VLOG(1) << "OnSyncCycleCompleted sent"; |
2572 ObserverList<SyncManager::Observer> temp_obs_list; | 2542 ObserverList<SyncManager::Observer> temp_obs_list; |
2573 CopyObservers(&temp_obs_list); | 2543 CopyObservers(&temp_obs_list); |
2574 FOR_EACH_OBSERVER(SyncManager::Observer, temp_obs_list, | 2544 FOR_EACH_OBSERVER(SyncManager::Observer, temp_obs_list, |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2991 share->name); | 2961 share->name); |
2992 cryptographer_ = share->dir_manager->GetCryptographer(this); | 2962 cryptographer_ = share->dir_manager->GetCryptographer(this); |
2993 if (!(lookup_->good())) | 2963 if (!(lookup_->good())) |
2994 DCHECK(false) << "ScopedDirLookup failed on valid DirManager."; | 2964 DCHECK(false) << "ScopedDirLookup failed on valid DirManager."; |
2995 } | 2965 } |
2996 BaseTransaction::~BaseTransaction() { | 2966 BaseTransaction::~BaseTransaction() { |
2997 delete lookup_; | 2967 delete lookup_; |
2998 } | 2968 } |
2999 | 2969 |
3000 UserShare* SyncManager::GetUserShare() const { | 2970 UserShare* SyncManager::GetUserShare() const { |
3001 DCHECK(data_->initialized()) << "GetUserShare requires initialization!"; | |
3002 return data_->GetUserShare(); | 2971 return data_->GetUserShare(); |
3003 } | 2972 } |
3004 | 2973 |
3005 syncable::ModelTypeSet SyncManager::GetEncryptedDataTypes() const { | 2974 syncable::ModelTypeSet SyncManager::GetEncryptedDataTypes() const { |
3006 sync_api::ReadTransaction trans(GetUserShare()); | 2975 sync_api::ReadTransaction trans(GetUserShare()); |
3007 return GetEncryptedTypes(&trans); | 2976 return GetEncryptedTypes(&trans); |
3008 } | 2977 } |
3009 | 2978 |
3010 | 2979 |
3011 bool SyncManager::HasUnsyncedItems() const { | 2980 bool SyncManager::HasUnsyncedItems() const { |
(...skipping 27 matching lines...) Expand all Loading... | |
3039 void SyncManager::TriggerOnIncomingNotificationForTest( | 3008 void SyncManager::TriggerOnIncomingNotificationForTest( |
3040 const syncable::ModelTypeBitSet& model_types) { | 3009 const syncable::ModelTypeBitSet& model_types) { |
3041 syncable::ModelTypePayloadMap model_types_with_payloads = | 3010 syncable::ModelTypePayloadMap model_types_with_payloads = |
3042 syncable::ModelTypePayloadMapFromBitSet(model_types, | 3011 syncable::ModelTypePayloadMapFromBitSet(model_types, |
3043 std::string()); | 3012 std::string()); |
3044 | 3013 |
3045 data_->OnIncomingNotification(model_types_with_payloads); | 3014 data_->OnIncomingNotification(model_types_with_payloads); |
3046 } | 3015 } |
3047 | 3016 |
3048 } // namespace sync_api | 3017 } // namespace sync_api |
OLD | NEW |