OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/ui/app_list/app_list_syncable_service.h" | 5 #include "chrome/browser/ui/app_list/app_list_syncable_service.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "chrome/browser/chrome_notification_types.h" | 8 #include "chrome/browser/chrome_notification_types.h" |
9 #include "chrome/browser/extensions/extension_prefs.h" | |
9 #include "chrome/browser/extensions/extension_service.h" | 10 #include "chrome/browser/extensions/extension_service.h" |
10 #include "chrome/browser/extensions/extension_system.h" | 11 #include "chrome/browser/extensions/extension_system.h" |
11 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
12 #include "chrome/browser/ui/app_list/app_list_service.h" | 13 #include "chrome/browser/ui/app_list/app_list_service.h" |
13 #include "chrome/browser/ui/app_list/extension_app_item.h" | 14 #include "chrome/browser/ui/app_list/extension_app_item.h" |
14 #include "chrome/browser/ui/app_list/extension_app_model_builder.h" | 15 #include "chrome/browser/ui/app_list/extension_app_model_builder.h" |
15 #include "chrome/browser/ui/host_desktop.h" | 16 #include "chrome/browser/ui/host_desktop.h" |
16 #include "chrome/common/chrome_switches.h" | 17 #include "chrome/common/chrome_switches.h" |
17 #include "content/public/browser/notification_source.h" | 18 #include "content/public/browser/notification_source.h" |
18 #include "sync/api/sync_change_processor.h" | 19 #include "sync/api/sync_change_processor.h" |
19 #include "sync/api/sync_data.h" | 20 #include "sync/api/sync_data.h" |
20 #include "sync/api/sync_merge_result.h" | 21 #include "sync/api/sync_merge_result.h" |
21 #include "sync/protocol/sync.pb.h" | 22 #include "sync/protocol/sync.pb.h" |
23 #include "ui/app_list/app_list_folder_item.h" | |
22 #include "ui/app_list/app_list_item.h" | 24 #include "ui/app_list/app_list_item.h" |
23 #include "ui/app_list/app_list_model.h" | 25 #include "ui/app_list/app_list_model.h" |
24 | 26 |
25 using syncer::SyncChange; | 27 using syncer::SyncChange; |
26 | 28 |
27 namespace app_list { | 29 namespace app_list { |
28 | 30 |
29 namespace { | 31 namespace { |
30 | 32 |
31 void UpdateSyncItemFromSync(const sync_pb::AppListSpecifics& specifics, | 33 void UpdateSyncItemFromSync(const sync_pb::AppListSpecifics& specifics, |
32 AppListSyncableService::SyncItem* item) { | 34 AppListSyncableService::SyncItem* item) { |
33 DCHECK_EQ(item->item_id, specifics.item_id()); | 35 DCHECK_EQ(item->item_id, specifics.item_id()); |
34 item->item_type = specifics.item_type(); | 36 item->item_type = specifics.item_type(); |
35 item->item_name = specifics.item_name(); | 37 item->item_name = specifics.item_name(); |
36 item->parent_id = specifics.parent_id(); | 38 item->parent_id = specifics.parent_id(); |
37 if (!specifics.page_ordinal().empty()) | 39 if (!specifics.page_ordinal().empty()) |
38 item->page_ordinal = syncer::StringOrdinal(specifics.page_ordinal()); | 40 item->page_ordinal = syncer::StringOrdinal(specifics.page_ordinal()); |
39 if (!specifics.item_ordinal().empty()) | 41 if (!specifics.item_ordinal().empty()) |
40 item->item_ordinal = syncer::StringOrdinal(specifics.item_ordinal()); | 42 item->item_ordinal = syncer::StringOrdinal(specifics.item_ordinal()); |
41 } | 43 } |
42 | 44 |
43 bool UpdateSyncItemFromAppItem(const AppListItem* app_item, | 45 bool UpdateSyncItemFromAppItem(const AppListItem* app_item, |
44 AppListSyncableService::SyncItem* sync_item) { | 46 AppListSyncableService::SyncItem* sync_item) { |
45 DCHECK_EQ(sync_item->item_id, app_item->id()); | 47 DCHECK_EQ(sync_item->item_id, app_item->id()); |
46 bool changed = false; | 48 bool changed = false; |
49 if (sync_item->item_name != app_item->title()) { | |
50 sync_item->item_name = app_item->title(); | |
51 changed = true; | |
52 } | |
47 if (!sync_item->item_ordinal.IsValid() || | 53 if (!sync_item->item_ordinal.IsValid() || |
48 !app_item->position().Equals(sync_item->item_ordinal)) { | 54 !app_item->position().Equals(sync_item->item_ordinal)) { |
49 sync_item->item_ordinal = app_item->position(); | 55 sync_item->item_ordinal = app_item->position(); |
50 changed = true; | 56 changed = true; |
51 } | 57 } |
52 // TODO(stevenjb): Set parent_id and page_ordinal. | 58 // TODO(stevenjb): Set parent_id and page_ordinal. |
53 return changed; | 59 return changed; |
54 } | 60 } |
55 | 61 |
56 void GetSyncSpecificsFromSyncItem(const AppListSyncableService::SyncItem* item, | 62 void GetSyncSpecificsFromSyncItem(const AppListSyncableService::SyncItem* item, |
(...skipping 11 matching lines...) Expand all Loading... | |
68 | 74 |
69 syncer::SyncData GetSyncDataFromSyncItem( | 75 syncer::SyncData GetSyncDataFromSyncItem( |
70 const AppListSyncableService::SyncItem* item) { | 76 const AppListSyncableService::SyncItem* item) { |
71 sync_pb::EntitySpecifics specifics; | 77 sync_pb::EntitySpecifics specifics; |
72 GetSyncSpecificsFromSyncItem(item, specifics.mutable_app_list()); | 78 GetSyncSpecificsFromSyncItem(item, specifics.mutable_app_list()); |
73 return syncer::SyncData::CreateLocalData(item->item_id, | 79 return syncer::SyncData::CreateLocalData(item->item_id, |
74 item->item_id, | 80 item->item_id, |
75 specifics); | 81 specifics); |
76 } | 82 } |
77 | 83 |
84 bool AppIsDefault(ExtensionService* service, const std::string& id) { | |
85 return service && service->extension_prefs()->WasInstalledByDefault(id); | |
86 } | |
87 | |
88 bool AppIsPlatformApp(ExtensionService* service, const std::string& id) { | |
89 if (!service) | |
90 return false; | |
91 const extensions::Extension* app = service->GetInstalledExtension(id); | |
92 DVLOG_IF(1, !app) << "No App for ID: " << id; | |
93 return app ? app->is_platform_app() : false; | |
94 } | |
95 | |
96 void UninstallExtension(ExtensionService* service, const std::string& id) { | |
97 if (service && service->GetInstalledExtension(id)) | |
98 service->UninstallExtension(id, false, NULL); | |
99 } | |
100 | |
78 } // namespace | 101 } // namespace |
79 | 102 |
80 // AppListSyncableService::SyncItem | 103 // AppListSyncableService::SyncItem |
81 | 104 |
82 AppListSyncableService::SyncItem::SyncItem( | 105 AppListSyncableService::SyncItem::SyncItem( |
83 const std::string& id, | 106 const std::string& id, |
84 sync_pb::AppListSpecifics::AppListItemType type) | 107 sync_pb::AppListSpecifics::AppListItemType type) |
85 : item_id(id), | 108 : item_id(id), |
86 item_type(type) { | 109 item_type(type) { |
87 } | 110 } |
88 | 111 |
89 AppListSyncableService::SyncItem::~SyncItem() { | 112 AppListSyncableService::SyncItem::~SyncItem() { |
90 } | 113 } |
91 | 114 |
92 // AppListSyncableService | 115 // AppListSyncableService |
93 | 116 |
94 AppListSyncableService::AppListSyncableService( | 117 AppListSyncableService::AppListSyncableService( |
95 Profile* profile, | 118 Profile* profile, |
96 ExtensionService* extension_service) | 119 extensions::ExtensionSystem* extension_system) |
97 : profile_(profile), | 120 : profile_(profile), |
121 extension_system_(extension_system), | |
98 model_(new AppListModel) { | 122 model_(new AppListModel) { |
99 if (extension_service && extension_service->is_ready()) { | 123 if (!extension_system || !extension_system->extension_service()) { |
124 LOG(WARNING) << "AppListSyncableService created with no ExtensionService"; | |
125 return; | |
126 } | |
127 | |
128 if (extension_system->extension_service()->is_ready()) { | |
100 BuildModel(); | 129 BuildModel(); |
101 return; | 130 return; |
102 } | 131 } |
103 | 132 |
104 // The extensions for this profile have not yet all been loaded. | 133 // The extensions for this profile have not yet all been loaded. |
105 registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY, | 134 registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY, |
106 content::Source<Profile>(profile)); | 135 content::Source<Profile>(profile)); |
107 } | 136 } |
108 | 137 |
109 AppListSyncableService::~AppListSyncableService() { | 138 AppListSyncableService::~AppListSyncableService() { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
145 } | 174 } |
146 | 175 |
147 const AppListSyncableService::SyncItem* | 176 const AppListSyncableService::SyncItem* |
148 AppListSyncableService::GetSyncItem(const std::string& id) const { | 177 AppListSyncableService::GetSyncItem(const std::string& id) const { |
149 SyncItemMap::const_iterator iter = sync_items_.find(id); | 178 SyncItemMap::const_iterator iter = sync_items_.find(id); |
150 if (iter != sync_items_.end()) | 179 if (iter != sync_items_.end()) |
151 return iter->second; | 180 return iter->second; |
152 return NULL; | 181 return NULL; |
153 } | 182 } |
154 | 183 |
155 void AppListSyncableService::AddExtensionAppItem(ExtensionAppItem* item) { | 184 void AppListSyncableService::AddItem(AppListItem* item) { |
156 SyncItem* sync_item = AddItem( | 185 const std::string& item_id = item->id(); |
157 sync_pb::AppListSpecifics_AppListItemType_TYPE_APP, item); | 186 if (item_id.empty()) { |
158 if (!sync_item) | 187 LOG(ERROR) << "AppListItem item with empty ID"; |
159 return; // Item already exists. | 188 return; |
160 sync_item->item_name = item->extension_name(); | 189 } |
190 sync_pb::AppListSpecifics::AppListItemType type; | |
191 const char* item_type = item->GetAppType(); | |
192 if (item_type == ExtensionAppItem::kAppType) { | |
193 type = sync_pb::AppListSpecifics_AppListItemType_TYPE_APP; | |
194 } else if (item_type == AppListFolderItem::kAppType) { | |
195 type = sync_pb::AppListSpecifics_AppListItemType_TYPE_FOLDER; | |
196 } else { | |
197 LOG(ERROR) << "Unrecognized model type: " << item_type; | |
198 return; | |
199 } | |
200 SyncItem* sync_item = FindSyncItem(item_id); | |
201 if (sync_item) { | |
202 // If there is an existing, non-REMOVE_DEFAULT entry, update it. | |
203 if (sync_item->item_type != | |
204 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { | |
205 DCHECK_EQ(sync_item->item_type, type); | |
206 DVLOG(2) << this << ": AddItem already exists: " << sync_item->ToString(); | |
207 UpdateItem(item); | |
208 return; | |
209 } | |
210 // If there is an existing REMOVE_DEFAULT_APP entry, and the app is | |
211 // installed as a Default app, uninstall the app instead of adding it. | |
212 if (type == sync_pb::AppListSpecifics_AppListItemType_TYPE_APP && | |
213 AppIsDefault(extension_system_->extension_service(), item_id)) { | |
214 DVLOG(1) << this << ": AddItem: Uninstall: " << sync_item->ToString(); | |
215 UninstallExtension(extension_system_->extension_service(), item_id); | |
Nicolas Zea
2013/12/30 19:49:00
Has the App already been installed at this point?
stevenjb
2014/01/02 21:15:49
Default apps are installed once on creation of a n
| |
216 return; | |
217 } | |
218 // Otherwise, we are adding the app as a non-default app (i.e. an app that | |
219 // was installed by Default and removed is getting installed explicitly by | |
220 // the user), so delete the REMOVE_DEFAULT_APP. | |
221 if (SyncStarted()) { | |
222 DVLOG(2) << this << " -> SYNC DELETE: " << sync_item->ToString(); | |
223 SyncChange sync_change(FROM_HERE, SyncChange::ACTION_DELETE, | |
224 GetSyncDataFromSyncItem(sync_item)); | |
225 sync_processor_->ProcessSyncChanges( | |
226 FROM_HERE, syncer::SyncChangeList(1, sync_change)); | |
227 } | |
228 delete sync_item; | |
229 sync_items_.erase(item_id); | |
230 // Fall through. The REMOVE_DEFAULT_APP entry has been deleted, now an App | |
231 // entry can be added as usual. | |
232 } | |
233 | |
234 sync_item = CreateSyncItem(item_id, type); | |
235 UpdateSyncItemFromAppItem(item, sync_item); | |
236 model_->item_list()->AddItem(item); | |
237 DVLOG(1) << this << ": AddItem: " << sync_item->ToString() << " Default: " | |
238 << AppIsDefault(extension_system_->extension_service(), item->id()); | |
161 SendSyncChange(sync_item, SyncChange::ACTION_ADD); | 239 SendSyncChange(sync_item, SyncChange::ACTION_ADD); |
162 } | 240 } |
163 | 241 |
164 void AppListSyncableService::UpdateExtensionAppItem(ExtensionAppItem* item) { | 242 void AppListSyncableService::UpdateItem(AppListItem* item) { |
165 SyncItem* sync_item = FindSyncItem(item->id()); | 243 SyncItem* sync_item = FindSyncItem(item->id()); |
166 if (!sync_item) { | 244 if (!sync_item) { |
167 LOG(ERROR) << "UpdateExtensionAppItem: no sync item: " << item->id(); | 245 LOG(ERROR) << "UpdateItem: no sync item: " << item->id(); |
168 return; | 246 return; |
169 } | 247 } |
170 bool changed = UpdateSyncItemFromAppItem(item, sync_item); | 248 bool changed = UpdateSyncItemFromAppItem(item, sync_item); |
171 if (sync_item->item_name != item->extension_name()) { | |
172 sync_item->item_name = item->extension_name(); | |
173 changed = true; | |
174 } | |
175 if (!changed) { | 249 if (!changed) { |
176 DVLOG(2) << this << " - Update: SYNC NO CHANGE: " << sync_item->ToString(); | 250 DVLOG(2) << this << " - Update: SYNC NO CHANGE: " << sync_item->ToString(); |
177 return; | 251 return; |
178 } | 252 } |
179 SendSyncChange(sync_item, SyncChange::ACTION_UPDATE); | 253 SendSyncChange(sync_item, SyncChange::ACTION_UPDATE); |
180 } | 254 } |
181 | 255 |
182 void AppListSyncableService::RemoveItem(const std::string& id) { | 256 void AppListSyncableService::RemoveItem(const std::string& id) { |
183 DVLOG(2) << this << ": RemoveItem: " << id.substr(0, 8); | 257 DVLOG(2) << this << ": RemoveItem: " << id.substr(0, 8); |
184 SyncItemMap::iterator iter = sync_items_.find(id); | 258 SyncItemMap::iterator iter = sync_items_.find(id); |
185 if (iter == sync_items_.end()) | 259 if (iter == sync_items_.end()) { |
260 DVLOG(2) << this << " : No Sync Item."; | |
186 return; | 261 return; |
262 } | |
263 // Always delete the item from the model. | |
264 model_->item_list()->DeleteItem(id); | |
265 | |
266 // Check for existing RemoveDefault sync item. | |
187 SyncItem* sync_item = iter->second; | 267 SyncItem* sync_item = iter->second; |
268 if (sync_item->item_type == | |
269 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { | |
270 // RemoveDefault item exists, just return. | |
271 DVLOG(2) << this << " : RemoveDefault Item exists."; | |
272 return; | |
273 } | |
274 | |
275 // Existing entry is a normal entry, send a Delete sync change and remove | |
276 // the entry. | |
188 if (SyncStarted()) { | 277 if (SyncStarted()) { |
189 DVLOG(2) << this << " -> SYNC DELETE: " << sync_item->ToString(); | 278 DVLOG(2) << this << " -> SYNC DELETE: " << sync_item->ToString(); |
190 SyncChange sync_change(FROM_HERE, SyncChange::ACTION_DELETE, | 279 SyncChange sync_change(FROM_HERE, SyncChange::ACTION_DELETE, |
191 GetSyncDataFromSyncItem(sync_item)); | 280 GetSyncDataFromSyncItem(sync_item)); |
192 sync_processor_->ProcessSyncChanges( | 281 sync_processor_->ProcessSyncChanges( |
193 FROM_HERE, syncer::SyncChangeList(1, sync_change)); | 282 FROM_HERE, syncer::SyncChangeList(1, sync_change)); |
194 } | 283 } |
195 delete sync_item; | 284 delete sync_item; |
196 sync_items_.erase(iter); | 285 sync_items_.erase(iter); |
197 model_->item_list()->DeleteItem(id); | 286 |
287 if (!AppIsDefault(extension_system_->extension_service(), id)) | |
288 return; | |
289 // This is a Default app; create and send a REMOVE_DEFAULT sync change. | |
290 // Note: we add the REMOVE_DEFAULT entry after we delete the existing entry. | |
291 sync_item = CreateSyncItem( | |
292 id, sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP); | |
293 DVLOG(1) << this << ": RemoveDefaultItem: " << sync_item->ToString(); | |
294 SendSyncChange(sync_item, SyncChange::ACTION_ADD); | |
198 } | 295 } |
199 | 296 |
200 // AppListSyncableService syncer::SyncableService | 297 // AppListSyncableService syncer::SyncableService |
201 | 298 |
202 syncer::SyncMergeResult AppListSyncableService::MergeDataAndStartSyncing( | 299 syncer::SyncMergeResult AppListSyncableService::MergeDataAndStartSyncing( |
203 syncer::ModelType type, | 300 syncer::ModelType type, |
204 const syncer::SyncDataList& initial_sync_data, | 301 const syncer::SyncDataList& initial_sync_data, |
205 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, | 302 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, |
206 scoped_ptr<syncer::SyncErrorFactory> error_handler) { | 303 scoped_ptr<syncer::SyncErrorFactory> error_handler) { |
207 DCHECK(!sync_processor_.get()); | 304 DCHECK(!sync_processor_.get()); |
(...skipping 13 matching lines...) Expand all Loading... | |
221 for (SyncItemMap::const_iterator iter = sync_items_.begin(); | 318 for (SyncItemMap::const_iterator iter = sync_items_.begin(); |
222 iter != sync_items_.end(); ++iter) { | 319 iter != sync_items_.end(); ++iter) { |
223 unsynced_items.insert(iter->first); | 320 unsynced_items.insert(iter->first); |
224 } | 321 } |
225 | 322 |
226 // Create SyncItem entries for initial_sync_data. | 323 // Create SyncItem entries for initial_sync_data. |
227 size_t new_items = 0, updated_items = 0; | 324 size_t new_items = 0, updated_items = 0; |
228 for (syncer::SyncDataList::const_iterator iter = initial_sync_data.begin(); | 325 for (syncer::SyncDataList::const_iterator iter = initial_sync_data.begin(); |
229 iter != initial_sync_data.end(); ++iter) { | 326 iter != initial_sync_data.end(); ++iter) { |
230 const syncer::SyncData& data = *iter; | 327 const syncer::SyncData& data = *iter; |
328 DVLOG(2) << this << " Initial Sync Item: " | |
329 << data.GetSpecifics().app_list().item_id() | |
330 << " Type: " << data.GetSpecifics().app_list().item_type(); | |
231 DCHECK_EQ(syncer::APP_LIST, data.GetDataType()); | 331 DCHECK_EQ(syncer::APP_LIST, data.GetDataType()); |
232 if (CreateOrUpdateSyncItem(data.GetSpecifics().app_list())) | 332 if (ProcessSyncItem(data.GetSpecifics().app_list())) |
233 ++new_items; | 333 ++new_items; |
234 else | 334 else |
235 ++updated_items; | 335 ++updated_items; |
236 unsynced_items.erase(data.GetSpecifics().app_list().item_id()); | 336 unsynced_items.erase(data.GetSpecifics().app_list().item_id()); |
237 } | 337 } |
238 | 338 |
239 result.set_num_items_after_association(sync_items_.size()); | 339 result.set_num_items_after_association(sync_items_.size()); |
240 result.set_num_items_added(new_items); | 340 result.set_num_items_added(new_items); |
241 result.set_num_items_deleted(0); | 341 result.set_num_items_deleted(0); |
242 result.set_num_items_modified(updated_items); | 342 result.set_num_items_modified(updated_items); |
(...skipping 16 matching lines...) Expand all Loading... | |
259 DCHECK_EQ(type, syncer::APP_LIST); | 359 DCHECK_EQ(type, syncer::APP_LIST); |
260 | 360 |
261 sync_processor_.reset(); | 361 sync_processor_.reset(); |
262 sync_error_handler_.reset(); | 362 sync_error_handler_.reset(); |
263 } | 363 } |
264 | 364 |
265 syncer::SyncDataList AppListSyncableService::GetAllSyncData( | 365 syncer::SyncDataList AppListSyncableService::GetAllSyncData( |
266 syncer::ModelType type) const { | 366 syncer::ModelType type) const { |
267 DCHECK_EQ(syncer::APP_LIST, type); | 367 DCHECK_EQ(syncer::APP_LIST, type); |
268 | 368 |
269 DVLOG(1) << this << "GetAllSyncData: " << sync_items_.size(); | 369 DVLOG(1) << this << ": GetAllSyncData: " << sync_items_.size(); |
270 syncer::SyncDataList list; | 370 syncer::SyncDataList list; |
271 for (SyncItemMap::const_iterator iter = sync_items_.begin(); | 371 for (SyncItemMap::const_iterator iter = sync_items_.begin(); |
272 iter != sync_items_.end(); ++iter) { | 372 iter != sync_items_.end(); ++iter) { |
273 DVLOG(2) << this << " -> SYNC: " << iter->second->ToString(); | 373 DVLOG(2) << this << " -> SYNC: " << iter->second->ToString(); |
274 list.push_back(GetSyncDataFromSyncItem(iter->second)); | 374 list.push_back(GetSyncDataFromSyncItem(iter->second)); |
275 } | 375 } |
276 return list; | 376 return list; |
277 } | 377 } |
278 | 378 |
279 syncer::SyncError AppListSyncableService::ProcessSyncChanges( | 379 syncer::SyncError AppListSyncableService::ProcessSyncChanges( |
280 const tracked_objects::Location& from_here, | 380 const tracked_objects::Location& from_here, |
281 const syncer::SyncChangeList& change_list) { | 381 const syncer::SyncChangeList& change_list) { |
282 if (!sync_processor_.get()) { | 382 if (!sync_processor_.get()) { |
283 return syncer::SyncError(FROM_HERE, | 383 return syncer::SyncError(FROM_HERE, |
284 syncer::SyncError::DATATYPE_ERROR, | 384 syncer::SyncError::DATATYPE_ERROR, |
285 "App List syncable service is not started.", | 385 "App List syncable service is not started.", |
286 syncer::APP_LIST); | 386 syncer::APP_LIST); |
287 } | 387 } |
288 | 388 |
289 // Process incoming changes first. | |
290 DVLOG(1) << this << ": ProcessSyncChanges: " << change_list.size(); | 389 DVLOG(1) << this << ": ProcessSyncChanges: " << change_list.size(); |
291 for (syncer::SyncChangeList::const_iterator iter = change_list.begin(); | 390 for (syncer::SyncChangeList::const_iterator iter = change_list.begin(); |
292 iter != change_list.end(); ++iter) { | 391 iter != change_list.end(); ++iter) { |
293 const SyncChange& change = *iter; | 392 const SyncChange& change = *iter; |
393 DVLOG(2) << this << " Change: " | |
394 << change.sync_data().GetSpecifics().app_list().item_id() | |
395 << " (" << change.change_type() << ")"; | |
294 if (change.change_type() == SyncChange::ACTION_ADD || | 396 if (change.change_type() == SyncChange::ACTION_ADD || |
295 change.change_type() == SyncChange::ACTION_UPDATE) { | 397 change.change_type() == SyncChange::ACTION_UPDATE) { |
296 CreateOrUpdateSyncItem(change.sync_data().GetSpecifics().app_list()); | 398 ProcessSyncItem(change.sync_data().GetSpecifics().app_list()); |
297 } else if (change.change_type() == SyncChange::ACTION_DELETE) { | 399 } else if (change.change_type() == SyncChange::ACTION_DELETE) { |
298 DeleteSyncItem(change.sync_data().GetSpecifics().app_list()); | 400 DeleteSyncItem(change.sync_data().GetSpecifics().app_list()); |
299 } else { | 401 } else { |
300 LOG(ERROR) << "Invalid sync change"; | 402 LOG(ERROR) << "Invalid sync change"; |
301 } | 403 } |
302 } | 404 } |
303 return syncer::SyncError(); | 405 return syncer::SyncError(); |
304 } | 406 } |
305 | 407 |
306 // AppListSyncableService private | 408 // AppListSyncableService private |
307 | 409 |
308 void AppListSyncableService::CreateAppItemFromSyncItem(SyncItem* sync_item) { | 410 bool AppListSyncableService::ProcessSyncItem( |
309 if (sync_item->item_type == sync_pb::AppListSpecifics::TYPE_APP) { | 411 const sync_pb::AppListSpecifics& specifics) { |
310 std::string extension_id = sync_item->item_id; | 412 const std::string& item_id = specifics.item_id(); |
311 const ExtensionService* extension_service = | 413 if (item_id.empty()) { |
312 extensions::ExtensionSystem::Get(profile_)->extension_service(); | 414 LOG(ERROR) << "AppList item with empty ID"; |
313 const extensions::Extension* app = | 415 return false; |
314 extension_service->GetInstalledExtension(extension_id); | |
315 DVLOG_IF(1, !app) << this << "No App for ID: " << extension_id; | |
316 bool is_platform_app = app ? app->is_platform_app() : false; | |
317 ExtensionAppItem* app_item = new ExtensionAppItem( | |
318 profile_, | |
319 sync_item, | |
320 extension_id, | |
321 sync_item->item_name, | |
322 gfx::ImageSkia(), | |
323 is_platform_app); | |
324 model_->item_list()->AddItem(app_item); | |
325 return; | |
326 } | 416 } |
327 if (sync_item->item_type == | 417 SyncItem* sync_item = FindSyncItem(item_id); |
418 if (sync_item) { | |
419 // If an item of the same type exists, update it. | |
420 if (sync_item->item_type == specifics.item_type()) { | |
421 UpdateSyncItemFromSync(specifics, sync_item); | |
422 ProcessExistingSyncItem(sync_item); | |
423 DVLOG(2) << this << " <- SYNC UPDATE: " << sync_item->ToString(); | |
424 return false; | |
425 } | |
426 // Otherwise, one of the entries should be TYPE_REMOVE_DEFAULT_APP. | |
427 if (sync_item->item_type != | |
428 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP && | |
429 specifics.item_type() != | |
430 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { | |
431 LOG(ERROR) << "Synced item type: " << specifics.item_type() | |
432 << " != existing sync item type: " << sync_item->item_type | |
433 << " Deleting item from model!"; | |
434 model_->item_list()->DeleteItem(item_id); | |
435 } | |
436 DVLOG(2) << this << " - ProcessSyncItem: Delete existing entry: " | |
437 << sync_item->ToString(); | |
438 delete sync_item; | |
439 sync_items_.erase(item_id); | |
440 } | |
441 | |
442 sync_item = CreateSyncItem(item_id, specifics.item_type()); | |
443 UpdateSyncItemFromSync(specifics, sync_item); | |
444 ProcessNewSyncItem(sync_item); | |
445 DVLOG(2) << this << " <- SYNC ADD: " << sync_item->ToString(); | |
446 return true; | |
447 } | |
448 | |
449 void AppListSyncableService::ProcessNewSyncItem(SyncItem* sync_item) { | |
450 switch (sync_item->item_type) { | |
451 case sync_pb::AppListSpecifics::TYPE_APP: { | |
452 std::string extension_id = sync_item->item_id; | |
453 bool is_platform_app = | |
454 AppIsPlatformApp(extension_system_->extension_service(), | |
455 extension_id); | |
456 ExtensionAppItem* app_item = new ExtensionAppItem( | |
457 profile_, | |
458 sync_item, | |
459 extension_id, | |
460 sync_item->item_name, | |
461 gfx::ImageSkia(), | |
462 is_platform_app); | |
463 model_->item_list()->AddItem(app_item); | |
464 return; | |
465 } | |
466 case sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP: { | |
467 DVLOG(1) << this << ": Uninstall: " << sync_item->ToString(); | |
468 UninstallExtension(extension_system_->extension_service(), | |
469 sync_item->item_id); | |
470 return; | |
471 } | |
472 case sync_pb::AppListSpecifics::TYPE_FOLDER: { | |
473 // TODO(stevenjb): Implement | |
474 LOG(WARNING) << "TYPE_FOLDER not supported"; | |
475 return; | |
476 } | |
477 case sync_pb::AppListSpecifics::TYPE_URL: { | |
478 // TODO(stevenjb): Implement | |
479 LOG(WARNING) << "TYPE_URL not supported"; | |
480 return; | |
481 } | |
482 } | |
483 NOTREACHED() << "Unrecoginized sync item type: " << sync_item->ToString(); | |
484 } | |
485 | |
486 void AppListSyncableService::ProcessExistingSyncItem(SyncItem* sync_item) { | |
487 if (sync_item->item_type != | |
328 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { | 488 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { |
329 // TODO(stevenjb): Implement | 489 AppListItem* item = model_->item_list()->FindItem(sync_item->item_id); |
490 if (item && !item->position().Equals(sync_item->item_ordinal)) | |
491 model_->item_list()->SetItemPosition(item, sync_item->item_ordinal); | |
330 } | 492 } |
331 if (sync_item->item_type == sync_pb::AppListSpecifics::TYPE_FOLDER) { | |
332 // TODO(stevenjb): Implement | |
333 } | |
334 if (sync_item->item_type == sync_pb::AppListSpecifics::TYPE_URL) { | |
335 // TODO(stevenjb): Implement | |
336 } | |
337 LOG(ERROR) << "Unsupported type: " << sync_item->item_type; | |
338 } | 493 } |
339 | 494 |
340 bool AppListSyncableService::SyncStarted() { | 495 bool AppListSyncableService::SyncStarted() { |
341 if (sync_processor_.get()) | 496 if (sync_processor_.get()) |
342 return true; | 497 return true; |
343 if (flare_.is_null()) { | 498 if (flare_.is_null()) { |
344 DVLOG(2) << this << ": SyncStarted: Flare."; | 499 DVLOG(2) << this << ": SyncStarted: Flare."; |
345 flare_ = sync_start_util::GetFlareForSyncableService(profile_->GetPath()); | 500 flare_ = sync_start_util::GetFlareForSyncableService(profile_->GetPath()); |
346 flare_.Run(syncer::APP_LIST); | 501 flare_.Run(syncer::APP_LIST); |
347 } | 502 } |
348 return false; | 503 return false; |
349 } | 504 } |
350 | 505 |
351 AppListSyncableService::SyncItem* AppListSyncableService::AddItem( | |
352 sync_pb::AppListSpecifics::AppListItemType type, | |
353 AppListItem* app_item) { | |
354 const std::string& item_id = app_item->id(); | |
355 if (item_id.empty()) { | |
356 LOG(ERROR) << "AppListItem item with empty ID"; | |
357 return NULL; | |
358 } | |
359 bool new_item = false; | |
360 SyncItem* sync_item = FindOrCreateSyncItem(item_id, type, &new_item); | |
361 if (!new_item) { | |
362 DVLOG(2) << this << ": AddItem already exists: " << sync_item->ToString(); | |
363 return NULL; // Item already exists. | |
364 } | |
365 UpdateSyncItemFromAppItem(app_item, sync_item); | |
366 DVLOG(1) << this << ": AddItem: " << sync_item->ToString(); | |
367 model_->item_list()->AddItem(app_item); | |
368 return sync_item; | |
369 } | |
370 | |
371 void AppListSyncableService::SendSyncChange( | 506 void AppListSyncableService::SendSyncChange( |
372 SyncItem* sync_item, | 507 SyncItem* sync_item, |
373 SyncChange::SyncChangeType sync_change_type) { | 508 SyncChange::SyncChangeType sync_change_type) { |
374 if (!SyncStarted()) { | 509 if (!SyncStarted()) { |
375 DVLOG(2) << this << " - SendSyncChange: SYNC NOT STARTED: " | 510 DVLOG(2) << this << " - SendSyncChange: SYNC NOT STARTED: " |
376 << sync_item->ToString(); | 511 << sync_item->ToString(); |
377 return; | 512 return; |
378 } | 513 } |
379 if (sync_change_type == SyncChange::ACTION_ADD) | 514 if (sync_change_type == SyncChange::ACTION_ADD) |
380 DVLOG(2) << this << " -> SYNC ADD: " << sync_item->ToString(); | 515 DVLOG(2) << this << " -> SYNC ADD: " << sync_item->ToString(); |
381 else | 516 else |
382 DVLOG(2) << this << " -> SYNC UPDATE: " << sync_item->ToString(); | 517 DVLOG(2) << this << " -> SYNC UPDATE: " << sync_item->ToString(); |
383 SyncChange sync_change(FROM_HERE, sync_change_type, | 518 SyncChange sync_change(FROM_HERE, sync_change_type, |
384 GetSyncDataFromSyncItem(sync_item)); | 519 GetSyncDataFromSyncItem(sync_item)); |
385 sync_processor_->ProcessSyncChanges( | 520 sync_processor_->ProcessSyncChanges( |
386 FROM_HERE, syncer::SyncChangeList(1, sync_change)); | 521 FROM_HERE, syncer::SyncChangeList(1, sync_change)); |
387 } | 522 } |
388 | 523 |
389 AppListSyncableService::SyncItem* | 524 AppListSyncableService::SyncItem* |
390 AppListSyncableService::FindSyncItem(const std::string& item_id) { | 525 AppListSyncableService::FindSyncItem(const std::string& item_id) { |
391 SyncItemMap::iterator iter = sync_items_.find(item_id); | 526 SyncItemMap::iterator iter = sync_items_.find(item_id); |
392 if (iter == sync_items_.end()) | 527 if (iter == sync_items_.end()) |
393 return NULL; | 528 return NULL; |
394 return iter->second; | 529 return iter->second; |
395 } | 530 } |
396 | 531 |
397 AppListSyncableService::SyncItem* AppListSyncableService::FindOrCreateSyncItem( | 532 AppListSyncableService::SyncItem* |
533 AppListSyncableService::CreateSyncItem( | |
398 const std::string& item_id, | 534 const std::string& item_id, |
399 sync_pb::AppListSpecifics::AppListItemType type, | 535 sync_pb::AppListSpecifics::AppListItemType item_type) { |
400 bool* new_item) { | 536 DCHECK(!ContainsKey(sync_items_, item_id)); |
401 SyncItem* item = FindSyncItem(item_id); | 537 SyncItem* sync_item = new SyncItem(item_id, item_type); |
402 if (item) { | 538 sync_items_[item_id] = sync_item; |
403 DCHECK(type == item->item_type); | 539 return sync_item; |
404 *new_item = false; | |
405 return item; | |
406 } | |
407 | |
408 item = new SyncItem(item_id, type); | |
409 sync_items_[item_id] = item; | |
410 *new_item = true; | |
411 return item; | |
412 } | |
413 | |
414 bool AppListSyncableService::CreateOrUpdateSyncItem( | |
415 const sync_pb::AppListSpecifics& specifics) { | |
416 const std::string& item_id = specifics.item_id(); | |
417 if (item_id.empty()) { | |
418 LOG(ERROR) << "CreateOrUpdate AppList item with empty ID"; | |
419 return false; | |
420 } | |
421 bool new_item = false; | |
422 SyncItem* sync_item = | |
423 FindOrCreateSyncItem(item_id, specifics.item_type(), &new_item); | |
424 DVLOG(2) << this << "CreateOrUpdateSyncItem: " << sync_item->ToString() | |
425 << " New: " << new_item << " Pos: " << specifics.item_ordinal(); | |
426 UpdateSyncItemFromSync(specifics, sync_item); | |
427 // Update existing item in model | |
428 AppListItem* item = model_->item_list()->FindItem(sync_item->item_id); | |
429 if (item && !item->position().Equals(sync_item->item_ordinal)) | |
430 model_->item_list()->SetItemPosition(item, sync_item->item_ordinal); | |
431 if (new_item) { | |
432 CreateAppItemFromSyncItem(sync_item); | |
433 DVLOG(2) << this << " <- SYNC ADD: " << sync_item->ToString(); | |
434 } else { | |
435 DVLOG(2) << this << " <- SYNC UPDATE: " << sync_item->ToString(); | |
436 } | |
437 return new_item; | |
438 } | 540 } |
439 | 541 |
440 void AppListSyncableService::DeleteSyncItem( | 542 void AppListSyncableService::DeleteSyncItem( |
441 const sync_pb::AppListSpecifics& specifics) { | 543 const sync_pb::AppListSpecifics& specifics) { |
442 const std::string& item_id = specifics.item_id(); | 544 const std::string& item_id = specifics.item_id(); |
443 if (item_id.empty()) { | 545 if (item_id.empty()) { |
444 LOG(ERROR) << "Delete AppList item with empty ID"; | 546 LOG(ERROR) << "Delete AppList item with empty ID"; |
445 return; | 547 return; |
446 } | 548 } |
447 DVLOG(2) << this << "DeleteSyncItem: " << item_id.substr(0, 8); | 549 DVLOG(2) << this << ": DeleteSyncItem: " << item_id.substr(0, 8); |
448 SyncItemMap::iterator iter = sync_items_.find(item_id); | 550 SyncItemMap::iterator iter = sync_items_.find(item_id); |
449 if (iter == sync_items_.end()) | 551 if (iter == sync_items_.end()) |
450 return; | 552 return; |
553 sync_pb::AppListSpecifics::AppListItemType item_type = | |
554 iter->second->item_type; | |
451 DVLOG(2) << this << " <- SYNC DELETE: " << iter->second->ToString(); | 555 DVLOG(2) << this << " <- SYNC DELETE: " << iter->second->ToString(); |
452 delete iter->second; | 556 delete iter->second; |
453 sync_items_.erase(iter); | 557 sync_items_.erase(iter); |
454 model_->item_list()->DeleteItem(item_id); | 558 if (item_type != sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) |
559 model_->item_list()->DeleteItem(item_id); | |
455 } | 560 } |
456 | 561 |
457 std::string AppListSyncableService::SyncItem::ToString() const { | 562 std::string AppListSyncableService::SyncItem::ToString() const { |
458 return item_id.substr(0, 8) + " [" + item_ordinal.ToDebugString() + "]"; | 563 std::string res = item_id.substr(0, 8); |
564 if (item_type == sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { | |
565 res += " { RemoveDefault }"; | |
566 } else { | |
567 res += " { " + item_name + " }"; | |
568 res += " [" + item_ordinal.ToDebugString() + "]"; | |
569 } | |
570 return res; | |
459 } | 571 } |
460 | 572 |
461 } // namespace app_list | 573 } // namespace app_list |
OLD | NEW |