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

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

Powered by Google App Engine
This is Rietveld 408576698