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

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

Issue 981893002: Lazily build the app list model. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@fix_set_enabled
Patch Set: Created 5 years, 9 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
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 "base/strings/string_util.h" 8 #include "base/strings/string_util.h"
9 #include "chrome/browser/apps/drive/drive_app_provider.h" 9 #include "chrome/browser/apps/drive/drive_app_provider.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/extensions/extension_service.h" 10 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/app_list/app_list_prefs.h" 12 #include "chrome/browser/ui/app_list/app_list_prefs.h"
14 #include "chrome/browser/ui/app_list/app_list_service.h" 13 #include "chrome/browser/ui/app_list/app_list_service.h"
15 #include "chrome/browser/ui/app_list/extension_app_item.h" 14 #include "chrome/browser/ui/app_list/extension_app_item.h"
16 #include "chrome/browser/ui/app_list/extension_app_model_builder.h" 15 #include "chrome/browser/ui/app_list/extension_app_model_builder.h"
17 #include "chrome/browser/ui/app_list/model_pref_updater.h" 16 #include "chrome/browser/ui/app_list/model_pref_updater.h"
18 #include "chrome/browser/ui/host_desktop.h" 17 #include "chrome/browser/ui/host_desktop.h"
19 #include "chrome/common/chrome_switches.h" 18 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/extensions/extension_constants.h" 19 #include "chrome/common/extensions/extension_constants.h"
21 #include "chrome/grit/generated_resources.h" 20 #include "chrome/grit/generated_resources.h"
22 #include "content/public/browser/notification_source.h"
23 #include "extensions/browser/extension_prefs.h" 21 #include "extensions/browser/extension_prefs.h"
24 #include "extensions/browser/extension_system.h" 22 #include "extensions/browser/extension_system.h"
25 #include "extensions/browser/uninstall_reason.h" 23 #include "extensions/browser/uninstall_reason.h"
26 #include "extensions/common/constants.h" 24 #include "extensions/common/constants.h"
27 #include "sync/api/sync_change_processor.h" 25 #include "sync/api/sync_change_processor.h"
28 #include "sync/api/sync_data.h" 26 #include "sync/api/sync_data.h"
29 #include "sync/api/sync_merge_result.h" 27 #include "sync/api/sync_merge_result.h"
30 #include "sync/protocol/sync.pb.h" 28 #include "sync/protocol/sync.pb.h"
31 #include "ui/app_list/app_list_folder_item.h" 29 #include "ui/app_list/app_list_folder_item.h"
32 #include "ui/app_list/app_list_item.h" 30 #include "ui/app_list/app_list_item.h"
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 } 172 }
175 173
176 // AppListSyncableService::ModelObserver 174 // AppListSyncableService::ModelObserver
177 175
178 class AppListSyncableService::ModelObserver : public AppListModelObserver { 176 class AppListSyncableService::ModelObserver : public AppListModelObserver {
179 public: 177 public:
180 explicit ModelObserver(AppListSyncableService* owner) 178 explicit ModelObserver(AppListSyncableService* owner)
181 : owner_(owner), 179 : owner_(owner),
182 adding_item_(NULL) { 180 adding_item_(NULL) {
183 DVLOG(2) << owner_ << ": ModelObserver Added"; 181 DVLOG(2) << owner_ << ": ModelObserver Added";
184 owner_->model()->AddObserver(this); 182 owner_->GetModel()->AddObserver(this);
185 } 183 }
186 184
187 ~ModelObserver() override { 185 ~ModelObserver() override {
188 owner_->model()->RemoveObserver(this); 186 owner_->GetModel()->RemoveObserver(this);
189 DVLOG(2) << owner_ << ": ModelObserver Removed"; 187 DVLOG(2) << owner_ << ": ModelObserver Removed";
190 } 188 }
191 189
192 private: 190 private:
193 // AppListModelObserver 191 // AppListModelObserver
194 void OnAppListItemAdded(AppListItem* item) override { 192 void OnAppListItemAdded(AppListItem* item) override {
195 DCHECK(!adding_item_); 193 DCHECK(!adding_item_);
196 adding_item_ = item; // Ignore updates while adding an item. 194 adding_item_ = item; // Ignore updates while adding an item.
197 VLOG(2) << owner_ << " OnAppListItemAdded: " << item->ToDebugString(); 195 VLOG(2) << owner_ << " OnAppListItemAdded: " << item->ToDebugString();
198 owner_->AddOrUpdateFromSyncItem(item); 196 owner_->AddOrUpdateFromSyncItem(item);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 model_(new AppListModel), 235 model_(new AppListModel),
238 initial_sync_data_processed_(false), 236 initial_sync_data_processed_(false),
239 first_app_list_sync_(true) { 237 first_app_list_sync_(true) {
240 if (!extension_system) { 238 if (!extension_system) {
241 LOG(ERROR) << "AppListSyncableService created with no ExtensionSystem"; 239 LOG(ERROR) << "AppListSyncableService created with no ExtensionSystem";
242 return; 240 return;
243 } 241 }
244 242
245 oem_folder_name_ = 243 oem_folder_name_ =
246 l10n_util::GetStringUTF8(IDS_APP_LIST_OEM_DEFAULT_FOLDER_NAME); 244 l10n_util::GetStringUTF8(IDS_APP_LIST_OEM_DEFAULT_FOLDER_NAME);
247
248 // Note: model_observer_ is constructed after the initial sync changes are
249 // received in MergeDataAndStartSyncing(). Changes to the model before that
250 // will be synced after the initial sync occurs.
251 if (extension_system->extension_service() &&
tapted 2015/03/10 19:19:54 How do you know this logic isn't needed any more?
stevenjb 2015/03/10 19:56:06 Since AppListSyncableService is a context keyed se
calamity 2015/03/12 21:23:22 DCHECKs added.
252 extension_system->extension_service()->is_ready()) {
253 BuildModel();
254 return;
255 }
256
257 // The extensions for this profile have not yet all been loaded.
258 registrar_.Add(this,
259 extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED,
260 content::Source<Profile>(profile));
261 } 245 }
262 246
263 AppListSyncableService::~AppListSyncableService() { 247 AppListSyncableService::~AppListSyncableService() {
264 // Remove observers. 248 // Remove observers.
265 model_observer_.reset(); 249 model_observer_.reset();
266 model_pref_updater_.reset(); 250 model_pref_updater_.reset();
267 251
268 STLDeleteContainerPairSecondPointers(sync_items_.begin(), sync_items_.end()); 252 STLDeleteContainerPairSecondPointers(sync_items_.begin(), sync_items_.end());
269 } 253 }
270 254
271 void AppListSyncableService::BuildModel() { 255 void AppListSyncableService::BuildModel() {
272 // For now, use the AppListControllerDelegate associated with the native 256 // For now, use the AppListControllerDelegate associated with the native
273 // desktop. TODO(stevenjb): Remove ExtensionAppModelBuilder controller 257 // desktop. TODO(stevenjb): Remove ExtensionAppModelBuilder controller
274 // dependency and move the dependent methods from AppListControllerDelegate 258 // dependency and move the dependent methods from AppListControllerDelegate
275 // to an extension service delegate associated with this class. 259 // to an extension service delegate associated with this class.
276 AppListControllerDelegate* controller = NULL; 260 AppListControllerDelegate* controller = NULL;
277 AppListService* service = 261 AppListService* service =
278 AppListService::Get(chrome::HOST_DESKTOP_TYPE_NATIVE); 262 AppListService::Get(chrome::HOST_DESKTOP_TYPE_NATIVE);
279 if (service) 263 if (service)
280 controller = service->GetControllerDelegate(); 264 controller = service->GetControllerDelegate();
281 apps_builder_.reset(new ExtensionAppModelBuilder(controller)); 265 apps_builder_.reset(new ExtensionAppModelBuilder(controller));
282 DCHECK(profile_); 266 DCHECK(profile_);
283 if (app_list::switches::IsAppListSyncEnabled()) { 267 if (app_list::switches::IsAppListSyncEnabled()) {
284 VLOG(1) << this << ": AppListSyncableService: InitializeWithService."; 268 VLOG(1) << this << ": AppListSyncableService: InitializeWithService.";
285 SyncStarted(); 269 SyncStarted();
286 apps_builder_->InitializeWithService(this); 270 apps_builder_->InitializeWithService(this, model_.get());
287 } else { 271 } else {
288 VLOG(1) << this << ": AppListSyncableService: InitializeWithProfile."; 272 VLOG(1) << this << ": AppListSyncableService: InitializeWithProfile.";
289 apps_builder_->InitializeWithProfile(profile_, model_.get()); 273 apps_builder_->InitializeWithProfile(profile_, model_.get());
290 } 274 }
291 275
292 model_pref_updater_.reset( 276 model_pref_updater_.reset(
293 new ModelPrefUpdater(AppListPrefs::Get(profile_), model_.get())); 277 new ModelPrefUpdater(AppListPrefs::Get(profile_), model_.get()));
294 278
295 if (app_list::switches::IsDriveAppsInAppListEnabled()) 279 if (app_list::switches::IsDriveAppsInAppListEnabled())
296 drive_app_provider_.reset(new DriveAppProvider(profile_, this)); 280 drive_app_provider_.reset(new DriveAppProvider(profile_, this));
297 } 281 }
298 282
283 size_t AppListSyncableService::GetNumSyncItemsForTest() {
284 // If the model isn't built yet, there will be no sync items.
285 if (!apps_builder_)
286 BuildModel();
stevenjb 2015/03/10 19:56:06 nit: GetModel();
calamity 2015/03/12 21:23:22 Done.
287
288 return sync_items_.size();
289 }
290
299 void AppListSyncableService::ResetDriveAppProviderForTest() { 291 void AppListSyncableService::ResetDriveAppProviderForTest() {
300 drive_app_provider_.reset(); 292 drive_app_provider_.reset();
301 } 293 }
302 294
303 void AppListSyncableService::Shutdown() { 295 void AppListSyncableService::Shutdown() {
304 // DriveAppProvider touches other KeyedServices in its dtor and needs be 296 // DriveAppProvider touches other KeyedServices in its dtor and needs be
305 // released in shutdown stage. 297 // released in shutdown stage.
306 drive_app_provider_.reset(); 298 drive_app_provider_.reset();
307 } 299 }
308 300
(...skipping 17 matching lines...) Expand all
326 const std::string sync_id = GetDriveAppSyncId(drive_app_id); 318 const std::string sync_id = GetDriveAppSyncId(drive_app_id);
327 SyncItem* sync_item = FindSyncItem(sync_id); 319 SyncItem* sync_item = FindSyncItem(sync_id);
328 if (!sync_item) 320 if (!sync_item)
329 return; 321 return;
330 322
331 DCHECK_EQ(sync_item->item_type, 323 DCHECK_EQ(sync_item->item_type,
332 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP); 324 sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP);
333 DeleteSyncItem(sync_item); 325 DeleteSyncItem(sync_item);
334 } 326 }
335 327
336 void AppListSyncableService::Observe(
337 int type,
338 const content::NotificationSource& source,
339 const content::NotificationDetails& details) {
340 DCHECK_EQ(extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, type);
341 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr());
342 registrar_.RemoveAll();
343 BuildModel();
344 }
345
346 const AppListSyncableService::SyncItem* 328 const AppListSyncableService::SyncItem*
347 AppListSyncableService::GetSyncItem(const std::string& id) const { 329 AppListSyncableService::GetSyncItem(const std::string& id) const {
348 SyncItemMap::const_iterator iter = sync_items_.find(id); 330 SyncItemMap::const_iterator iter = sync_items_.find(id);
349 if (iter != sync_items_.end()) 331 if (iter != sync_items_.end())
350 return iter->second; 332 return iter->second;
351 return NULL; 333 return NULL;
352 } 334 }
353 335
354 void AppListSyncableService::SetOemFolderName(const std::string& name) { 336 void AppListSyncableService::SetOemFolderName(const std::string& name) {
355 oem_folder_name_ = name; 337 oem_folder_name_ = name;
356 AppListFolderItem* oem_folder = model_->FindFolderItem(kOemFolderId); 338 AppListFolderItem* oem_folder = model_->FindFolderItem(kOemFolderId);
357 if (oem_folder) 339 if (oem_folder)
358 model_->SetItemName(oem_folder, oem_folder_name_); 340 model_->SetItemName(oem_folder, oem_folder_name_);
359 } 341 }
360 342
343 AppListModel* AppListSyncableService::GetModel() {
344 if (!apps_builder_)
345 BuildModel();
346
347 return model_.get();
348 }
349
361 void AppListSyncableService::AddItem(scoped_ptr<AppListItem> app_item) { 350 void AppListSyncableService::AddItem(scoped_ptr<AppListItem> app_item) {
362 SyncItem* sync_item = FindOrAddSyncItem(app_item.get()); 351 SyncItem* sync_item = FindOrAddSyncItem(app_item.get());
363 if (!sync_item) 352 if (!sync_item)
364 return; // Item is not valid. 353 return; // Item is not valid.
365 354
366 std::string folder_id; 355 std::string folder_id;
367 if (app_list::switches::IsFolderUIEnabled()) { 356 if (app_list::switches::IsFolderUIEnabled()) {
368 if (AppIsOem(app_item->id())) { 357 if (AppIsOem(app_item->id())) {
369 folder_id = FindOrCreateOemFolder(); 358 folder_id = FindOrCreateOemFolder();
370 VLOG_IF(2, !folder_id.empty()) 359 VLOG_IF(2, !folder_id.empty())
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 bool changed = UpdateSyncItemFromAppItem(app_item, sync_item); 463 bool changed = UpdateSyncItemFromAppItem(app_item, sync_item);
475 if (!changed) { 464 if (!changed) {
476 DVLOG(2) << this << " - Update: SYNC NO CHANGE: " << sync_item->ToString(); 465 DVLOG(2) << this << " - Update: SYNC NO CHANGE: " << sync_item->ToString();
477 return; 466 return;
478 } 467 }
479 SendSyncChange(sync_item, SyncChange::ACTION_UPDATE); 468 SendSyncChange(sync_item, SyncChange::ACTION_UPDATE);
480 } 469 }
481 470
482 void AppListSyncableService::RemoveItem(const std::string& id) { 471 void AppListSyncableService::RemoveItem(const std::string& id) {
483 RemoveSyncItem(id); 472 RemoveSyncItem(id);
484 model_->DeleteItem(id); 473 model_->DeleteItem(id);
tapted 2015/03/10 19:19:54 What about all these calls internally that access
stevenjb 2015/03/10 19:56:06 No sync events will get called before MergeDataAnd
Nicolas Zea 2015/03/12 18:09:00 Sync can start up at any time, whether or not GetM
calamity 2015/03/12 21:23:22 Hmm. I don't know if I should ensure the model is
Nicolas Zea 2015/03/12 21:28:05 If you're concerned about a race here, Sync has th
tapted 2015/03/20 11:47:14 Perhaps just GetModel() with a comment at the star
calamity 2015/03/23 05:14:49 Done.
485 PruneEmptySyncFolders(); 474 PruneEmptySyncFolders();
486 } 475 }
487 476
488 void AppListSyncableService::UpdateItem(AppListItem* app_item) { 477 void AppListSyncableService::UpdateItem(AppListItem* app_item) {
489 // Check to see if the item needs to be moved to/from the OEM folder. 478 // Check to see if the item needs to be moved to/from the OEM folder.
490 if (!app_list::switches::IsFolderUIEnabled()) 479 if (!app_list::switches::IsFolderUIEnabled())
491 return; 480 return;
492 bool is_oem = AppIsOem(app_item->id()); 481 bool is_oem = AppIsOem(app_item->id());
493 if (!is_oem && app_item->folder_id() == kOemFolderId) 482 if (!is_oem && app_item->folder_id() == kOemFolderId)
494 model_->MoveItemToFolder(app_item, ""); 483 model_->MoveItemToFolder(app_item, "");
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 } else { 985 } else {
997 res += " { " + item_name + " }"; 986 res += " { " + item_name + " }";
998 res += " [" + item_ordinal.ToDebugString() + "]"; 987 res += " [" + item_ordinal.ToDebugString() + "]";
999 if (!parent_id.empty()) 988 if (!parent_id.empty())
1000 res += " <" + parent_id.substr(0, 8) + ">"; 989 res += " <" + parent_id.substr(0, 8) + ">";
1001 } 990 }
1002 return res; 991 return res;
1003 } 992 }
1004 993
1005 } // namespace app_list 994 } // namespace app_list
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698