Chromium Code Reviews| 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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| 11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 14 #include "build/build_config.h" | 14 #include "build/build_config.h" |
| 15 #include "chrome/browser/apps/drive/drive_app_provider.h" | 15 #include "chrome/browser/apps/drive/drive_app_provider.h" |
| 16 #include "chrome/browser/extensions/extension_service.h" | 16 #include "chrome/browser/extensions/extension_service.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/ui/app_list/app_list_service.h" | 18 #include "chrome/browser/ui/app_list/app_list_service.h" |
| 19 #include "chrome/browser/ui/app_list/extension_app_item.h" | 19 #include "chrome/browser/ui/app_list/extension_app_item.h" |
| 20 #include "chrome/browser/ui/app_list/extension_app_model_builder.h" | 20 #include "chrome/browser/ui/app_list/extension_app_model_builder.h" |
| 21 #include "chrome/common/chrome_switches.h" | 21 #include "chrome/common/chrome_switches.h" |
| 22 #include "chrome/common/extensions/extension_constants.h" | 22 #include "chrome/common/extensions/extension_constants.h" |
| 23 #include "chrome/common/pref_names.h" | |
| 23 #include "chrome/grit/generated_resources.h" | 24 #include "chrome/grit/generated_resources.h" |
| 25 #include "components/pref_registry/pref_registry_syncable.h" | |
| 24 #include "components/sync/model/sync_change_processor.h" | 26 #include "components/sync/model/sync_change_processor.h" |
| 25 #include "components/sync/model/sync_data.h" | 27 #include "components/sync/model/sync_data.h" |
| 26 #include "components/sync/model/sync_merge_result.h" | 28 #include "components/sync/model/sync_merge_result.h" |
| 27 #include "components/sync/protocol/sync.pb.h" | 29 #include "components/sync/protocol/sync.pb.h" |
| 28 #include "extensions/browser/extension_prefs.h" | 30 #include "extensions/browser/extension_prefs.h" |
| 29 #include "extensions/browser/extension_system.h" | 31 #include "extensions/browser/extension_system.h" |
| 30 #include "extensions/browser/uninstall_reason.h" | 32 #include "extensions/browser/uninstall_reason.h" |
| 31 #include "extensions/common/constants.h" | 33 #include "extensions/common/constants.h" |
| 32 #include "ui/app_list/app_list_folder_item.h" | 34 #include "ui/app_list/app_list_folder_item.h" |
| 33 #include "ui/app_list/app_list_item.h" | 35 #include "ui/app_list/app_list_item.h" |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 46 #endif | 48 #endif |
| 47 | 49 |
| 48 using syncer::SyncChange; | 50 using syncer::SyncChange; |
| 49 | 51 |
| 50 namespace app_list { | 52 namespace app_list { |
| 51 | 53 |
| 52 namespace { | 54 namespace { |
| 53 | 55 |
| 54 const char kOemFolderId[] = "ddb1da55-d478-4243-8642-56d3041f0263"; | 56 const char kOemFolderId[] = "ddb1da55-d478-4243-8642-56d3041f0263"; |
| 55 | 57 |
| 58 const char kNameKey[] = "name"; | |
| 59 const char kParentIdKey[] = "parent_id"; | |
| 60 const char kPositionKey[] = "position"; | |
| 61 const char kPinPositionKey[] = "pin_position"; | |
| 62 const char kTypeKey[] = "type"; | |
| 63 | |
| 56 // Prefix for a sync id of a Drive app. Drive app ids are in a different | 64 // Prefix for a sync id of a Drive app. Drive app ids are in a different |
| 57 // format and have to be used because a Drive app could have only an URL | 65 // format and have to be used because a Drive app could have only an URL |
| 58 // without a matching Chrome app. To differentiate the Drive app id from | 66 // without a matching Chrome app. To differentiate the Drive app id from |
| 59 // Chrome app ids, this prefix will be added to create the sync item id | 67 // Chrome app ids, this prefix will be added to create the sync item id |
| 60 // for a Drive app item. | 68 // for a Drive app item. |
| 61 const char kDriveAppSyncIdPrefix[] = "drive-app-"; | 69 const char kDriveAppSyncIdPrefix[] = "drive-app-"; |
| 62 | 70 |
| 63 void UpdateSyncItemFromSync(const sync_pb::AppListSpecifics& specifics, | 71 void UpdateSyncItemFromSync(const sync_pb::AppListSpecifics& specifics, |
| 64 AppListSyncableService::SyncItem* item) { | 72 AppListSyncableService::SyncItem* item) { |
| 65 DCHECK_EQ(item->item_id, specifics.item_id()); | 73 DCHECK_EQ(item->item_id, specifics.item_id()); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 std::string GetDriveAppSyncId(const std::string& drive_app_id) { | 174 std::string GetDriveAppSyncId(const std::string& drive_app_id) { |
| 167 return kDriveAppSyncIdPrefix + drive_app_id; | 175 return kDriveAppSyncIdPrefix + drive_app_id; |
| 168 } | 176 } |
| 169 | 177 |
| 170 std::string GetDriveAppIdFromSyncId(const std::string& sync_id) { | 178 std::string GetDriveAppIdFromSyncId(const std::string& sync_id) { |
| 171 if (!IsDriveAppSyncId(sync_id)) | 179 if (!IsDriveAppSyncId(sync_id)) |
| 172 return std::string(); | 180 return std::string(); |
| 173 return sync_id.substr(strlen(kDriveAppSyncIdPrefix)); | 181 return sync_id.substr(strlen(kDriveAppSyncIdPrefix)); |
| 174 } | 182 } |
| 175 | 183 |
| 184 void RemoveSyncItemFromLocalStorage(Profile* profile, | |
| 185 const std::string& item_id) { | |
| 186 DictionaryPrefUpdate(profile->GetPrefs(), prefs::kAppListLocalState)-> | |
| 187 Remove(item_id, nullptr); | |
| 188 } | |
| 189 | |
| 190 void UpdateSyncItemInLocalStorage( | |
| 191 Profile* profile, | |
| 192 const AppListSyncableService::SyncItem* sync_item) { | |
| 193 DictionaryPrefUpdate pref_update(profile->GetPrefs(), | |
| 194 prefs::kAppListLocalState); | |
| 195 base::DictionaryValue* dict_item = nullptr; | |
| 196 if (!pref_update->GetDictionaryWithoutPathExpansion(sync_item->item_id, | |
| 197 &dict_item)) { | |
| 198 dict_item = new base::DictionaryValue(); | |
| 199 pref_update->SetWithoutPathExpansion(sync_item->item_id, dict_item); | |
| 200 } | |
| 201 | |
| 202 dict_item->SetString(kNameKey, sync_item->item_name); | |
| 203 dict_item->SetString(kParentIdKey, sync_item->parent_id); | |
| 204 dict_item->SetString(kPositionKey,sync_item->item_ordinal.IsValid() ? | |
| 205 sync_item->item_ordinal.ToInternalValue() : std::string()); | |
| 206 dict_item->SetString(kPinPositionKey, sync_item->item_pin_ordinal.IsValid() ? | |
| 207 sync_item->item_pin_ordinal.ToInternalValue() : std::string()); | |
| 208 dict_item->SetInteger(kTypeKey, static_cast<int>(sync_item->item_type)); | |
| 209 } | |
| 210 | |
| 176 } // namespace | 211 } // namespace |
| 177 | 212 |
| 178 // AppListSyncableService::SyncItem | 213 // AppListSyncableService::SyncItem |
| 179 | 214 |
| 180 AppListSyncableService::SyncItem::SyncItem( | 215 AppListSyncableService::SyncItem::SyncItem( |
| 181 const std::string& id, | 216 const std::string& id, |
| 182 sync_pb::AppListSpecifics::AppListItemType type) | 217 sync_pb::AppListSpecifics::AppListItemType type) |
| 183 : item_id(id), | 218 : item_id(id), |
| 184 item_type(type) { | 219 item_type(type) { |
| 185 } | 220 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 } | 282 } |
| 248 | 283 |
| 249 AppListSyncableService* owner_; | 284 AppListSyncableService* owner_; |
| 250 AppListItem* adding_item_; // Unowned pointer to item being added. | 285 AppListItem* adding_item_; // Unowned pointer to item being added. |
| 251 | 286 |
| 252 DISALLOW_COPY_AND_ASSIGN(ModelObserver); | 287 DISALLOW_COPY_AND_ASSIGN(ModelObserver); |
| 253 }; | 288 }; |
| 254 | 289 |
| 255 // AppListSyncableService | 290 // AppListSyncableService |
| 256 | 291 |
| 292 // static | |
| 293 void AppListSyncableService::RegisterProfilePrefs( | |
| 294 user_prefs::PrefRegistrySyncable* registry) { | |
| 295 registry->RegisterDictionaryPref(prefs::kAppListLocalState); | |
| 296 } | |
| 297 | |
| 257 AppListSyncableService::AppListSyncableService( | 298 AppListSyncableService::AppListSyncableService( |
| 258 Profile* profile, | 299 Profile* profile, |
| 259 extensions::ExtensionSystem* extension_system) | 300 extensions::ExtensionSystem* extension_system) |
| 260 : profile_(profile), | 301 : profile_(profile), |
| 261 extension_system_(extension_system), | 302 extension_system_(extension_system), |
| 262 model_(new AppListModel), | 303 model_(new AppListModel), |
| 263 initial_sync_data_processed_(false), | 304 initial_sync_data_processed_(false), |
| 264 first_app_list_sync_(true) { | 305 first_app_list_sync_(true) { |
| 265 if (!extension_system) { | 306 if (!extension_system) { |
| 266 LOG(ERROR) << "AppListSyncableService created with no ExtensionSystem"; | 307 LOG(ERROR) << "AppListSyncableService created with no ExtensionSystem"; |
| 267 return; | 308 return; |
| 268 } | 309 } |
| 269 | 310 |
| 270 oem_folder_name_ = | 311 oem_folder_name_ = |
| 271 l10n_util::GetStringUTF8(IDS_APP_LIST_OEM_DEFAULT_FOLDER_NAME); | 312 l10n_util::GetStringUTF8(IDS_APP_LIST_OEM_DEFAULT_FOLDER_NAME); |
| 313 | |
| 314 InitFromLocalStorage(); | |
| 272 } | 315 } |
| 273 | 316 |
| 274 AppListSyncableService::~AppListSyncableService() { | 317 AppListSyncableService::~AppListSyncableService() { |
| 275 // Remove observers. | 318 // Remove observers. |
| 276 model_observer_.reset(); | 319 model_observer_.reset(); |
| 277 } | 320 } |
| 278 | 321 |
| 322 void AppListSyncableService::InitFromLocalStorage() { | |
| 323 if (switches::IsFolderUIEnabled()) | |
| 324 model_->SetFoldersEnabled(true); | |
|
stevenjb
2016/10/20 17:04:46
We will need to test this, but in theory with loca
khmel
2016/10/20 18:00:06
Right, we can move it into CTOR and drop settings
| |
| 325 // Restore initial state from local storage. | |
| 326 const base::DictionaryValue* local_items = profile_->GetPrefs()-> | |
| 327 GetDictionary(prefs::kAppListLocalState); | |
| 328 DCHECK(local_items); | |
| 329 | |
| 330 for (base::DictionaryValue::Iterator item(*local_items); !item.IsAtEnd(); | |
| 331 item.Advance()) { | |
| 332 const base::DictionaryValue* dict_item; | |
| 333 if (!item.value().GetAsDictionary(&dict_item)) { | |
| 334 LOG(ERROR) << "Dictionary not found for " << item.key() + "."; | |
| 335 continue; | |
| 336 } | |
| 337 | |
| 338 int type; | |
| 339 if (!dict_item->GetInteger(kTypeKey, &type)) { | |
| 340 LOG(ERROR) << "Item type is not set in local storage for " << item.key() | |
| 341 << "."; | |
| 342 continue; | |
| 343 } | |
| 344 | |
| 345 SyncItem* sync_item = CreateSyncItem(item.key(), | |
| 346 static_cast<sync_pb::AppListSpecifics::AppListItemType>(type)); | |
| 347 | |
| 348 dict_item->GetString(kNameKey, &sync_item->item_name); | |
| 349 dict_item->GetString(kParentIdKey, &sync_item->parent_id); | |
| 350 std::string position; | |
| 351 std::string pin_position; | |
| 352 dict_item->GetString(kPositionKey, &position); | |
| 353 dict_item->GetString(kPinPositionKey, &pin_position); | |
| 354 if (!position.empty()) | |
| 355 sync_item->item_ordinal = syncer::StringOrdinal(position); | |
| 356 if (!pin_position.empty()) | |
| 357 sync_item->item_pin_ordinal = syncer::StringOrdinal(pin_position); | |
| 358 ProcessNewSyncItem(sync_item); | |
| 359 } | |
| 360 } | |
| 361 | |
| 279 void AppListSyncableService::BuildModel() { | 362 void AppListSyncableService::BuildModel() { |
| 280 // TODO(calamity): make this a DCHECK after a dev channel release. | 363 // TODO(calamity): make this a DCHECK after a dev channel release. |
| 281 CHECK(extension_system_->extension_service() && | 364 CHECK(extension_system_->extension_service() && |
| 282 extension_system_->extension_service()->is_ready()); | 365 extension_system_->extension_service()->is_ready()); |
| 283 AppListControllerDelegate* controller = NULL; | 366 AppListControllerDelegate* controller = NULL; |
| 284 AppListService* service = AppListService::Get(); | 367 AppListService* service = AppListService::Get(); |
| 285 if (service) | 368 if (service) |
| 286 controller = service->GetControllerDelegate(); | 369 controller = service->GetControllerDelegate(); |
| 287 apps_builder_.reset(new ExtensionAppModelBuilder(controller)); | 370 apps_builder_.reset(new ExtensionAppModelBuilder(controller)); |
| 288 #if defined(OS_CHROMEOS) | 371 #if defined(OS_CHROMEOS) |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 302 VLOG(1) << this << ": AppListSyncableService: InitializeWithProfile."; | 385 VLOG(1) << this << ": AppListSyncableService: InitializeWithProfile."; |
| 303 apps_builder_->InitializeWithProfile(profile_, model_.get()); | 386 apps_builder_->InitializeWithProfile(profile_, model_.get()); |
| 304 #if defined(OS_CHROMEOS) | 387 #if defined(OS_CHROMEOS) |
| 305 if (arc_apps_builder_.get()) | 388 if (arc_apps_builder_.get()) |
| 306 arc_apps_builder_->InitializeWithProfile(profile_, model_.get()); | 389 arc_apps_builder_->InitializeWithProfile(profile_, model_.get()); |
| 307 #endif | 390 #endif |
| 308 } | 391 } |
| 309 | 392 |
| 310 if (app_list::switches::IsDriveAppsInAppListEnabled()) | 393 if (app_list::switches::IsDriveAppsInAppListEnabled()) |
| 311 drive_app_provider_.reset(new DriveAppProvider(profile_, this)); | 394 drive_app_provider_.reset(new DriveAppProvider(profile_, this)); |
| 395 | |
| 396 ResolveFolderPositions(); | |
| 397 | |
| 398 // Start observing app list model changes. | |
| 399 model_observer_.reset(new ModelObserver(this)); | |
|
stevenjb
2016/10/20 17:04:46
If we start observing the model here, don't we nee
khmel
2016/10/20 18:00:06
With local storage support yes, we also need to re
stevenjb
2016/10/21 20:03:10
Is there any harm in requiring the model to be bui
khmel
2016/10/24 17:28:39
There is no harm to have model built before pin ac
| |
| 312 } | 400 } |
| 313 | 401 |
| 314 void AppListSyncableService::AddObserverAndStart(Observer* observer) { | 402 void AppListSyncableService::AddObserverAndStart(Observer* observer) { |
| 315 observer_list_.AddObserver(observer); | 403 observer_list_.AddObserver(observer); |
| 316 SyncStarted(); | 404 SyncStarted(); |
| 317 } | 405 } |
| 318 | 406 |
| 319 void AppListSyncableService::RemoveObserver(Observer* observer) { | 407 void AppListSyncableService::RemoveObserver(Observer* observer) { |
| 320 observer_list_.RemoveObserver(observer); | 408 observer_list_.RemoveObserver(observer); |
| 321 } | 409 } |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 438 } | 526 } |
| 439 | 527 |
| 440 AppListSyncableService::SyncItem* | 528 AppListSyncableService::SyncItem* |
| 441 AppListSyncableService::CreateSyncItemFromAppItem(AppListItem* app_item) { | 529 AppListSyncableService::CreateSyncItemFromAppItem(AppListItem* app_item) { |
| 442 sync_pb::AppListSpecifics::AppListItemType type; | 530 sync_pb::AppListSpecifics::AppListItemType type; |
| 443 if (!GetAppListItemType(app_item, &type)) | 531 if (!GetAppListItemType(app_item, &type)) |
| 444 return NULL; | 532 return NULL; |
| 445 VLOG(2) << this << " CreateSyncItemFromAppItem:" << app_item->ToDebugString(); | 533 VLOG(2) << this << " CreateSyncItemFromAppItem:" << app_item->ToDebugString(); |
| 446 SyncItem* sync_item = CreateSyncItem(app_item->id(), type); | 534 SyncItem* sync_item = CreateSyncItem(app_item->id(), type); |
| 447 UpdateSyncItemFromAppItem(app_item, sync_item); | 535 UpdateSyncItemFromAppItem(app_item, sync_item); |
| 536 UpdateSyncItemInLocalStorage(profile_, sync_item); | |
| 448 SendSyncChange(sync_item, SyncChange::ACTION_ADD); | 537 SendSyncChange(sync_item, SyncChange::ACTION_ADD); |
| 449 return sync_item; | 538 return sync_item; |
| 450 } | 539 } |
| 451 | 540 |
| 452 syncer::StringOrdinal AppListSyncableService::GetPinPosition( | 541 syncer::StringOrdinal AppListSyncableService::GetPinPosition( |
| 453 const std::string& app_id) { | 542 const std::string& app_id) { |
| 454 SyncItem* sync_item = FindSyncItem(app_id); | 543 SyncItem* sync_item = FindSyncItem(app_id); |
| 455 if (!sync_item) | 544 if (!sync_item) |
| 456 return syncer::StringOrdinal(); | 545 return syncer::StringOrdinal(); |
| 457 return sync_item->item_pin_ordinal; | 546 return sync_item->item_pin_ordinal; |
| 458 } | 547 } |
| 459 | 548 |
| 460 void AppListSyncableService::SetPinPosition( | 549 void AppListSyncableService::SetPinPosition( |
| 461 const std::string& app_id, | 550 const std::string& app_id, |
| 462 const syncer::StringOrdinal& item_pin_ordinal) { | 551 const syncer::StringOrdinal& item_pin_ordinal) { |
| 463 SyncItem* sync_item = FindSyncItem(app_id); | 552 SyncItem* sync_item = FindSyncItem(app_id); |
| 464 SyncChange::SyncChangeType sync_change_type; | 553 SyncChange::SyncChangeType sync_change_type; |
| 465 if (sync_item) { | 554 if (sync_item) { |
| 466 sync_change_type = SyncChange::ACTION_UPDATE; | 555 sync_change_type = SyncChange::ACTION_UPDATE; |
| 467 } else { | 556 } else { |
| 468 sync_item = CreateSyncItem(app_id, sync_pb::AppListSpecifics::TYPE_APP); | 557 sync_item = CreateSyncItem(app_id, sync_pb::AppListSpecifics::TYPE_APP); |
| 469 sync_change_type = SyncChange::ACTION_ADD; | 558 sync_change_type = SyncChange::ACTION_ADD; |
| 470 } | 559 } |
| 471 | 560 |
| 472 sync_item->item_pin_ordinal = item_pin_ordinal; | 561 sync_item->item_pin_ordinal = item_pin_ordinal; |
| 562 UpdateSyncItemInLocalStorage(profile_, sync_item); | |
| 473 SendSyncChange(sync_item, sync_change_type); | 563 SendSyncChange(sync_item, sync_change_type); |
| 474 } | 564 } |
| 475 | 565 |
| 476 void AppListSyncableService::AddOrUpdateFromSyncItem(AppListItem* app_item) { | 566 void AppListSyncableService::AddOrUpdateFromSyncItem(AppListItem* app_item) { |
| 477 // Do not create a sync item for the OEM folder here, do that in | 567 // Do not create a sync item for the OEM folder here, do that in |
| 478 // ResolveFolderPositions once the position has been resolved. | 568 // ResolveFolderPositions once the position has been resolved. |
| 479 if (app_item->id() == kOemFolderId) | 569 if (app_item->id() == kOemFolderId) |
| 480 return; | 570 return; |
| 481 | 571 |
| 482 SyncItem* sync_item = FindSyncItem(app_item->id()); | 572 SyncItem* sync_item = FindSyncItem(app_item->id()); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 515 LOG(ERROR) << "DeleteSyncItem: no sync item: " << item_id; | 605 LOG(ERROR) << "DeleteSyncItem: no sync item: " << item_id; |
| 516 return; | 606 return; |
| 517 } | 607 } |
| 518 if (SyncStarted()) { | 608 if (SyncStarted()) { |
| 519 VLOG(2) << this << " -> SYNC DELETE: " << sync_item->ToString(); | 609 VLOG(2) << this << " -> SYNC DELETE: " << sync_item->ToString(); |
| 520 SyncChange sync_change(FROM_HERE, SyncChange::ACTION_DELETE, | 610 SyncChange sync_change(FROM_HERE, SyncChange::ACTION_DELETE, |
| 521 GetSyncDataFromSyncItem(sync_item)); | 611 GetSyncDataFromSyncItem(sync_item)); |
| 522 sync_processor_->ProcessSyncChanges( | 612 sync_processor_->ProcessSyncChanges( |
| 523 FROM_HERE, syncer::SyncChangeList(1, sync_change)); | 613 FROM_HERE, syncer::SyncChangeList(1, sync_change)); |
| 524 } | 614 } |
| 615 RemoveSyncItemFromLocalStorage(profile_, item_id); | |
| 525 sync_items_.erase(item_id); | 616 sync_items_.erase(item_id); |
| 526 } | 617 } |
| 527 | 618 |
| 528 void AppListSyncableService::UpdateSyncItem(AppListItem* app_item) { | 619 void AppListSyncableService::UpdateSyncItem(AppListItem* app_item) { |
| 529 SyncItem* sync_item = FindSyncItem(app_item->id()); | 620 SyncItem* sync_item = FindSyncItem(app_item->id()); |
| 530 if (!sync_item) { | 621 if (!sync_item) { |
| 531 LOG(ERROR) << "UpdateItem: no sync item: " << app_item->id(); | 622 LOG(ERROR) << "UpdateItem: no sync item: " << app_item->id(); |
| 532 return; | 623 return; |
| 533 } | 624 } |
| 534 bool changed = UpdateSyncItemFromAppItem(app_item, sync_item); | 625 bool changed = UpdateSyncItemFromAppItem(app_item, sync_item); |
| 535 if (!changed) { | 626 if (!changed) { |
| 536 DVLOG(2) << this << " - Update: SYNC NO CHANGE: " << sync_item->ToString(); | 627 DVLOG(2) << this << " - Update: SYNC NO CHANGE: " << sync_item->ToString(); |
| 537 return; | 628 return; |
| 538 } | 629 } |
| 630 UpdateSyncItemInLocalStorage(profile_, sync_item); | |
| 539 SendSyncChange(sync_item, SyncChange::ACTION_UPDATE); | 631 SendSyncChange(sync_item, SyncChange::ACTION_UPDATE); |
| 540 } | 632 } |
| 541 | 633 |
| 542 void AppListSyncableService::RemoveItem(const std::string& id) { | 634 void AppListSyncableService::RemoveItem(const std::string& id) { |
| 543 RemoveSyncItem(id); | 635 RemoveSyncItem(id); |
| 544 model_->DeleteItem(id); | 636 model_->DeleteItem(id); |
| 545 PruneEmptySyncFolders(); | 637 PruneEmptySyncFolders(); |
| 546 } | 638 } |
| 547 | 639 |
| 548 void AppListSyncableService::RemoveUninstalledItem(const std::string& id) { | 640 void AppListSyncableService::RemoveUninstalledItem(const std::string& id) { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 579 return; | 671 return; |
| 580 } | 672 } |
| 581 | 673 |
| 582 if (type == sync_pb::AppListSpecifics::TYPE_APP && | 674 if (type == sync_pb::AppListSpecifics::TYPE_APP && |
| 583 AppIsDefault(extension_system_->extension_service(), id)) { | 675 AppIsDefault(extension_system_->extension_service(), id)) { |
| 584 // This is a Default app; update the entry to a REMOVE_DEFAULT entry. This | 676 // This is a Default app; update the entry to a REMOVE_DEFAULT entry. This |
| 585 // will overwrite any existing entry for the item. | 677 // will overwrite any existing entry for the item. |
| 586 VLOG(2) << this << " -> SYNC UPDATE: REMOVE_DEFAULT: " | 678 VLOG(2) << this << " -> SYNC UPDATE: REMOVE_DEFAULT: " |
| 587 << sync_item->item_id; | 679 << sync_item->item_id; |
| 588 sync_item->item_type = sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP; | 680 sync_item->item_type = sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP; |
| 681 UpdateSyncItemInLocalStorage(profile_, sync_item); | |
| 589 SendSyncChange(sync_item, SyncChange::ACTION_UPDATE); | 682 SendSyncChange(sync_item, SyncChange::ACTION_UPDATE); |
| 590 return; | 683 return; |
| 591 } | 684 } |
| 592 | 685 |
| 593 DeleteSyncItem(iter->first); | 686 DeleteSyncItem(iter->first); |
| 594 } | 687 } |
| 595 | 688 |
| 596 void AppListSyncableService::ResolveFolderPositions() { | 689 void AppListSyncableService::ResolveFolderPositions() { |
| 597 if (!app_list::switches::IsFolderUIEnabled()) | 690 if (!app_list::switches::IsFolderUIEnabled()) |
| 598 return; | 691 return; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 642 const syncer::SyncDataList& initial_sync_data, | 735 const syncer::SyncDataList& initial_sync_data, |
| 643 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, | 736 std::unique_ptr<syncer::SyncChangeProcessor> sync_processor, |
| 644 std::unique_ptr<syncer::SyncErrorFactory> error_handler) { | 737 std::unique_ptr<syncer::SyncErrorFactory> error_handler) { |
| 645 DCHECK(!sync_processor_.get()); | 738 DCHECK(!sync_processor_.get()); |
| 646 DCHECK(sync_processor.get()); | 739 DCHECK(sync_processor.get()); |
| 647 DCHECK(error_handler.get()); | 740 DCHECK(error_handler.get()); |
| 648 | 741 |
| 649 // Ensure the model is built. | 742 // Ensure the model is built. |
| 650 GetModel(); | 743 GetModel(); |
| 651 | 744 |
| 745 // Reset local state and recreate from sync info. | |
| 746 DictionaryPrefUpdate pref_update(profile_->GetPrefs(), | |
| 747 prefs::kAppListLocalState); | |
| 748 pref_update->Clear(); | |
| 749 | |
| 652 sync_processor_ = std::move(sync_processor); | 750 sync_processor_ = std::move(sync_processor); |
| 653 sync_error_handler_ = std::move(error_handler); | 751 sync_error_handler_ = std::move(error_handler); |
| 654 if (switches::IsFolderUIEnabled()) | 752 if (switches::IsFolderUIEnabled()) |
| 655 model_->SetFoldersEnabled(true); | 753 model_->SetFoldersEnabled(true); |
| 656 | 754 |
| 657 syncer::SyncMergeResult result = syncer::SyncMergeResult(type); | 755 syncer::SyncMergeResult result = syncer::SyncMergeResult(type); |
| 658 result.set_num_items_before_association(sync_items_.size()); | 756 result.set_num_items_before_association(sync_items_.size()); |
| 659 VLOG(1) << this << ": MergeDataAndStartSyncing: " | 757 VLOG(1) << this << ": MergeDataAndStartSyncing: " |
| 660 << initial_sync_data.size(); | 758 << initial_sync_data.size(); |
| 661 | 759 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 699 // Send unsynced items. Does not affect |result|. | 797 // Send unsynced items. Does not affect |result|. |
| 700 syncer::SyncChangeList change_list; | 798 syncer::SyncChangeList change_list; |
| 701 for (std::set<std::string>::iterator iter = unsynced_items.begin(); | 799 for (std::set<std::string>::iterator iter = unsynced_items.begin(); |
| 702 iter != unsynced_items.end(); ++iter) { | 800 iter != unsynced_items.end(); ++iter) { |
| 703 SyncItem* sync_item = FindSyncItem(*iter); | 801 SyncItem* sync_item = FindSyncItem(*iter); |
| 704 // Sync can cause an item to change folders, causing an unsynced folder | 802 // Sync can cause an item to change folders, causing an unsynced folder |
| 705 // item to be removed. | 803 // item to be removed. |
| 706 if (!sync_item) | 804 if (!sync_item) |
| 707 continue; | 805 continue; |
| 708 VLOG(2) << this << " -> SYNC ADD: " << sync_item->ToString(); | 806 VLOG(2) << this << " -> SYNC ADD: " << sync_item->ToString(); |
| 807 UpdateSyncItemInLocalStorage(profile_, sync_item); | |
| 709 change_list.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_ADD, | 808 change_list.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_ADD, |
| 710 GetSyncDataFromSyncItem(sync_item))); | 809 GetSyncDataFromSyncItem(sync_item))); |
| 711 } | 810 } |
| 712 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); | 811 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); |
| 713 | 812 |
| 714 // Adding items may have created folders without setting their positions | 813 // Adding items may have created folders without setting their positions |
| 715 // since we haven't started observing the item list yet. Resolve those. | 814 // since we haven't started observing the item list yet. Resolve those. |
| 716 ResolveFolderPositions(); | 815 ResolveFolderPositions(); |
| 717 | 816 |
| 718 // Start observing app list model changes. | 817 // Start observing app list model changes. |
| 719 model_observer_.reset(new ModelObserver(this)); | 818 model_observer_.reset(new ModelObserver(this)); |
| 720 | 819 |
| 721 NotifyObserversSyncUpdated(); | 820 NotifyObserversSyncUpdated(); |
| 722 | 821 |
| 723 return result; | 822 return result; |
| 724 } | 823 } |
| 725 | 824 |
| 726 void AppListSyncableService::StopSyncing(syncer::ModelType type) { | 825 void AppListSyncableService::StopSyncing(syncer::ModelType type) { |
| 727 DCHECK_EQ(type, syncer::APP_LIST); | 826 DCHECK_EQ(type, syncer::APP_LIST); |
| 728 | 827 |
| 729 sync_processor_.reset(); | 828 sync_processor_.reset(); |
| 730 sync_error_handler_.reset(); | 829 sync_error_handler_.reset(); |
| 731 model_->SetFoldersEnabled(false); | |
| 732 } | 830 } |
| 733 | 831 |
| 734 syncer::SyncDataList AppListSyncableService::GetAllSyncData( | 832 syncer::SyncDataList AppListSyncableService::GetAllSyncData( |
| 735 syncer::ModelType type) const { | 833 syncer::ModelType type) const { |
| 736 DCHECK_EQ(syncer::APP_LIST, type); | 834 DCHECK_EQ(syncer::APP_LIST, type); |
| 737 | 835 |
| 738 VLOG(1) << this << ": GetAllSyncData: " << sync_items_.size(); | 836 VLOG(1) << this << ": GetAllSyncData: " << sync_items_.size(); |
| 739 syncer::SyncDataList list; | 837 syncer::SyncDataList list; |
| 740 for (auto iter = sync_items_.begin(); iter != sync_items_.end(); ++iter) { | 838 for (auto iter = sync_items_.begin(); iter != sync_items_.end(); ++iter) { |
| 741 VLOG(2) << this << " -> SYNC: " << iter->second->ToString(); | 839 VLOG(2) << this << " -> SYNC: " << iter->second->ToString(); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 790 if (item_id.empty()) { | 888 if (item_id.empty()) { |
| 791 LOG(ERROR) << "AppList item with empty ID"; | 889 LOG(ERROR) << "AppList item with empty ID"; |
| 792 return false; | 890 return false; |
| 793 } | 891 } |
| 794 SyncItem* sync_item = FindSyncItem(item_id); | 892 SyncItem* sync_item = FindSyncItem(item_id); |
| 795 if (sync_item) { | 893 if (sync_item) { |
| 796 // If an item of the same type exists, update it. | 894 // If an item of the same type exists, update it. |
| 797 if (sync_item->item_type == specifics.item_type()) { | 895 if (sync_item->item_type == specifics.item_type()) { |
| 798 UpdateSyncItemFromSync(specifics, sync_item); | 896 UpdateSyncItemFromSync(specifics, sync_item); |
| 799 ProcessExistingSyncItem(sync_item); | 897 ProcessExistingSyncItem(sync_item); |
| 898 UpdateSyncItemInLocalStorage(profile_, sync_item); | |
| 800 VLOG(2) << this << " <- SYNC UPDATE: " << sync_item->ToString(); | 899 VLOG(2) << this << " <- SYNC UPDATE: " << sync_item->ToString(); |
| 801 return false; | 900 return false; |
| 802 } | 901 } |
| 803 // Otherwise, one of the entries should be TYPE_REMOVE_DEFAULT_APP. | 902 // Otherwise, one of the entries should be TYPE_REMOVE_DEFAULT_APP. |
| 804 if (sync_item->item_type != | 903 if (sync_item->item_type != |
| 805 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP && | 904 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP && |
| 806 specifics.item_type() != | 905 specifics.item_type() != |
| 807 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { | 906 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { |
| 808 LOG(ERROR) << "Synced item type: " << specifics.item_type() | 907 LOG(ERROR) << "Synced item type: " << specifics.item_type() |
| 809 << " != existing sync item type: " << sync_item->item_type | 908 << " != existing sync item type: " << sync_item->item_type |
| 810 << " Deleting item from model!"; | 909 << " Deleting item from model!"; |
| 811 model_->DeleteItem(item_id); | 910 model_->DeleteItem(item_id); |
| 812 } | 911 } |
| 813 VLOG(2) << this << " - ProcessSyncItem: Delete existing entry: " | 912 VLOG(2) << this << " - ProcessSyncItem: Delete existing entry: " |
| 814 << sync_item->ToString(); | 913 << sync_item->ToString(); |
| 815 sync_items_.erase(item_id); | 914 sync_items_.erase(item_id); |
| 816 } | 915 } |
| 817 | 916 |
| 818 sync_item = CreateSyncItem(item_id, specifics.item_type()); | 917 sync_item = CreateSyncItem(item_id, specifics.item_type()); |
| 819 UpdateSyncItemFromSync(specifics, sync_item); | 918 UpdateSyncItemFromSync(specifics, sync_item); |
| 820 ProcessNewSyncItem(sync_item); | 919 ProcessNewSyncItem(sync_item); |
| 920 UpdateSyncItemInLocalStorage(profile_, sync_item); | |
| 821 VLOG(2) << this << " <- SYNC ADD: " << sync_item->ToString(); | 921 VLOG(2) << this << " <- SYNC ADD: " << sync_item->ToString(); |
| 822 return true; | 922 return true; |
| 823 } | 923 } |
| 824 | 924 |
| 825 void AppListSyncableService::ProcessNewSyncItem(SyncItem* sync_item) { | 925 void AppListSyncableService::ProcessNewSyncItem(SyncItem* sync_item) { |
| 826 VLOG(2) << "ProcessNewSyncItem: " << sync_item->ToString(); | 926 VLOG(2) << "ProcessNewSyncItem: " << sync_item->ToString(); |
| 827 switch (sync_item->item_type) { | 927 switch (sync_item->item_type) { |
| 828 case sync_pb::AppListSpecifics::TYPE_APP: { | 928 case sync_pb::AppListSpecifics::TYPE_APP: { |
| 829 // New apps are added through ExtensionAppModelBuilder. | 929 // New apps are added through ExtensionAppModelBuilder. |
| 830 // TODO(stevenjb): Determine how to handle app items in sync that | 930 // TODO(stevenjb): Determine how to handle app items in sync that |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 962 LOG(ERROR) << "Delete AppList item with empty ID"; | 1062 LOG(ERROR) << "Delete AppList item with empty ID"; |
| 963 return; | 1063 return; |
| 964 } | 1064 } |
| 965 VLOG(2) << this << ": DeleteSyncItemSpecifics: " << item_id.substr(0, 8); | 1065 VLOG(2) << this << ": DeleteSyncItemSpecifics: " << item_id.substr(0, 8); |
| 966 auto iter = sync_items_.find(item_id); | 1066 auto iter = sync_items_.find(item_id); |
| 967 if (iter == sync_items_.end()) | 1067 if (iter == sync_items_.end()) |
| 968 return; | 1068 return; |
| 969 sync_pb::AppListSpecifics::AppListItemType item_type = | 1069 sync_pb::AppListSpecifics::AppListItemType item_type = |
| 970 iter->second->item_type; | 1070 iter->second->item_type; |
| 971 VLOG(2) << this << " <- SYNC DELETE: " << iter->second->ToString(); | 1071 VLOG(2) << this << " <- SYNC DELETE: " << iter->second->ToString(); |
| 1072 RemoveSyncItemFromLocalStorage(profile_, item_id); | |
| 972 sync_items_.erase(iter); | 1073 sync_items_.erase(iter); |
| 1074 | |
| 973 // Only delete apps from the model. Folders will be deleted when all | 1075 // Only delete apps from the model. Folders will be deleted when all |
| 974 // children have been deleted. | 1076 // children have been deleted. |
| 975 if (item_type == sync_pb::AppListSpecifics::TYPE_APP) { | 1077 if (item_type == sync_pb::AppListSpecifics::TYPE_APP) { |
| 976 model_->DeleteItem(item_id); | 1078 model_->DeleteItem(item_id); |
| 977 } else if (item_type == sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { | 1079 } else if (item_type == sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { |
| 978 if (IsDriveAppSyncId(item_id) && drive_app_provider_) { | 1080 if (IsDriveAppSyncId(item_id) && drive_app_provider_) { |
| 979 drive_app_provider_->RemoveUninstalledDriveAppFromSync( | 1081 drive_app_provider_->RemoveUninstalledDriveAppFromSync( |
| 980 GetDriveAppIdFromSyncId(item_id)); | 1082 GetDriveAppIdFromSyncId(item_id)); |
| 981 } | 1083 } |
| 982 } | 1084 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1069 res += " { " + item_name + " }"; | 1171 res += " { " + item_name + " }"; |
| 1070 res += " [" + item_ordinal.ToDebugString() + "]"; | 1172 res += " [" + item_ordinal.ToDebugString() + "]"; |
| 1071 if (!parent_id.empty()) | 1173 if (!parent_id.empty()) |
| 1072 res += " <" + parent_id.substr(0, 8) + ">"; | 1174 res += " <" + parent_id.substr(0, 8) + ">"; |
| 1073 res += " [" + item_pin_ordinal.ToDebugString() + "]"; | 1175 res += " [" + item_pin_ordinal.ToDebugString() + "]"; |
| 1074 } | 1176 } |
| 1075 return res; | 1177 return res; |
| 1076 } | 1178 } |
| 1077 | 1179 |
| 1078 } // namespace app_list | 1180 } // namespace app_list |
| OLD | NEW |