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"
17 namespace browser_sync
{
21 // Return the DeviceInfo UNIQUE_CLIENT_TAG value for the given sync cache_guid.
22 std::string
DeviceInfoLookupString(const std::string
& cache_guid
) {
23 return base::StringPrintf("DeviceInfo_%s", cache_guid
.c_str());
28 SyncedDeviceTracker::SyncedDeviceTracker(syncer::UserShare
* user_share
,
29 const std::string
& cache_guid
)
30 : ChangeProcessor(NULL
),
31 user_share_(user_share
),
32 cache_guid_(cache_guid
),
33 local_device_info_tag_(DeviceInfoLookupString(cache_guid
)),
35 observers_
= new ObserverListThreadSafe
<Observer
>;
38 SyncedDeviceTracker::~SyncedDeviceTracker() {
41 void SyncedDeviceTracker::StartImpl(Profile
* profile
) { }
43 void SyncedDeviceTracker::ApplyChangesFromSyncModel(
44 const syncer::BaseTransaction
* trans
,
46 const syncer::ImmutableChangeRecordList
& changes
) {
47 // If desired, we could maintain a cache of device info. This method will be
48 // called with a transaction every time the device info is modified, so this
49 // would be the right place to update the cache.
52 void SyncedDeviceTracker::CommitChangesFromSyncModel() {
53 observers_
->Notify(&Observer::OnDeviceInfoChange
);
56 scoped_ptr
<DeviceInfo
> SyncedDeviceTracker::ReadLocalDeviceInfo() const {
57 syncer::ReadTransaction
trans(FROM_HERE
, user_share_
);
58 return ReadLocalDeviceInfo(trans
);
61 scoped_ptr
<DeviceInfo
> SyncedDeviceTracker::ReadLocalDeviceInfo(
62 const syncer::BaseTransaction
& trans
) const {
63 syncer::ReadNode
node(&trans
);
64 if (node
.InitByClientTagLookup(syncer::DEVICE_INFO
, local_device_info_tag_
) !=
65 syncer::BaseNode::INIT_OK
) {
66 return scoped_ptr
<DeviceInfo
>();
69 const sync_pb::DeviceInfoSpecifics
& specifics
= node
.GetDeviceInfoSpecifics();
70 return scoped_ptr
<DeviceInfo
> (
71 new DeviceInfo(specifics
.cache_guid(),
72 specifics
.client_name(),
73 specifics
.chrome_version(),
74 specifics
.sync_user_agent(),
75 specifics
.device_type()));
78 scoped_ptr
<DeviceInfo
> SyncedDeviceTracker::ReadDeviceInfo(
79 const std::string
& client_id
) const {
80 syncer::ReadTransaction
trans(FROM_HERE
, user_share_
);
81 syncer::ReadNode
node(&trans
);
82 std::string lookup_string
= DeviceInfoLookupString(client_id
);
83 if (node
.InitByClientTagLookup(syncer::DEVICE_INFO
, lookup_string
) !=
84 syncer::BaseNode::INIT_OK
) {
85 return scoped_ptr
<DeviceInfo
>();
88 const sync_pb::DeviceInfoSpecifics
& specifics
= node
.GetDeviceInfoSpecifics();
89 return scoped_ptr
<DeviceInfo
> (
90 new DeviceInfo(specifics
.cache_guid(),
91 specifics
.client_name(),
92 specifics
.chrome_version(),
93 specifics
.sync_user_agent(),
94 specifics
.device_type()));
97 void SyncedDeviceTracker::GetAllSyncedDeviceInfo(
98 ScopedVector
<DeviceInfo
>* device_info
) const {
99 if (device_info
== NULL
)
102 device_info
->clear();
104 syncer::ReadTransaction
trans(FROM_HERE
, user_share_
);
105 syncer::ReadNode
root_node(&trans
);
107 if (root_node
.InitByTagLookup(
108 syncer::ModelTypeToRootTag(syncer::DEVICE_INFO
)) !=
109 syncer::BaseNode::INIT_OK
) {
113 // Get all the children of the root node and use the child id to read
114 // device info for devices.
115 std::vector
<int64
> children
;
116 root_node
.GetChildIds(&children
);
118 for (std::vector
<int64
>::const_iterator it
= children
.begin();
119 it
!= children
.end(); ++it
) {
120 syncer::ReadNode
node(&trans
);
121 if (node
.InitByIdLookup(*it
) != syncer::BaseNode::INIT_OK
)
124 const sync_pb::DeviceInfoSpecifics
& specifics
=
125 node
.GetDeviceInfoSpecifics();
126 device_info
->push_back(
127 new DeviceInfo(specifics
.cache_guid(),
128 specifics
.client_name(),
129 specifics
.chrome_version(),
130 specifics
.sync_user_agent(),
131 specifics
.device_type()));
136 std::string
SyncedDeviceTracker::cache_guid() const {
140 void SyncedDeviceTracker::AddObserver(Observer
* observer
) {
141 observers_
->AddObserver(observer
);
144 void SyncedDeviceTracker::RemoveObserver(Observer
* observer
) {
145 observers_
->RemoveObserver(observer
);
148 void SyncedDeviceTracker::InitLocalDeviceInfo(const base::Closure
& callback
) {
149 DeviceInfo::CreateLocalDeviceInfo(
151 base::Bind(&SyncedDeviceTracker::InitLocalDeviceInfoContinuation
,
152 weak_factory_
.GetWeakPtr(), callback
));
155 void SyncedDeviceTracker::InitLocalDeviceInfoContinuation(
156 const base::Closure
& callback
, const DeviceInfo
& local_info
) {
157 WriteLocalDeviceInfo(local_info
);
161 void SyncedDeviceTracker::WriteLocalDeviceInfo(const DeviceInfo
& info
) {
162 sync_pb::DeviceInfoSpecifics specifics
;
163 DCHECK_EQ(cache_guid_
, info
.guid());
164 specifics
.set_cache_guid(cache_guid_
);
165 specifics
.set_client_name(info
.client_name());
166 specifics
.set_chrome_version(info
.chrome_version());
167 specifics
.set_sync_user_agent(info
.sync_user_agent());
168 specifics
.set_device_type(info
.device_type());
170 WriteDeviceInfo(specifics
, local_device_info_tag_
);
173 void SyncedDeviceTracker::WriteDeviceInfo(
174 const sync_pb::DeviceInfoSpecifics
& specifics
,
175 const std::string
& tag
) {
176 syncer::WriteTransaction
trans(FROM_HERE
, user_share_
);
177 syncer::WriteNode
node(&trans
);
179 if (node
.InitByClientTagLookup(syncer::DEVICE_INFO
, tag
) ==
180 syncer::BaseNode::INIT_OK
) {
181 node
.SetDeviceInfoSpecifics(specifics
);
182 node
.SetTitle(base::UTF8ToWide(specifics
.client_name()));
184 syncer::ReadNode
type_root(&trans
);
185 syncer::BaseNode::InitByLookupResult type_root_lookup_result
=
186 type_root
.InitByTagLookup(ModelTypeToRootTag(syncer::DEVICE_INFO
));
187 DCHECK_EQ(syncer::BaseNode::INIT_OK
, type_root_lookup_result
);
189 syncer::WriteNode
new_node(&trans
);
190 syncer::WriteNode::InitUniqueByCreationResult create_result
=
191 new_node
.InitUniqueByCreation(syncer::DEVICE_INFO
,
194 DCHECK_EQ(syncer::WriteNode::INIT_SUCCESS
, create_result
);
195 new_node
.SetDeviceInfoSpecifics(specifics
);
196 new_node
.SetTitle(base::UTF8ToWide(specifics
.client_name()));
200 } // namespace browser_sync