OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/glue/extension_model_associator.h" | 5 #include "chrome/browser/sync/glue/extension_model_associator.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 DCHECK(!extension_data->NeedsUpdate(source)); | 48 DCHECK(!extension_data->NeedsUpdate(source)); |
49 } else { | 49 } else { |
50 extension_data->SetData(source, merge_user_properties, data); | 50 extension_data->SetData(source, merge_user_properties, data); |
51 } | 51 } |
52 return extension_data; | 52 return extension_data; |
53 } | 53 } |
54 | 54 |
55 void GetSyncableExtensionsClientData( | 55 void GetSyncableExtensionsClientData( |
56 const ExtensionList& extensions, | 56 const ExtensionList& extensions, |
57 ExtensionsService* extensions_service, | 57 ExtensionsService* extensions_service, |
| 58 std::set<std::string>* unsyncable_extensions, |
58 ExtensionDataMap* extension_data_map) { | 59 ExtensionDataMap* extension_data_map) { |
59 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 60 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
60 for (ExtensionList::const_iterator it = extensions.begin(); | 61 for (ExtensionList::const_iterator it = extensions.begin(); |
61 it != extensions.end(); ++it) { | 62 it != extensions.end(); ++it) { |
62 CHECK(*it); | 63 CHECK(*it); |
63 const Extension& extension = **it; | 64 const Extension& extension = **it; |
64 if (IsExtensionSyncable(extension)) { | 65 if (IsExtensionSyncable(extension)) { |
65 sync_pb::ExtensionSpecifics client_specifics; | 66 sync_pb::ExtensionSpecifics client_specifics; |
66 GetExtensionSpecifics(extension, extensions_service, | 67 GetExtensionSpecifics(extension, extensions_service, |
67 &client_specifics); | 68 &client_specifics); |
68 DcheckIsExtensionSpecificsValid(client_specifics); | 69 DcheckIsExtensionSpecificsValid(client_specifics); |
69 const ExtensionData& extension_data = | 70 const ExtensionData& extension_data = |
70 *SetOrCreateData(extension_data_map, | 71 *SetOrCreateData(extension_data_map, |
71 ExtensionData::CLIENT, true, client_specifics); | 72 ExtensionData::CLIENT, true, client_specifics); |
72 DcheckIsExtensionSpecificsValid(extension_data.merged_data()); | 73 DcheckIsExtensionSpecificsValid(extension_data.merged_data()); |
73 // Assumes this is called before any server data is read. | 74 // Assumes this is called before any server data is read. |
74 DCHECK(extension_data.NeedsUpdate(ExtensionData::SERVER)); | 75 DCHECK(extension_data.NeedsUpdate(ExtensionData::SERVER)); |
75 DCHECK(!extension_data.NeedsUpdate(ExtensionData::CLIENT)); | 76 DCHECK(!extension_data.NeedsUpdate(ExtensionData::CLIENT)); |
| 77 } else { |
| 78 unsyncable_extensions->insert(extension.id()); |
76 } | 79 } |
77 } | 80 } |
78 } | 81 } |
79 | 82 |
80 } // namespace | 83 } // namespace |
81 | 84 |
82 ExtensionModelAssociator::ExtensionModelAssociator( | 85 ExtensionModelAssociator::ExtensionModelAssociator( |
83 ProfileSyncService* sync_service) : sync_service_(sync_service) { | 86 ProfileSyncService* sync_service) : sync_service_(sync_service) { |
84 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 87 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
85 DCHECK(sync_service_); | 88 DCHECK(sync_service_); |
86 } | 89 } |
87 | 90 |
88 ExtensionModelAssociator::~ExtensionModelAssociator() { | 91 ExtensionModelAssociator::~ExtensionModelAssociator() { |
89 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 92 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
90 } | 93 } |
91 | 94 |
92 bool ExtensionModelAssociator::AssociateModels() { | 95 bool ExtensionModelAssociator::AssociateModels() { |
93 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 96 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
94 sync_api::WriteTransaction trans( | 97 sync_api::WriteTransaction trans( |
95 sync_service_->backend()->GetUserShareHandle()); | 98 sync_service_->backend()->GetUserShareHandle()); |
96 sync_api::ReadNode root(&trans); | 99 sync_api::ReadNode root(&trans); |
97 if (!root.InitByTagLookup(kExtensionsTag)) { | 100 if (!root.InitByTagLookup(kExtensionsTag)) { |
98 LOG(ERROR) << kNoExtensionsFolderError; | 101 LOG(ERROR) << kNoExtensionsFolderError; |
99 return false; | 102 return false; |
100 } | 103 } |
101 | 104 |
| 105 std::set<std::string> unsyncable_extensions; |
102 ExtensionDataMap extension_data_map; | 106 ExtensionDataMap extension_data_map; |
103 | 107 |
104 // Read client-side data. Do this first so server data takes | 108 // Read client-side data. Do this first so server data takes |
105 // precedence. | 109 // precedence. |
106 { | 110 { |
107 ExtensionsService* extensions_service = GetExtensionsService(); | 111 ExtensionsService* extensions_service = GetExtensionsService(); |
108 | 112 |
109 const ExtensionList* extensions = extensions_service->extensions(); | 113 const ExtensionList* extensions = extensions_service->extensions(); |
110 CHECK(extensions); | 114 CHECK(extensions); |
111 GetSyncableExtensionsClientData( | 115 GetSyncableExtensionsClientData( |
112 *extensions, extensions_service, &extension_data_map); | 116 *extensions, extensions_service, |
| 117 &unsyncable_extensions, &extension_data_map); |
113 | 118 |
114 const ExtensionList* disabled_extensions = | 119 const ExtensionList* disabled_extensions = |
115 extensions_service->disabled_extensions(); | 120 extensions_service->disabled_extensions(); |
116 CHECK(disabled_extensions); | 121 CHECK(disabled_extensions); |
117 GetSyncableExtensionsClientData( | 122 GetSyncableExtensionsClientData( |
118 *disabled_extensions, extensions_service, &extension_data_map); | 123 *disabled_extensions, extensions_service, |
| 124 &unsyncable_extensions, &extension_data_map); |
119 } | 125 } |
120 | 126 |
121 // Read server-side data. | 127 // Read server-side data. |
122 { | 128 { |
123 int64 id = root.GetFirstChildId(); | 129 int64 id = root.GetFirstChildId(); |
124 while (id != sync_api::kInvalidId) { | 130 while (id != sync_api::kInvalidId) { |
125 sync_api::ReadNode sync_node(&trans); | 131 sync_api::ReadNode sync_node(&trans); |
126 if (!sync_node.InitByIdLookup(id)) { | 132 if (!sync_node.InitByIdLookup(id)) { |
127 LOG(ERROR) << "Failed to fetch sync node for id " << id; | 133 LOG(ERROR) << "Failed to fetch sync node for id " << id; |
128 return false; | 134 return false; |
129 } | 135 } |
130 const sync_pb::ExtensionSpecifics& server_data = | 136 const sync_pb::ExtensionSpecifics& server_data = |
131 sync_node.GetExtensionSpecifics(); | 137 sync_node.GetExtensionSpecifics(); |
132 if (!IsExtensionSpecificsValid(server_data)) { | 138 if (!IsExtensionSpecificsValid(server_data)) { |
133 LOG(ERROR) << "Invalid extensions specifics for id " << id; | 139 LOG(ERROR) << "Invalid extensions specifics for id " << id; |
134 return false; | 140 return false; |
135 } | 141 } |
136 // Pass in false for merge_user_properties so client user | 142 // Don't process server data for extensions we know are |
137 // settings always take precedence. | 143 // unsyncable. This doesn't catch everything, as if we don't |
138 const ExtensionData& extension_data = | 144 // have the extension already installed we can't check, but we |
139 *SetOrCreateData(&extension_data_map, | 145 // also check at extension install time. |
140 ExtensionData::SERVER, false, server_data); | 146 if (unsyncable_extensions.find(server_data.id()) == |
141 DcheckIsExtensionSpecificsValid(extension_data.merged_data()); | 147 unsyncable_extensions.end()) { |
| 148 // Pass in false for merge_user_properties so client user |
| 149 // settings always take precedence. |
| 150 const ExtensionData& extension_data = |
| 151 *SetOrCreateData(&extension_data_map, |
| 152 ExtensionData::SERVER, false, server_data); |
| 153 DcheckIsExtensionSpecificsValid(extension_data.merged_data()); |
| 154 } |
142 id = sync_node.GetSuccessorId(); | 155 id = sync_node.GetSuccessorId(); |
143 } | 156 } |
144 } | 157 } |
145 | 158 |
146 // Update server and client as necessary. | 159 // Update server and client as necessary. |
147 bool should_nudge_extension_updater = false; | 160 bool should_nudge_extension_updater = false; |
148 for (ExtensionDataMap::iterator it = extension_data_map.begin(); | 161 for (ExtensionDataMap::iterator it = extension_data_map.begin(); |
149 it != extension_data_map.end(); ++it) { | 162 it != extension_data_map.end(); ++it) { |
150 ExtensionData* extension_data = &it->second; | 163 ExtensionData* extension_data = &it->second; |
151 // Update server first. | 164 // Update server first. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 } | 210 } |
198 | 211 |
199 bool ExtensionModelAssociator::OnClientUpdate(const std::string& id) { | 212 bool ExtensionModelAssociator::OnClientUpdate(const std::string& id) { |
200 sync_api::WriteTransaction trans( | 213 sync_api::WriteTransaction trans( |
201 sync_service_->backend()->GetUserShareHandle()); | 214 sync_service_->backend()->GetUserShareHandle()); |
202 sync_api::ReadNode root(&trans); | 215 sync_api::ReadNode root(&trans); |
203 if (!root.InitByTagLookup(kExtensionsTag)) { | 216 if (!root.InitByTagLookup(kExtensionsTag)) { |
204 LOG(ERROR) << kNoExtensionsFolderError; | 217 LOG(ERROR) << kNoExtensionsFolderError; |
205 return false; | 218 return false; |
206 } | 219 } |
207 | 220 ExtensionsService* extensions_service = GetExtensionsService(); |
208 sync_pb::ExtensionSpecifics client_data; | 221 Extension* extension = extensions_service->GetExtensionById(id, true); |
209 if (GetExtensionDataFromClient(id, &client_data)) { | 222 if (extension) { |
| 223 if (!IsExtensionSyncable(*extension)) { |
| 224 LOG(DFATAL) << "OnClientUpdate() called for non-syncable extension " |
| 225 << id; |
| 226 return false; |
| 227 } |
| 228 sync_pb::ExtensionSpecifics client_data; |
| 229 GetExtensionSpecifics(*extension, extensions_service, &client_data); |
| 230 DcheckIsExtensionSpecificsValid(client_data); |
210 ExtensionData extension_data = | 231 ExtensionData extension_data = |
211 ExtensionData::FromData(ExtensionData::CLIENT, client_data); | 232 ExtensionData::FromData(ExtensionData::CLIENT, client_data); |
212 sync_pb::ExtensionSpecifics server_data; | 233 sync_pb::ExtensionSpecifics server_data; |
213 if (GetExtensionDataFromServer(id, &trans, root, &server_data)) { | 234 if (GetExtensionDataFromServer(id, &trans, root, &server_data)) { |
214 extension_data = | 235 extension_data = |
215 ExtensionData::FromData(ExtensionData::SERVER, server_data); | 236 ExtensionData::FromData(ExtensionData::SERVER, server_data); |
216 extension_data.SetData(ExtensionData::CLIENT, true, client_data); | 237 extension_data.SetData(ExtensionData::CLIENT, true, client_data); |
217 } | 238 } |
218 if (extension_data.NeedsUpdate(ExtensionData::SERVER)) { | 239 if (extension_data.NeedsUpdate(ExtensionData::SERVER)) { |
219 if (!UpdateServer(&extension_data, &trans, root)) { | 240 if (!UpdateServer(&extension_data, &trans, root)) { |
(...skipping 18 matching lines...) Expand all Loading... |
238 } | 259 } |
239 } | 260 } |
240 return true; | 261 return true; |
241 } | 262 } |
242 | 263 |
243 void ExtensionModelAssociator::OnServerUpdate( | 264 void ExtensionModelAssociator::OnServerUpdate( |
244 const sync_pb::ExtensionSpecifics& server_data) { | 265 const sync_pb::ExtensionSpecifics& server_data) { |
245 DcheckIsExtensionSpecificsValid(server_data); | 266 DcheckIsExtensionSpecificsValid(server_data); |
246 ExtensionData extension_data = | 267 ExtensionData extension_data = |
247 ExtensionData::FromData(ExtensionData::SERVER, server_data); | 268 ExtensionData::FromData(ExtensionData::SERVER, server_data); |
248 sync_pb::ExtensionSpecifics client_data; | 269 ExtensionsService* extensions_service = GetExtensionsService(); |
249 if (GetExtensionDataFromClient(server_data.id(), &client_data)) { | 270 Extension* extension = |
250 ExtensionData extension_data = | 271 extensions_service->GetExtensionById(server_data.id(), true); |
| 272 if (extension) { |
| 273 if (!IsExtensionSyncable(*extension)) { |
| 274 // Ignore updates for non-syncable extensions (we may get those |
| 275 // for extensions that were previously syncable). |
| 276 return; |
| 277 } |
| 278 sync_pb::ExtensionSpecifics client_data; |
| 279 GetExtensionSpecifics(*extension, extensions_service, &client_data); |
| 280 DcheckIsExtensionSpecificsValid(client_data); |
| 281 extension_data = |
251 ExtensionData::FromData(ExtensionData::CLIENT, client_data); | 282 ExtensionData::FromData(ExtensionData::CLIENT, client_data); |
252 extension_data.SetData(ExtensionData::SERVER, true, server_data); | 283 extension_data.SetData(ExtensionData::SERVER, true, server_data); |
253 } | 284 } |
254 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER)); | 285 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER)); |
255 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) { | 286 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) { |
256 TryUpdateClient(&extension_data); | 287 TryUpdateClient(&extension_data); |
257 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) { | 288 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) { |
258 NudgeExtensionUpdater(); | 289 NudgeExtensionUpdater(); |
259 } | 290 } |
260 } | 291 } |
261 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER)); | 292 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER)); |
262 } | 293 } |
263 | 294 |
264 void ExtensionModelAssociator::OnServerRemove(const std::string& id) { | 295 void ExtensionModelAssociator::OnServerRemove(const std::string& id) { |
265 ExtensionsService* extensions_service = GetExtensionsService(); | 296 ExtensionsService* extensions_service = GetExtensionsService(); |
266 Extension* extension = extensions_service->GetExtensionById(id, true); | 297 Extension* extension = extensions_service->GetExtensionById(id, true); |
267 if (extension) { | 298 if (extension) { |
268 extensions_service->UninstallExtension(id, false); | 299 if (IsExtensionSyncable(*extension)) { |
| 300 extensions_service->UninstallExtension(id, false); |
| 301 } |
269 } else { | 302 } else { |
270 LOG(ERROR) << "Trying to uninstall nonexistent extension " << id; | 303 LOG(ERROR) << "Trying to uninstall nonexistent extension " << id; |
271 } | 304 } |
272 } | 305 } |
273 | 306 |
274 ExtensionsService* ExtensionModelAssociator::GetExtensionsService() { | 307 ExtensionsService* ExtensionModelAssociator::GetExtensionsService() { |
275 CHECK(sync_service_); | 308 CHECK(sync_service_); |
276 Profile* profile = sync_service_->profile(); | 309 Profile* profile = sync_service_->profile(); |
277 CHECK(profile); | 310 CHECK(profile); |
278 ExtensionsService* extensions_service = profile->GetExtensionsService(); | 311 ExtensionsService* extensions_service = profile->GetExtensionsService(); |
279 CHECK(extensions_service); | 312 CHECK(extensions_service); |
280 return extensions_service; | 313 return extensions_service; |
281 } | 314 } |
282 | 315 |
283 bool ExtensionModelAssociator::GetExtensionDataFromClient( | |
284 const std::string& id, sync_pb::ExtensionSpecifics* client_data) { | |
285 ExtensionsService* extensions_service = GetExtensionsService(); | |
286 Extension* extension = extensions_service->GetExtensionById(id, true); | |
287 if (!extension) { | |
288 return false; | |
289 } | |
290 GetExtensionSpecifics(*extension, extensions_service, client_data); | |
291 DcheckIsExtensionSpecificsValid(*client_data); | |
292 return true; | |
293 } | |
294 | |
295 bool ExtensionModelAssociator::GetExtensionDataFromServer( | 316 bool ExtensionModelAssociator::GetExtensionDataFromServer( |
296 const std::string& id, sync_api::WriteTransaction* trans, | 317 const std::string& id, sync_api::WriteTransaction* trans, |
297 const sync_api::ReadNode& root, | 318 const sync_api::ReadNode& root, |
298 sync_pb::ExtensionSpecifics* server_data) { | 319 sync_pb::ExtensionSpecifics* server_data) { |
299 sync_api::ReadNode sync_node(trans); | 320 sync_api::ReadNode sync_node(trans); |
300 if (!sync_node.InitByClientTagLookup(syncable::EXTENSIONS, id)) { | 321 if (!sync_node.InitByClientTagLookup(syncable::EXTENSIONS, id)) { |
301 LOG(ERROR) << "Failed to fetch sync node for id " << id; | 322 LOG(ERROR) << "Failed to fetch sync node for id " << id; |
302 return false; | 323 return false; |
303 } | 324 } |
304 const sync_pb::ExtensionSpecifics& read_server_data = | 325 const sync_pb::ExtensionSpecifics& read_server_data = |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 ExtensionData* extension_data) { | 374 ExtensionData* extension_data) { |
354 DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER)); | 375 DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER)); |
355 DCHECK(extension_data->NeedsUpdate(ExtensionData::CLIENT)); | 376 DCHECK(extension_data->NeedsUpdate(ExtensionData::CLIENT)); |
356 const sync_pb::ExtensionSpecifics& specifics = | 377 const sync_pb::ExtensionSpecifics& specifics = |
357 extension_data->merged_data(); | 378 extension_data->merged_data(); |
358 DcheckIsExtensionSpecificsValid(specifics); | 379 DcheckIsExtensionSpecificsValid(specifics); |
359 ExtensionsService* extensions_service = GetExtensionsService(); | 380 ExtensionsService* extensions_service = GetExtensionsService(); |
360 const std::string& id = specifics.id(); | 381 const std::string& id = specifics.id(); |
361 Extension* extension = extensions_service->GetExtensionById(id, true); | 382 Extension* extension = extensions_service->GetExtensionById(id, true); |
362 if (extension) { | 383 if (extension) { |
| 384 if (!IsExtensionSyncable(*extension)) { |
| 385 LOG(DFATAL) << "TryUpdateClient() called for non-syncable extension " |
| 386 << extension->id(); |
| 387 return; |
| 388 } |
363 SetExtensionProperties(specifics, extensions_service, extension); | 389 SetExtensionProperties(specifics, extensions_service, extension); |
364 { | 390 { |
365 sync_pb::ExtensionSpecifics extension_specifics; | 391 sync_pb::ExtensionSpecifics extension_specifics; |
366 GetExtensionSpecifics(*extension, extensions_service, | 392 GetExtensionSpecifics(*extension, extensions_service, |
367 &extension_specifics); | 393 &extension_specifics); |
368 DCHECK(AreExtensionSpecificsUserPropertiesEqual( | 394 DCHECK(AreExtensionSpecificsUserPropertiesEqual( |
369 specifics, extension_specifics)) | 395 specifics, extension_specifics)) |
370 << ExtensionSpecificsToString(specifics) << ", " | 396 << ExtensionSpecificsToString(specifics) << ", " |
371 << ExtensionSpecificsToString(extension_specifics); | 397 << ExtensionSpecificsToString(extension_specifics); |
372 } | 398 } |
(...skipping 18 matching lines...) Expand all Loading... |
391 // ExtensionsService in ProfileImpl::InitExtensions()). | 417 // ExtensionsService in ProfileImpl::InitExtensions()). |
392 if (extension_updater) { | 418 if (extension_updater) { |
393 extension_updater->CheckNow(); | 419 extension_updater->CheckNow(); |
394 } else { | 420 } else { |
395 LOG(DFATAL) << "Extension updater unexpectedly NULL; " | 421 LOG(DFATAL) << "Extension updater unexpectedly NULL; " |
396 << "auto-updates may be turned off"; | 422 << "auto-updates may be turned off"; |
397 } | 423 } |
398 } | 424 } |
399 | 425 |
400 } // namespace browser_sync | 426 } // namespace browser_sync |
OLD | NEW |