Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(257)

Side by Side Diff: chrome/browser/ui/app_list/app_list_syncable_service.cc

Issue 118463002: Sync removal of Default apps. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 } 175 }
147 176
148 const AppListSyncableService::SyncItem* 177 const AppListSyncableService::SyncItem*
149 AppListSyncableService::GetSyncItem(const std::string& id) const { 178 AppListSyncableService::GetSyncItem(const std::string& id) const {
150 SyncItemMap::const_iterator iter = sync_items_.find(id); 179 SyncItemMap::const_iterator iter = sync_items_.find(id);
151 if (iter != sync_items_.end()) 180 if (iter != sync_items_.end())
152 return iter->second; 181 return iter->second;
153 return NULL; 182 return NULL;
154 } 183 }
155 184
156 void AppListSyncableService::AddExtensionAppItem(ExtensionAppItem* item) { 185 void AppListSyncableService::AddItem(AppListItem* item) {
157 SyncItem* sync_item = AddItem( 186 const std::string& item_id = item->id();
158 sync_pb::AppListSpecifics_AppListItemType_TYPE_APP, item); 187 if (item_id.empty()) {
159 if (!sync_item) 188 LOG(ERROR) << "AppListItem item with empty ID";
160 return; // Item already exists. 189 return;
161 sync_item->item_name = item->extension_name(); 190 }
191 sync_pb::AppListSpecifics::AppListItemType type;
192 const char* item_type = item->GetAppType();
193 if (item_type == ExtensionAppItem::kAppType) {
194 type = sync_pb::AppListSpecifics_AppListItemType_TYPE_APP;
195 } else if (item_type == AppListFolderItem::kAppType) {
196 type = sync_pb::AppListSpecifics_AppListItemType_TYPE_FOLDER;
197 } else {
198 LOG(ERROR) << "Unrecognized model type: " << item_type;
199 return;
200 }
201 SyncItem* sync_item = FindSyncItem(item_id);
202 if (sync_item) {
203 // If there is an existing, non-REMOVE_DEFAULT entry, update it.
204 if (sync_item->item_type !=
205 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) {
206 DCHECK_EQ(sync_item->item_type, type);
207 DVLOG(2) << this << ": AddItem already exists: " << sync_item->ToString();
208 UpdateItem(item);
209 return;
210 }
211 // If there is an existing REMOVE_DEFAULT_APP entry, and the app is
212 // installed as a Default app, uninstall the app instead of adding it.
213 if (type == sync_pb::AppListSpecifics_AppListItemType_TYPE_APP &&
214 AppIsDefault(extension_system_->extension_service(), item_id)) {
215 DVLOG(1) << this << ": AddItem: Uninstall: " << sync_item->ToString();
216 UninstallExtension(extension_system_->extension_service(), item_id);
217 return;
218 }
219 // Otherwise, we are adding the app as a non-default app (i.e. an app that
220 // was installed by Default and removed is getting installed explicitly by
221 // the user), so delete the REMOVE_DEFAULT_APP.
222 if (SyncStarted()) {
223 DVLOG(2) << this << " -> SYNC DELETE: " << sync_item->ToString();
224 SyncChange sync_change(FROM_HERE, SyncChange::ACTION_DELETE,
225 GetSyncDataFromSyncItem(sync_item));
226 sync_processor_->ProcessSyncChanges(
227 FROM_HERE, syncer::SyncChangeList(1, sync_change));
228 }
229 delete sync_item;
230 sync_items_.erase(item_id);
231 // Fall through. The REMOVE_DEFAULT_APP entry has been deleted, now an App
232 // entry can be added as usual.
233 }
234
235 sync_item = CreateSyncItem(item_id, type);
236 UpdateSyncItemFromAppItem(item, sync_item);
237 model_->item_list()->AddItem(item);
238 DVLOG(1) << this << ": AddItem: " << sync_item->ToString() << " Default: "
239 << AppIsDefault(extension_system_->extension_service(), item->id());
162 SendSyncChange(sync_item, SyncChange::ACTION_ADD); 240 SendSyncChange(sync_item, SyncChange::ACTION_ADD);
163 } 241 }
164 242
165 void AppListSyncableService::UpdateExtensionAppItem(ExtensionAppItem* item) { 243 void AppListSyncableService::UpdateItem(AppListItem* item) {
166 SyncItem* sync_item = FindSyncItem(item->id()); 244 SyncItem* sync_item = FindSyncItem(item->id());
167 if (!sync_item) { 245 if (!sync_item) {
168 LOG(ERROR) << "UpdateExtensionAppItem: no sync item: " << item->id(); 246 LOG(ERROR) << "UpdateItem: no sync item: " << item->id();
169 return; 247 return;
170 } 248 }
171 bool changed = UpdateSyncItemFromAppItem(item, sync_item); 249 bool changed = UpdateSyncItemFromAppItem(item, sync_item);
172 if (sync_item->item_name != item->extension_name()) {
173 sync_item->item_name = item->extension_name();
174 changed = true;
175 }
176 if (!changed) { 250 if (!changed) {
177 DVLOG(2) << this << " - Update: SYNC NO CHANGE: " << sync_item->ToString(); 251 DVLOG(2) << this << " - Update: SYNC NO CHANGE: " << sync_item->ToString();
178 return; 252 return;
179 } 253 }
180 SendSyncChange(sync_item, SyncChange::ACTION_UPDATE); 254 SendSyncChange(sync_item, SyncChange::ACTION_UPDATE);
181 } 255 }
182 256
183 void AppListSyncableService::RemoveItem(const std::string& id) { 257 void AppListSyncableService::RemoveItem(const std::string& id) {
184 DVLOG(2) << this << ": RemoveItem: " << id.substr(0, 8); 258 DVLOG(2) << this << ": RemoveItem: " << id.substr(0, 8);
185 SyncItemMap::iterator iter = sync_items_.find(id); 259 SyncItemMap::iterator iter = sync_items_.find(id);
186 if (iter == sync_items_.end()) 260 if (iter == sync_items_.end()) {
261 DVLOG(2) << this << " : No Sync Item.";
187 return; 262 return;
263 }
264 // Always delete the item from the model.
265 model_->item_list()->DeleteItem(id);
266
267 // Check for existing RemoveDefault sync item.
188 SyncItem* sync_item = iter->second; 268 SyncItem* sync_item = iter->second;
269 if (sync_item->item_type ==
270 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) {
271 // RemoveDefault item exists, just return.
272 DVLOG(2) << this << " : RemoveDefault Item exists.";
273 return;
274 }
275
276 if (AppIsDefault(extension_system_->extension_service(), id)) {
277 // This is a Default app; update the entry to a REMOVE_DEFAULT entry. This
278 // will overwrite any existing entry for the item.
279 DVLOG(2) << this << " -> SYNC UPDATE: REMOVE_DEFAULT: "
280 << sync_item->item_id;
281 sync_item->item_type = sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP;
282 SendSyncChange(sync_item, SyncChange::ACTION_UPDATE);
283 return;
284 }
285
286 // Existing entry is a normal entry, send a Delete sync change and remove
287 // the entry.
189 if (SyncStarted()) { 288 if (SyncStarted()) {
190 DVLOG(2) << this << " -> SYNC DELETE: " << sync_item->ToString(); 289 DVLOG(2) << this << " -> SYNC DELETE: " << sync_item->ToString();
191 SyncChange sync_change(FROM_HERE, SyncChange::ACTION_DELETE, 290 SyncChange sync_change(FROM_HERE, SyncChange::ACTION_DELETE,
192 GetSyncDataFromSyncItem(sync_item)); 291 GetSyncDataFromSyncItem(sync_item));
193 sync_processor_->ProcessSyncChanges( 292 sync_processor_->ProcessSyncChanges(
194 FROM_HERE, syncer::SyncChangeList(1, sync_change)); 293 FROM_HERE, syncer::SyncChangeList(1, sync_change));
195 } 294 }
196 delete sync_item; 295 delete sync_item;
197 sync_items_.erase(iter); 296 sync_items_.erase(iter);
198 model_->item_list()->DeleteItem(id);
199 } 297 }
200 298
201 // AppListSyncableService syncer::SyncableService 299 // AppListSyncableService syncer::SyncableService
202 300
203 syncer::SyncMergeResult AppListSyncableService::MergeDataAndStartSyncing( 301 syncer::SyncMergeResult AppListSyncableService::MergeDataAndStartSyncing(
204 syncer::ModelType type, 302 syncer::ModelType type,
205 const syncer::SyncDataList& initial_sync_data, 303 const syncer::SyncDataList& initial_sync_data,
206 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 304 scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
207 scoped_ptr<syncer::SyncErrorFactory> error_handler) { 305 scoped_ptr<syncer::SyncErrorFactory> error_handler) {
208 DCHECK(!sync_processor_.get()); 306 DCHECK(!sync_processor_.get());
(...skipping 13 matching lines...) Expand all
222 for (SyncItemMap::const_iterator iter = sync_items_.begin(); 320 for (SyncItemMap::const_iterator iter = sync_items_.begin();
223 iter != sync_items_.end(); ++iter) { 321 iter != sync_items_.end(); ++iter) {
224 unsynced_items.insert(iter->first); 322 unsynced_items.insert(iter->first);
225 } 323 }
226 324
227 // Create SyncItem entries for initial_sync_data. 325 // Create SyncItem entries for initial_sync_data.
228 size_t new_items = 0, updated_items = 0; 326 size_t new_items = 0, updated_items = 0;
229 for (syncer::SyncDataList::const_iterator iter = initial_sync_data.begin(); 327 for (syncer::SyncDataList::const_iterator iter = initial_sync_data.begin();
230 iter != initial_sync_data.end(); ++iter) { 328 iter != initial_sync_data.end(); ++iter) {
231 const syncer::SyncData& data = *iter; 329 const syncer::SyncData& data = *iter;
330 DVLOG(2) << this << " Initial Sync Item: "
331 << data.GetSpecifics().app_list().item_id()
332 << " Type: " << data.GetSpecifics().app_list().item_type();
232 DCHECK_EQ(syncer::APP_LIST, data.GetDataType()); 333 DCHECK_EQ(syncer::APP_LIST, data.GetDataType());
233 if (CreateOrUpdateSyncItem(data.GetSpecifics().app_list())) 334 if (ProcessSyncItem(data.GetSpecifics().app_list()))
234 ++new_items; 335 ++new_items;
235 else 336 else
236 ++updated_items; 337 ++updated_items;
237 unsynced_items.erase(data.GetSpecifics().app_list().item_id()); 338 unsynced_items.erase(data.GetSpecifics().app_list().item_id());
238 } 339 }
239 340
240 result.set_num_items_after_association(sync_items_.size()); 341 result.set_num_items_after_association(sync_items_.size());
241 result.set_num_items_added(new_items); 342 result.set_num_items_added(new_items);
242 result.set_num_items_deleted(0); 343 result.set_num_items_deleted(0);
243 result.set_num_items_modified(updated_items); 344 result.set_num_items_modified(updated_items);
(...skipping 16 matching lines...) Expand all
260 DCHECK_EQ(type, syncer::APP_LIST); 361 DCHECK_EQ(type, syncer::APP_LIST);
261 362
262 sync_processor_.reset(); 363 sync_processor_.reset();
263 sync_error_handler_.reset(); 364 sync_error_handler_.reset();
264 } 365 }
265 366
266 syncer::SyncDataList AppListSyncableService::GetAllSyncData( 367 syncer::SyncDataList AppListSyncableService::GetAllSyncData(
267 syncer::ModelType type) const { 368 syncer::ModelType type) const {
268 DCHECK_EQ(syncer::APP_LIST, type); 369 DCHECK_EQ(syncer::APP_LIST, type);
269 370
270 DVLOG(1) << this << "GetAllSyncData: " << sync_items_.size(); 371 DVLOG(1) << this << ": GetAllSyncData: " << sync_items_.size();
271 syncer::SyncDataList list; 372 syncer::SyncDataList list;
272 for (SyncItemMap::const_iterator iter = sync_items_.begin(); 373 for (SyncItemMap::const_iterator iter = sync_items_.begin();
273 iter != sync_items_.end(); ++iter) { 374 iter != sync_items_.end(); ++iter) {
274 DVLOG(2) << this << " -> SYNC: " << iter->second->ToString(); 375 DVLOG(2) << this << " -> SYNC: " << iter->second->ToString();
275 list.push_back(GetSyncDataFromSyncItem(iter->second)); 376 list.push_back(GetSyncDataFromSyncItem(iter->second));
276 } 377 }
277 return list; 378 return list;
278 } 379 }
279 380
280 syncer::SyncError AppListSyncableService::ProcessSyncChanges( 381 syncer::SyncError AppListSyncableService::ProcessSyncChanges(
281 const tracked_objects::Location& from_here, 382 const tracked_objects::Location& from_here,
282 const syncer::SyncChangeList& change_list) { 383 const syncer::SyncChangeList& change_list) {
283 if (!sync_processor_.get()) { 384 if (!sync_processor_.get()) {
284 return syncer::SyncError(FROM_HERE, 385 return syncer::SyncError(FROM_HERE,
285 syncer::SyncError::DATATYPE_ERROR, 386 syncer::SyncError::DATATYPE_ERROR,
286 "App List syncable service is not started.", 387 "App List syncable service is not started.",
287 syncer::APP_LIST); 388 syncer::APP_LIST);
288 } 389 }
289 390
290 // Process incoming changes first.
291 DVLOG(1) << this << ": ProcessSyncChanges: " << change_list.size(); 391 DVLOG(1) << this << ": ProcessSyncChanges: " << change_list.size();
292 for (syncer::SyncChangeList::const_iterator iter = change_list.begin(); 392 for (syncer::SyncChangeList::const_iterator iter = change_list.begin();
293 iter != change_list.end(); ++iter) { 393 iter != change_list.end(); ++iter) {
294 const SyncChange& change = *iter; 394 const SyncChange& change = *iter;
395 DVLOG(2) << this << " Change: "
396 << change.sync_data().GetSpecifics().app_list().item_id()
397 << " (" << change.change_type() << ")";
295 if (change.change_type() == SyncChange::ACTION_ADD || 398 if (change.change_type() == SyncChange::ACTION_ADD ||
296 change.change_type() == SyncChange::ACTION_UPDATE) { 399 change.change_type() == SyncChange::ACTION_UPDATE) {
297 CreateOrUpdateSyncItem(change.sync_data().GetSpecifics().app_list()); 400 ProcessSyncItem(change.sync_data().GetSpecifics().app_list());
298 } else if (change.change_type() == SyncChange::ACTION_DELETE) { 401 } else if (change.change_type() == SyncChange::ACTION_DELETE) {
299 DeleteSyncItem(change.sync_data().GetSpecifics().app_list()); 402 DeleteSyncItem(change.sync_data().GetSpecifics().app_list());
300 } else { 403 } else {
301 LOG(ERROR) << "Invalid sync change"; 404 LOG(ERROR) << "Invalid sync change";
302 } 405 }
303 } 406 }
304 return syncer::SyncError(); 407 return syncer::SyncError();
305 } 408 }
306 409
307 // AppListSyncableService private 410 // AppListSyncableService private
308 411
309 void AppListSyncableService::CreateAppItemFromSyncItem(SyncItem* sync_item) { 412 bool AppListSyncableService::ProcessSyncItem(
310 if (sync_item->item_type == sync_pb::AppListSpecifics::TYPE_APP) { 413 const sync_pb::AppListSpecifics& specifics) {
311 std::string extension_id = sync_item->item_id; 414 const std::string& item_id = specifics.item_id();
312 const ExtensionService* extension_service = 415 if (item_id.empty()) {
313 extensions::ExtensionSystem::Get(profile_)->extension_service(); 416 LOG(ERROR) << "AppList item with empty ID";
314 const extensions::Extension* app = 417 return false;
315 extension_service->GetInstalledExtension(extension_id);
316 DVLOG_IF(1, !app) << this << "No App for ID: " << extension_id;
317 bool is_platform_app = app ? app->is_platform_app() : false;
318 ExtensionAppItem* app_item = new ExtensionAppItem(
319 profile_,
320 sync_item,
321 extension_id,
322 sync_item->item_name,
323 gfx::ImageSkia(),
324 is_platform_app);
325 model_->item_list()->AddItem(app_item);
326 return;
327 } 418 }
328 if (sync_item->item_type == 419 SyncItem* sync_item = FindSyncItem(item_id);
420 if (sync_item) {
421 // If an item of the same type exists, update it.
422 if (sync_item->item_type == specifics.item_type()) {
423 UpdateSyncItemFromSync(specifics, sync_item);
424 ProcessExistingSyncItem(sync_item);
425 DVLOG(2) << this << " <- SYNC UPDATE: " << sync_item->ToString();
426 return false;
427 }
428 // Otherwise, one of the entries should be TYPE_REMOVE_DEFAULT_APP.
429 if (sync_item->item_type !=
430 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP &&
431 specifics.item_type() !=
432 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) {
433 LOG(ERROR) << "Synced item type: " << specifics.item_type()
434 << " != existing sync item type: " << sync_item->item_type
435 << " Deleting item from model!";
436 model_->item_list()->DeleteItem(item_id);
437 }
438 DVLOG(2) << this << " - ProcessSyncItem: Delete existing entry: "
439 << sync_item->ToString();
440 delete sync_item;
441 sync_items_.erase(item_id);
442 }
443
444 sync_item = CreateSyncItem(item_id, specifics.item_type());
445 UpdateSyncItemFromSync(specifics, sync_item);
446 ProcessNewSyncItem(sync_item);
447 DVLOG(2) << this << " <- SYNC ADD: " << sync_item->ToString();
448 return true;
449 }
450
451 void AppListSyncableService::ProcessNewSyncItem(SyncItem* sync_item) {
452 switch (sync_item->item_type) {
453 case sync_pb::AppListSpecifics::TYPE_APP: {
454 std::string extension_id = sync_item->item_id;
455 bool is_platform_app =
456 AppIsPlatformApp(extension_system_->extension_service(),
457 extension_id);
458 ExtensionAppItem* app_item = new ExtensionAppItem(
459 profile_,
460 sync_item,
461 extension_id,
462 sync_item->item_name,
463 gfx::ImageSkia(),
464 is_platform_app);
465 model_->item_list()->AddItem(app_item);
466 return;
467 }
468 case sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP: {
469 DVLOG(1) << this << ": Uninstall: " << sync_item->ToString();
470 UninstallExtension(extension_system_->extension_service(),
471 sync_item->item_id);
472 return;
473 }
474 case sync_pb::AppListSpecifics::TYPE_FOLDER: {
475 // TODO(stevenjb): Implement
476 LOG(WARNING) << "TYPE_FOLDER not supported";
477 return;
478 }
479 case sync_pb::AppListSpecifics::TYPE_URL: {
480 // TODO(stevenjb): Implement
481 LOG(WARNING) << "TYPE_URL not supported";
482 return;
483 }
484 }
485 NOTREACHED() << "Unrecoginized sync item type: " << sync_item->ToString();
486 }
487
488 void AppListSyncableService::ProcessExistingSyncItem(SyncItem* sync_item) {
489 if (sync_item->item_type !=
329 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { 490 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) {
330 // TODO(stevenjb): Implement 491 AppListItem* item = model_->item_list()->FindItem(sync_item->item_id);
492 if (item && !item->position().Equals(sync_item->item_ordinal))
493 model_->item_list()->SetItemPosition(item, sync_item->item_ordinal);
331 } 494 }
332 if (sync_item->item_type == sync_pb::AppListSpecifics::TYPE_FOLDER) {
333 // TODO(stevenjb): Implement
334 }
335 if (sync_item->item_type == sync_pb::AppListSpecifics::TYPE_URL) {
336 // TODO(stevenjb): Implement
337 }
338 LOG(ERROR) << "Unsupported type: " << sync_item->item_type;
339 } 495 }
340 496
341 bool AppListSyncableService::SyncStarted() { 497 bool AppListSyncableService::SyncStarted() {
342 if (sync_processor_.get()) 498 if (sync_processor_.get())
343 return true; 499 return true;
344 if (flare_.is_null()) { 500 if (flare_.is_null()) {
345 DVLOG(2) << this << ": SyncStarted: Flare."; 501 DVLOG(2) << this << ": SyncStarted: Flare.";
346 flare_ = sync_start_util::GetFlareForSyncableService(profile_->GetPath()); 502 flare_ = sync_start_util::GetFlareForSyncableService(profile_->GetPath());
347 flare_.Run(syncer::APP_LIST); 503 flare_.Run(syncer::APP_LIST);
348 } 504 }
349 return false; 505 return false;
350 } 506 }
351 507
352 AppListSyncableService::SyncItem* AppListSyncableService::AddItem(
353 sync_pb::AppListSpecifics::AppListItemType type,
354 AppListItem* app_item) {
355 const std::string& item_id = app_item->id();
356 if (item_id.empty()) {
357 LOG(ERROR) << "AppListItem item with empty ID";
358 return NULL;
359 }
360 bool new_item = false;
361 SyncItem* sync_item = FindOrCreateSyncItem(item_id, type, &new_item);
362 if (!new_item) {
363 DVLOG(2) << this << ": AddItem already exists: " << sync_item->ToString();
364 return NULL; // Item already exists.
365 }
366 UpdateSyncItemFromAppItem(app_item, sync_item);
367 DVLOG(1) << this << ": AddItem: " << sync_item->ToString();
368 model_->item_list()->AddItem(app_item);
369 return sync_item;
370 }
371
372 void AppListSyncableService::SendSyncChange( 508 void AppListSyncableService::SendSyncChange(
373 SyncItem* sync_item, 509 SyncItem* sync_item,
374 SyncChange::SyncChangeType sync_change_type) { 510 SyncChange::SyncChangeType sync_change_type) {
375 if (!SyncStarted()) { 511 if (!SyncStarted()) {
376 DVLOG(2) << this << " - SendSyncChange: SYNC NOT STARTED: " 512 DVLOG(2) << this << " - SendSyncChange: SYNC NOT STARTED: "
377 << sync_item->ToString(); 513 << sync_item->ToString();
378 return; 514 return;
379 } 515 }
380 if (sync_change_type == SyncChange::ACTION_ADD) 516 if (sync_change_type == SyncChange::ACTION_ADD)
381 DVLOG(2) << this << " -> SYNC ADD: " << sync_item->ToString(); 517 DVLOG(2) << this << " -> SYNC ADD: " << sync_item->ToString();
382 else 518 else
383 DVLOG(2) << this << " -> SYNC UPDATE: " << sync_item->ToString(); 519 DVLOG(2) << this << " -> SYNC UPDATE: " << sync_item->ToString();
384 SyncChange sync_change(FROM_HERE, sync_change_type, 520 SyncChange sync_change(FROM_HERE, sync_change_type,
385 GetSyncDataFromSyncItem(sync_item)); 521 GetSyncDataFromSyncItem(sync_item));
386 sync_processor_->ProcessSyncChanges( 522 sync_processor_->ProcessSyncChanges(
387 FROM_HERE, syncer::SyncChangeList(1, sync_change)); 523 FROM_HERE, syncer::SyncChangeList(1, sync_change));
388 } 524 }
389 525
390 AppListSyncableService::SyncItem* 526 AppListSyncableService::SyncItem*
391 AppListSyncableService::FindSyncItem(const std::string& item_id) { 527 AppListSyncableService::FindSyncItem(const std::string& item_id) {
392 SyncItemMap::iterator iter = sync_items_.find(item_id); 528 SyncItemMap::iterator iter = sync_items_.find(item_id);
393 if (iter == sync_items_.end()) 529 if (iter == sync_items_.end())
394 return NULL; 530 return NULL;
395 return iter->second; 531 return iter->second;
396 } 532 }
397 533
398 AppListSyncableService::SyncItem* AppListSyncableService::FindOrCreateSyncItem( 534 AppListSyncableService::SyncItem*
535 AppListSyncableService::CreateSyncItem(
399 const std::string& item_id, 536 const std::string& item_id,
400 sync_pb::AppListSpecifics::AppListItemType type, 537 sync_pb::AppListSpecifics::AppListItemType item_type) {
401 bool* new_item) { 538 DCHECK(!ContainsKey(sync_items_, item_id));
402 SyncItem* item = FindSyncItem(item_id); 539 SyncItem* sync_item = new SyncItem(item_id, item_type);
403 if (item) { 540 sync_items_[item_id] = sync_item;
404 DCHECK(type == item->item_type); 541 return sync_item;
405 *new_item = false;
406 return item;
407 }
408
409 item = new SyncItem(item_id, type);
410 sync_items_[item_id] = item;
411 *new_item = true;
412 return item;
413 }
414
415 bool AppListSyncableService::CreateOrUpdateSyncItem(
416 const sync_pb::AppListSpecifics& specifics) {
417 const std::string& item_id = specifics.item_id();
418 if (item_id.empty()) {
419 LOG(ERROR) << "CreateOrUpdate AppList item with empty ID";
420 return false;
421 }
422 bool new_item = false;
423 SyncItem* sync_item =
424 FindOrCreateSyncItem(item_id, specifics.item_type(), &new_item);
425 DVLOG(2) << this << "CreateOrUpdateSyncItem: " << sync_item->ToString()
426 << " New: " << new_item << " Pos: " << specifics.item_ordinal();
427 UpdateSyncItemFromSync(specifics, sync_item);
428 // Update existing item in model
429 AppListItem* item = model_->item_list()->FindItem(sync_item->item_id);
430 if (item && !item->position().Equals(sync_item->item_ordinal))
431 model_->item_list()->SetItemPosition(item, sync_item->item_ordinal);
432 if (new_item) {
433 CreateAppItemFromSyncItem(sync_item);
434 DVLOG(2) << this << " <- SYNC ADD: " << sync_item->ToString();
435 } else {
436 DVLOG(2) << this << " <- SYNC UPDATE: " << sync_item->ToString();
437 }
438 return new_item;
439 } 542 }
440 543
441 void AppListSyncableService::DeleteSyncItem( 544 void AppListSyncableService::DeleteSyncItem(
442 const sync_pb::AppListSpecifics& specifics) { 545 const sync_pb::AppListSpecifics& specifics) {
443 const std::string& item_id = specifics.item_id(); 546 const std::string& item_id = specifics.item_id();
444 if (item_id.empty()) { 547 if (item_id.empty()) {
445 LOG(ERROR) << "Delete AppList item with empty ID"; 548 LOG(ERROR) << "Delete AppList item with empty ID";
446 return; 549 return;
447 } 550 }
448 DVLOG(2) << this << "DeleteSyncItem: " << item_id.substr(0, 8); 551 DVLOG(2) << this << ": DeleteSyncItem: " << item_id.substr(0, 8);
449 SyncItemMap::iterator iter = sync_items_.find(item_id); 552 SyncItemMap::iterator iter = sync_items_.find(item_id);
450 if (iter == sync_items_.end()) 553 if (iter == sync_items_.end())
451 return; 554 return;
555 sync_pb::AppListSpecifics::AppListItemType item_type =
556 iter->second->item_type;
452 DVLOG(2) << this << " <- SYNC DELETE: " << iter->second->ToString(); 557 DVLOG(2) << this << " <- SYNC DELETE: " << iter->second->ToString();
453 delete iter->second; 558 delete iter->second;
454 sync_items_.erase(iter); 559 sync_items_.erase(iter);
455 model_->item_list()->DeleteItem(item_id); 560 if (item_type != sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP)
561 model_->item_list()->DeleteItem(item_id);
456 } 562 }
457 563
458 std::string AppListSyncableService::SyncItem::ToString() const { 564 std::string AppListSyncableService::SyncItem::ToString() const {
459 return item_id.substr(0, 8) + " [" + item_ordinal.ToDebugString() + "]"; 565 std::string res = item_id.substr(0, 8);
566 if (item_type == sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) {
567 res += " { RemoveDefault }";
568 } else {
569 res += " { " + item_name + " }";
570 res += " [" + item_ordinal.ToDebugString() + "]";
571 }
572 return res;
460 } 573 }
461 574
462 } // namespace app_list 575 } // namespace app_list
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698