1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/sync/glue/synced_device_tracker.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/sync/glue/device_info.h"
10 #include "sync/internal_api/public/base/model_type.h"
11 #include "sync/internal_api/public/read_node.h"
12 #include "sync/internal_api/public/read_transaction.h"
13 #include "sync/internal_api/public/user_share.h"
14 #include "sync/internal_api/public/write_node.h"
15 #include "sync/internal_api/public/write_transaction.h"
16 #include "sync/util/time.h"
18 namespace browser_sync
{
22 // Return the DeviceInfo UNIQUE_CLIENT_TAG value for the given sync cache_guid.
23 std::string
DeviceInfoLookupString(const std::string
& cache_guid
) {
24 return base::StringPrintf("DeviceInfo_%s", cache_guid
.c_str());
29 SyncedDeviceTracker::SyncedDeviceTracker(syncer::UserShare
* user_share
,
30 const std::string
& cache_guid
)
31 : ChangeProcessor(NULL
),
32 user_share_(user_share
),
33 cache_guid_(cache_guid
),
34 local_device_info_tag_(DeviceInfoLookupString(cache_guid
)),
36 observers_
= new ObserverListThreadSafe
<Observer
>;
39 SyncedDeviceTracker::~SyncedDeviceTracker() {
42 void SyncedDeviceTracker::StartImpl() { }
44 void SyncedDeviceTracker::ApplyChangesFromSyncModel(
45 const syncer::BaseTransaction
* trans
,
47 const syncer::ImmutableChangeRecordList
& changes
) {
48 // If desired, we could maintain a cache of device info. This method will be
49 // called with a transaction every time the device info is modified, so this
50 // would be the right place to update the cache.
53 void SyncedDeviceTracker::CommitChangesFromSyncModel() {
54 observers_
->Notify(&Observer::OnDeviceInfoChange
);
57 scoped_ptr
<DeviceInfo
> SyncedDeviceTracker::ReadLocalDeviceInfo() const {
58 syncer::ReadTransaction
trans(FROM_HERE
, user_share_
);
59 return ReadLocalDeviceInfo(trans
);
62 scoped_ptr
<DeviceInfo
> SyncedDeviceTracker::ReadLocalDeviceInfo(
63 const syncer::BaseTransaction
& trans
) const {
64 syncer::ReadNode
node(&trans
);
65 if (node
.InitByClientTagLookup(syncer::DEVICE_INFO
, local_device_info_tag_
) !=
66 syncer::BaseNode::INIT_OK
) {
67 return scoped_ptr
<DeviceInfo
>();
70 const sync_pb::DeviceInfoSpecifics
& specifics
= node
.GetDeviceInfoSpecifics();
71 return scoped_ptr
<DeviceInfo
>(
72 new DeviceInfo(specifics
.cache_guid(),
73 specifics
.client_name(),
74 specifics
.chrome_version(),
75 specifics
.sync_user_agent(),
76 specifics
.device_type(),
77 specifics
.signin_scoped_device_id()));
80 scoped_ptr
<DeviceInfo
> SyncedDeviceTracker::ReadDeviceInfo(
81 const std::string
& client_id
) const {
82 syncer::ReadTransaction
trans(FROM_HERE
, user_share_
);
83 syncer::ReadNode
node(&trans
);
84 std::string lookup_string
= DeviceInfoLookupString(client_id
);
85 if (node
.InitByClientTagLookup(syncer::DEVICE_INFO
, lookup_string
) !=
86 syncer::BaseNode::INIT_OK
) {
87 return scoped_ptr
<DeviceInfo
>();
90 const sync_pb::DeviceInfoSpecifics
& specifics
= node
.GetDeviceInfoSpecifics();
91 return scoped_ptr
<DeviceInfo
>(
92 new DeviceInfo(specifics
.cache_guid(),
93 specifics
.client_name(),
94 specifics
.chrome_version(),
95 specifics
.sync_user_agent(),
96 specifics
.device_type(),
97 specifics
.signin_scoped_device_id()));
100 void SyncedDeviceTracker::GetAllSyncedDeviceInfo(
101 ScopedVector
<DeviceInfo
>* device_info
) const {
102 if (device_info
== NULL
)
105 device_info
->clear();
107 syncer::ReadTransaction
trans(FROM_HERE
, user_share_
);
108 syncer::ReadNode
root_node(&trans
);
110 if (root_node
.InitTypeRoot(syncer::DEVICE_INFO
) !=
111 syncer::BaseNode::INIT_OK
) {
115 // Get all the children of the root node and use the child id to read
116 // device info for devices.
117 std::vector
<int64
> children
;
118 root_node
.GetChildIds(&children
);
120 for (std::vector
<int64
>::const_iterator it
= children
.begin();
121 it
!= children
.end(); ++it
) {
122 syncer::ReadNode
node(&trans
);
123 if (node
.InitByIdLookup(*it
) != syncer::BaseNode::INIT_OK
)
126 const sync_pb::DeviceInfoSpecifics
& specifics
=
127 node
.GetDeviceInfoSpecifics();
128 device_info
->push_back(new DeviceInfo(specifics
.cache_guid(),
129 specifics
.client_name(),
130 specifics
.chrome_version(),
131 specifics
.sync_user_agent(),
132 specifics
.device_type(),
133 specifics
.signin_scoped_device_id()));
137 std::string
SyncedDeviceTracker::cache_guid() const {
141 void SyncedDeviceTracker::AddObserver(Observer
* observer
) {
142 observers_
->AddObserver(observer
);
145 void SyncedDeviceTracker::RemoveObserver(Observer
* observer
) {
146 observers_
->RemoveObserver(observer
);
149 void SyncedDeviceTracker::InitLocalDeviceInfo(
150 const std::string
& signin_scoped_device_id
,
151 const base::Closure
& callback
) {
152 DeviceInfo::CreateLocalDeviceInfo(
154 signin_scoped_device_id
,
155 base::Bind(&SyncedDeviceTracker::InitLocalDeviceInfoContinuation
,
156 weak_factory_
.GetWeakPtr(),
160 void SyncedDeviceTracker::InitLocalDeviceInfoContinuation(
161 const base::Closure
& callback
, const DeviceInfo
& local_info
) {
162 WriteLocalDeviceInfo(local_info
);
166 void SyncedDeviceTracker::WriteLocalDeviceInfo(const DeviceInfo
& info
) {
167 DCHECK_EQ(cache_guid_
, info
.guid());
168 WriteDeviceInfo(info
, local_device_info_tag_
);
171 void SyncedDeviceTracker::WriteDeviceInfo(const DeviceInfo
& info
,
172 const std::string
& tag
) {
173 syncer::WriteTransaction
trans(FROM_HERE
, user_share_
);
174 syncer::WriteNode
node(&trans
);
176 sync_pb::DeviceInfoSpecifics specifics
;
177 specifics
.set_cache_guid(info
.guid());
178 specifics
.set_client_name(info
.client_name());
179 specifics
.set_chrome_version(info
.chrome_version());
180 specifics
.set_sync_user_agent(info
.sync_user_agent());
181 specifics
.set_device_type(info
.device_type());
182 specifics
.set_signin_scoped_device_id(info
.signin_scoped_device_id());
184 if (node
.InitByClientTagLookup(syncer::DEVICE_INFO
, tag
) ==
185 syncer::BaseNode::INIT_OK
) {
186 const sync_pb::DeviceInfoSpecifics
& sync_specifics
=
187 node
.GetDeviceInfoSpecifics();
188 if (sync_specifics
.has_backup_timestamp())
189 specifics
.set_backup_timestamp(sync_specifics
.backup_timestamp());
190 node
.SetDeviceInfoSpecifics(specifics
);
191 node
.SetTitle(specifics
.client_name());
193 syncer::ReadNode
type_root(&trans
);
194 syncer::BaseNode::InitByLookupResult type_root_lookup_result
=
195 type_root
.InitTypeRoot(syncer::DEVICE_INFO
);
196 DCHECK_EQ(syncer::BaseNode::INIT_OK
, type_root_lookup_result
);
198 syncer::WriteNode
new_node(&trans
);
199 syncer::WriteNode::InitUniqueByCreationResult create_result
=
200 new_node
.InitUniqueByCreation(syncer::DEVICE_INFO
,
203 DCHECK_EQ(syncer::WriteNode::INIT_SUCCESS
, create_result
);
204 new_node
.SetDeviceInfoSpecifics(specifics
);
205 new_node
.SetTitle(specifics
.client_name());
209 void SyncedDeviceTracker::UpdateLocalDeviceBackupTime(base::Time backup_time
) {
210 syncer::WriteTransaction
trans(FROM_HERE
, user_share_
);
211 syncer::WriteNode
node(&trans
);
213 if (node
.InitByClientTagLookup(syncer::DEVICE_INFO
, local_device_info_tag_
)
214 == syncer::BaseNode::INIT_OK
) {
215 sync_pb::DeviceInfoSpecifics specifics
= node
.GetDeviceInfoSpecifics();
216 int64 new_backup_timestamp
= syncer::TimeToProtoTime(backup_time
);
217 if (!specifics
.has_backup_timestamp() ||
218 specifics
.backup_timestamp() != new_backup_timestamp
) {
219 specifics
.set_backup_timestamp(new_backup_timestamp
);
220 node
.SetDeviceInfoSpecifics(specifics
);
225 base::Time
SyncedDeviceTracker::GetLocalDeviceBackupTime() const {
226 syncer::ReadTransaction
trans(FROM_HERE
, user_share_
);
227 syncer::ReadNode
node(&trans
);
228 if (node
.InitByClientTagLookup(syncer::DEVICE_INFO
, local_device_info_tag_
)
229 == syncer::BaseNode::INIT_OK
&&
230 node
.GetDeviceInfoSpecifics().has_backup_timestamp()) {
231 return syncer::ProtoTimeToTime(
232 node
.GetDeviceInfoSpecifics().backup_timestamp());
238 } // namespace browser_sync