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

Side by Side Diff: chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc

Issue 2769323002: mash: Update shelf pin prefs in ShelfModelObserver overrides. (Closed)
Patch Set: Cleanup; fix tests by ignoring initial browser shortcut pin position syncing. Created 3 years, 8 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/ash/launcher/chrome_launcher_controller_impl.h" 5 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <vector> 9 #include <vector>
10 10
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 #include "chrome/grit/generated_resources.h" 71 #include "chrome/grit/generated_resources.h"
72 #include "chrome/grit/theme_resources.h" 72 #include "chrome/grit/theme_resources.h"
73 #include "components/favicon/content/content_favicon_driver.h" 73 #include "components/favicon/content/content_favicon_driver.h"
74 #include "components/prefs/scoped_user_pref_update.h" 74 #include "components/prefs/scoped_user_pref_update.h"
75 #include "components/signin/core/account_id/account_id.h" 75 #include "components/signin/core/account_id/account_id.h"
76 #include "components/strings/grit/components_strings.h" 76 #include "components/strings/grit/components_strings.h"
77 #include "components/sync_preferences/pref_service_syncable.h" 77 #include "components/sync_preferences/pref_service_syncable.h"
78 #include "components/user_manager/user_manager.h" 78 #include "components/user_manager/user_manager.h"
79 #include "content/public/browser/navigation_entry.h" 79 #include "content/public/browser/navigation_entry.h"
80 #include "content/public/browser/web_contents.h" 80 #include "content/public/browser/web_contents.h"
81 #include "extensions/browser/extension_system.h"
James Cook 2017/03/29 14:28:02 Are these new includes needed?
msw 2017/03/29 21:34:17 Nope, thanks for catching that; removed.
81 #include "extensions/common/extension.h" 82 #include "extensions/common/extension.h"
83 #include "extensions/common/one_shot_event.h"
82 #include "ui/aura/window.h" 84 #include "ui/aura/window.h"
83 #include "ui/aura/window_event_dispatcher.h" 85 #include "ui/aura/window_event_dispatcher.h"
84 #include "ui/base/l10n/l10n_util.h" 86 #include "ui/base/l10n/l10n_util.h"
85 #include "ui/base/resource/resource_bundle.h" 87 #include "ui/base/resource/resource_bundle.h"
86 #include "ui/base/window_open_disposition.h" 88 #include "ui/base/window_open_disposition.h"
87 #include "ui/display/types/display_constants.h" 89 #include "ui/display/types/display_constants.h"
88 #include "ui/keyboard/keyboard_util.h" 90 #include "ui/keyboard/keyboard_util.h"
89 #include "ui/resources/grit/ui_resources.h" 91 #include "ui/resources/grit/ui_resources.h"
90 #include "ui/wm/core/window_animations.h" 92 #include "ui/wm/core/window_animations.h"
91 93
(...skipping 13 matching lines...) Expand all
105 // A callback that does nothing after shelf item selection handling. 107 // A callback that does nothing after shelf item selection handling.
106 void NoopCallback(ash::ShelfAction, base::Optional<MenuItemList>) {} 108 void NoopCallback(ash::ShelfAction, base::Optional<MenuItemList>) {}
107 109
108 // Calls ItemSelected with |source|, default arguments, and no callback. 110 // Calls ItemSelected with |source|, default arguments, and no callback.
109 void SelectItemWithSource(ash::mojom::ShelfItemDelegate* delegate, 111 void SelectItemWithSource(ash::mojom::ShelfItemDelegate* delegate,
110 ash::ShelfLaunchSource source) { 112 ash::ShelfLaunchSource source) {
111 delegate->ItemSelected(nullptr, display::kInvalidDisplayId, source, 113 delegate->ItemSelected(nullptr, display::kInvalidDisplayId, source,
112 base::Bind(&NoopCallback)); 114 base::Bind(&NoopCallback));
113 } 115 }
114 116
117 // Returns true if the given |item| has a pinned shelf item type.
118 bool ItemTypeIsPinned(const ash::ShelfItem& item) {
119 return item.type == ash::TYPE_PINNED_APP ||
120 item.type == ash::TYPE_BROWSER_SHORTCUT;
121 }
122
115 } // namespace 123 } // namespace
116 124
117 // A class to get events from ChromeOS when a user gets changed or added. 125 // A class to get events from ChromeOS when a user gets changed or added.
118 class ChromeLauncherControllerUserSwitchObserver 126 class ChromeLauncherControllerUserSwitchObserver
119 : public user_manager::UserManager::UserSessionStateObserver { 127 : public user_manager::UserManager::UserSessionStateObserver {
120 public: 128 public:
121 ChromeLauncherControllerUserSwitchObserver( 129 ChromeLauncherControllerUserSwitchObserver(
122 ChromeLauncherControllerImpl* controller) 130 ChromeLauncherControllerImpl* controller)
123 : controller_(controller) { 131 : controller_(controller) {
124 DCHECK(user_manager::UserManager::IsInitialized()); 132 DCHECK(user_manager::UserManager::IsInitialized());
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 const ash::ShelfItem* item = GetItem(id); 362 const ash::ShelfItem* item = GetItem(id);
355 LauncherItemController* controller = GetLauncherItemController(id); 363 LauncherItemController* controller = GetLauncherItemController(id);
356 if (item && (item->status != ash::STATUS_CLOSED || controller->locked())) 364 if (item && (item->status != ash::STATUS_CLOSED || controller->locked()))
357 UnpinRunningAppInternal(model_->ItemIndexByID(id)); 365 UnpinRunningAppInternal(model_->ItemIndexByID(id));
358 else 366 else
359 LauncherItemClosed(id); 367 LauncherItemClosed(id);
360 } 368 }
361 369
362 bool ChromeLauncherControllerImpl::IsPinned(ash::ShelfID id) { 370 bool ChromeLauncherControllerImpl::IsPinned(ash::ShelfID id) {
363 const ash::ShelfItem* item = GetItem(id); 371 const ash::ShelfItem* item = GetItem(id);
364 return item && (item->type == ash::TYPE_PINNED_APP || 372 return item && ItemTypeIsPinned(*item);
365 item->type == ash::TYPE_BROWSER_SHORTCUT);
366 } 373 }
367 374
368 void ChromeLauncherControllerImpl::LockV1AppWithID(const std::string& app_id) { 375 void ChromeLauncherControllerImpl::LockV1AppWithID(const std::string& app_id) {
369 ash::ShelfID id = GetShelfIDForAppID(app_id); 376 ash::ShelfID id = GetShelfIDForAppID(app_id);
370 if (id == ash::kInvalidShelfID) { 377 if (id == ash::kInvalidShelfID) {
371 CreateAppShortcutLauncherItemWithType(ash::AppLaunchId(app_id), 378 CreateAppShortcutLauncherItemWithType(ash::AppLaunchId(app_id),
372 model_->item_count(), ash::TYPE_APP); 379 model_->item_count(), ash::TYPE_APP);
373 id = GetShelfIDForAppID(app_id); 380 id = GetShelfIDForAppID(app_id);
374 } 381 }
375 CHECK(id); 382 CHECK(id);
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 // Convert an existing item to be pinned, or create a new pinned item. 850 // Convert an existing item to be pinned, or create a new pinned item.
844 ash::ShelfID shelf_id = GetShelfIDForAppID(shelf_app_id); 851 ash::ShelfID shelf_id = GetShelfIDForAppID(shelf_app_id);
845 if (shelf_id != ash::kInvalidShelfID) { 852 if (shelf_id != ash::kInvalidShelfID) {
846 DCHECK_EQ(GetItem(shelf_id)->type, ash::TYPE_APP); 853 DCHECK_EQ(GetItem(shelf_id)->type, ash::TYPE_APP);
847 DCHECK(!GetItem(shelf_id)->pinned_by_policy); 854 DCHECK(!GetItem(shelf_id)->pinned_by_policy);
848 SetItemType(shelf_id, ash::TYPE_PINNED_APP); 855 SetItemType(shelf_id, ash::TYPE_PINNED_APP);
849 } else { 856 } else {
850 shelf_id = CreateAppShortcutLauncherItem(ash::AppLaunchId(shelf_app_id), 857 shelf_id = CreateAppShortcutLauncherItem(ash::AppLaunchId(shelf_app_id),
851 model_->item_count()); 858 model_->item_count());
852 } 859 }
853
854 // TODO(msw): Trigger pref updates in ShelfModelObserver overrides.
855 SyncPinPosition(shelf_id);
856 } 860 }
857 861
858 bool ChromeLauncherControllerImpl::IsAppPinned(const std::string& app_id) { 862 bool ChromeLauncherControllerImpl::IsAppPinned(const std::string& app_id) {
859 // TODO(khmel): Fix this Arc application id mapping. See http://b/31703859 863 // TODO(khmel): Fix this Arc application id mapping. See http://b/31703859
860 const std::string shelf_app_id = 864 const std::string shelf_app_id =
861 ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(app_id); 865 ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(app_id);
862 866
863 return IsPinned(GetShelfIDForAppID(shelf_app_id)); 867 return IsPinned(GetShelfIDForAppID(shelf_app_id));
864 } 868 }
865 869
866 void ChromeLauncherControllerImpl::UnpinAppWithID(const std::string& app_id) { 870 void ChromeLauncherControllerImpl::UnpinAppWithID(const std::string& app_id) {
867 // TODO(khmel): Fix this Arc application id mapping. See http://b/31703859 871 // TODO(khmel): Fix this Arc application id mapping. See http://b/31703859
868 const std::string shelf_app_id = 872 const std::string shelf_app_id =
869 ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(app_id); 873 ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(app_id);
870 874
871 // Requests to unpin should only be be made for apps with editable pin states. 875 // Requests to unpin should only be be made for apps with editable pin states.
872 DCHECK_EQ(GetPinnableForAppID(shelf_app_id, profile()), 876 DCHECK_EQ(GetPinnableForAppID(shelf_app_id, profile()),
873 AppListControllerDelegate::PIN_EDITABLE); 877 AppListControllerDelegate::PIN_EDITABLE);
874 878
875 // If the app is already not pinned, do nothing and return. 879 // If the app is pinned, unpin the shelf item (and remove it if not running).
876 if (!IsAppPinned(shelf_app_id)) 880 if (IsAppPinned(shelf_app_id))
877 return; 881 UnpinShelfItemInternal(GetShelfIDForAppID(shelf_app_id));
878
879 // TODO(msw): Trigger pref updates in ShelfModelObserver overrides.
880 ash::launcher::RemovePinPosition(profile(), ash::AppLaunchId(shelf_app_id));
881
882 // Unpin the shelf item.
883 UnpinShelfItemInternal(GetShelfIDForAppID(shelf_app_id));
884 } 882 }
885 883
886 /////////////////////////////////////////////////////////////////////////////// 884 ///////////////////////////////////////////////////////////////////////////////
887 // LauncherAppUpdater::Delegate: 885 // LauncherAppUpdater::Delegate:
888 886
889 void ChromeLauncherControllerImpl::OnAppInstalled( 887 void ChromeLauncherControllerImpl::OnAppInstalled(
890 content::BrowserContext* browser_context, 888 content::BrowserContext* browser_context,
891 const std::string& app_id) { 889 const std::string& app_id) {
892 if (IsAppPinned(app_id)) { 890 if (IsAppPinned(app_id)) {
893 // Clear and re-fetch to ensure icon is up-to-date. 891 // Clear and re-fetch to ensure icon is up-to-date.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 // pin position from profile preferences. When needed, it is automatically 923 // pin position from profile preferences. When needed, it is automatically
926 // deleted on app list model update. 924 // deleted on app list model update.
927 UnpinShelfItemInternal(shelf_id); 925 UnpinShelfItemInternal(shelf_id);
928 } 926 }
929 AppIconLoader* app_icon_loader = GetAppIconLoaderForApp(app_id); 927 AppIconLoader* app_icon_loader = GetAppIconLoaderForApp(app_id);
930 if (app_icon_loader) 928 if (app_icon_loader)
931 app_icon_loader->ClearImage(app_id); 929 app_icon_loader->ClearImage(app_id);
932 } 930 }
933 } 931 }
934 932
933 void ChromeLauncherControllerImpl::OnAppDisabling(const std::string& app_id) {
934 // Avoid removing pin positions of ARC apps when ARC itself is disabled.
msw 2017/03/29 01:29:56 This is unfortunate and I'm receptive to better ap
935 keep_pin_positions_.insert(app_id);
936 }
937
938 void ChromeLauncherControllerImpl::OnAppDisabled(const std::string& app_id) {
939 keep_pin_positions_.erase(app_id);
940 }
941
935 /////////////////////////////////////////////////////////////////////////////// 942 ///////////////////////////////////////////////////////////////////////////////
936 // ChromeLauncherControllerImpl protected: 943 // ChromeLauncherControllerImpl protected:
937 944
938 void ChromeLauncherControllerImpl::OnInit() { 945 void ChromeLauncherControllerImpl::OnInit() {
939 CreateBrowserShortcutLauncherItem(); 946 CreateBrowserShortcutLauncherItem();
940 UpdateAppLaunchersFromPref(); 947 UpdateAppLaunchersFromPref();
941 948
942 // TODO(sky): update unit test so that this test isn't necessary. 949 // TODO(sky): update unit test so that this test isn't necessary.
943 if (ash::Shell::HasInstance()) 950 if (ash::Shell::HasInstance())
944 SetVirtualKeyboardBehaviorFromPrefs(); 951 SetVirtualKeyboardBehaviorFromPrefs();
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
1260 if (app_icon_loader) { 1267 if (app_icon_loader) {
1261 app_icon_loader->FetchImage(app_id); 1268 app_icon_loader->FetchImage(app_id);
1262 app_icon_loader->UpdateImage(app_id); 1269 app_icon_loader->UpdateImage(app_id);
1263 } 1270 }
1264 1271
1265 SetShelfItemDelegate(id, controller); 1272 SetShelfItemDelegate(id, controller);
1266 return id; 1273 return id;
1267 } 1274 }
1268 1275
1269 void ChromeLauncherControllerImpl::CreateBrowserShortcutLauncherItem() { 1276 void ChromeLauncherControllerImpl::CreateBrowserShortcutLauncherItem() {
1277 // Do not sync the pin position of the browser shortcut item when it is added;
msw 2017/03/29 01:29:56 This threw me for a loop... I tried other approach
1278 // its initial position before prefs have loaded is unimportant and the sync
1279 // service may not yet be initialized.
1280 base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true);
1281
1270 ash::ShelfItem browser_shortcut; 1282 ash::ShelfItem browser_shortcut;
1271 browser_shortcut.type = ash::TYPE_BROWSER_SHORTCUT; 1283 browser_shortcut.type = ash::TYPE_BROWSER_SHORTCUT;
1272 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 1284 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
1273 browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32); 1285 browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32);
1274 browser_shortcut.title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); 1286 browser_shortcut.title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
1275 browser_shortcut.app_launch_id = 1287 browser_shortcut.app_launch_id =
1276 ash::AppLaunchId(extension_misc::kChromeAppId); 1288 ash::AppLaunchId(extension_misc::kChromeAppId);
1277 ash::ShelfID id = model_->next_id(); 1289 ash::ShelfID id = model_->next_id();
1278 model_->AddAt(0, browser_shortcut); 1290 model_->AddAt(0, browser_shortcut);
1279 BrowserShortcutLauncherItemController* controller = 1291 BrowserShortcutLauncherItemController* controller =
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1354 app_list::AppListSyncableServiceFactory::GetForProfile(profile()); 1366 app_list::AppListSyncableServiceFactory::GetForProfile(profile());
1355 if (app_service) 1367 if (app_service)
1356 app_service->RemoveObserver(this); 1368 app_service->RemoveObserver(this);
1357 1369
1358 PrefServiceSyncableFromProfile(profile())->RemoveObserver(this); 1370 PrefServiceSyncableFromProfile(profile())->RemoveObserver(this);
1359 } 1371 }
1360 1372
1361 /////////////////////////////////////////////////////////////////////////////// 1373 ///////////////////////////////////////////////////////////////////////////////
1362 // ash::ShelfModelObserver: 1374 // ash::ShelfModelObserver:
1363 1375
1364 void ChromeLauncherControllerImpl::ShelfItemAdded(int index) {} 1376 void ChromeLauncherControllerImpl::ShelfItemAdded(int index) {
1377 // Update the pin position preference as needed.
1378 const ash::ShelfItem& item = model_->items()[index];
1379 if (ItemTypeIsPinned(item) && !ignore_persist_pinned_state_change_)
James Cook 2017/03/29 14:28:02 SyncPinPosition() checks ignore_persist_pinned_sta
msw 2017/03/29 21:34:17 I changed the check inside SyncPinPosition to a DC
1380 SyncPinPosition(item.id);
1381 }
1365 1382
1366 void ChromeLauncherControllerImpl::ShelfItemRemoved( 1383 void ChromeLauncherControllerImpl::ShelfItemRemoved(
1367 int index, 1384 int index,
1368 const ash::ShelfItem& old_item) { 1385 const ash::ShelfItem& old_item) {
1386 // TODO(khmel): Fix this Arc application id mapping. See http://b/31703859
1387 const std::string shelf_app_id =
1388 ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(
1389 old_item.app_launch_id.app_id());
1390
1391 // Remove the pin position from preferences as needed. Do not remove positions
1392 // of ARC items removed due to ARC being disabled, see |keep_pin_positions_|.
1393 if (ItemTypeIsPinned(old_item) && !ignore_persist_pinned_state_change_ &&
1394 keep_pin_positions_.count(shelf_app_id) == 0) {
1395 ash::AppLaunchId app_launch_id(shelf_app_id,
1396 old_item.app_launch_id.launch_id());
James Cook 2017/03/29 14:28:02 Is it valid to recycle the launch_id when GetShelf
msw 2017/03/29 21:34:17 Yes, this translation is only done for arc::kPlayS
1397 ash::launcher::RemovePinPosition(profile(), app_launch_id);
1398 }
1399
1369 // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we 1400 // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we
1370 // get into this state in the first place. 1401 // get into this state in the first place.
1371 IDToItemControllerMap::iterator iter = 1402 if (id_to_item_controller_map_.count(old_item.id) > 0)
1372 id_to_item_controller_map_.find(old_item.id); 1403 id_to_item_controller_map_.erase(old_item.id);
1373 if (iter == id_to_item_controller_map_.end())
1374 return;
1375
1376 LOG(ERROR) << "Unexpected removal of shelf item, id: " << old_item.id;
1377 id_to_item_controller_map_.erase(iter);
1378 } 1404 }
1379 1405
1380 void ChromeLauncherControllerImpl::ShelfItemMoved(int start_index, 1406 void ChromeLauncherControllerImpl::ShelfItemMoved(int start_index,
1381 int target_index) { 1407 int target_index) {
1408 // Update the pin position preference as needed.
1382 const ash::ShelfItem& item = model_->items()[target_index]; 1409 const ash::ShelfItem& item = model_->items()[target_index];
1383 // We remember the moved item position if it is either pinnable or
1384 // it is the app list with the alternate shelf layout.
1385 DCHECK_NE(ash::TYPE_APP_LIST, item.type); 1410 DCHECK_NE(ash::TYPE_APP_LIST, item.type);
1386 if (IsPinned(item.id)) 1411 if (ItemTypeIsPinned(item) && !ignore_persist_pinned_state_change_)
1387 SyncPinPosition(item.id); 1412 SyncPinPosition(item.id);
1388 } 1413 }
1389 1414
1390 void ChromeLauncherControllerImpl::ShelfItemChanged( 1415 void ChromeLauncherControllerImpl::ShelfItemChanged(
1391 int index, 1416 int index,
1392 const ash::ShelfItem& old_item) {} 1417 const ash::ShelfItem& old_item) {
1418 if (ignore_persist_pinned_state_change_)
1419 return;
1420
1421 const ash::ShelfItem& item = model_->items()[index];
1422 // Add or remove the pin position from preferences as needed.
1423 if (!ItemTypeIsPinned(old_item) && ItemTypeIsPinned(item)) {
1424 SyncPinPosition(item.id);
1425 } else if (ItemTypeIsPinned(old_item) && !ItemTypeIsPinned(item)) {
1426 // TODO(khmel): Fix this Arc application id mapping. See http://b/31703859
1427 const std::string shelf_app_id =
1428 ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(
1429 old_item.app_launch_id.app_id());
1430
1431 ash::AppLaunchId app_launch_id(shelf_app_id,
1432 old_item.app_launch_id.launch_id());
1433 ash::launcher::RemovePinPosition(profile(), app_launch_id);
1434 }
1435 }
1393 1436
1394 void ChromeLauncherControllerImpl::OnSetShelfItemDelegate( 1437 void ChromeLauncherControllerImpl::OnSetShelfItemDelegate(
1395 ash::ShelfID id, 1438 ash::ShelfID id,
1396 ash::mojom::ShelfItemDelegate* item_delegate) { 1439 ash::mojom::ShelfItemDelegate* item_delegate) {
1397 // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we 1440 // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we
1398 // get into this state in the first place. 1441 // get into this state in the first place.
1399 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id); 1442 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
1400 if (iter == id_to_item_controller_map_.end() || item_delegate == iter->second) 1443 if (iter == id_to_item_controller_map_.end() || item_delegate == iter->second)
1401 return; 1444 return;
1402 LOG(ERROR) << "Unexpected change of shelf item delegate, id: " << id; 1445 LOG(ERROR) << "Unexpected change of shelf item delegate, id: " << id;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1449 LauncherItemController* controller = GetLauncherItemController(item.id); 1492 LauncherItemController* controller = GetLauncherItemController(item.id);
1450 if (!controller || controller->image_set_by_controller()) 1493 if (!controller || controller->image_set_by_controller())
1451 continue; 1494 continue;
1452 item.image = image; 1495 item.image = image;
1453 if (arc_deferred_launcher_) 1496 if (arc_deferred_launcher_)
1454 arc_deferred_launcher_->MaybeApplySpinningEffect(id, &item.image); 1497 arc_deferred_launcher_->MaybeApplySpinningEffect(id, &item.image);
1455 model_->Set(index, item); 1498 model_->Set(index, item);
1456 // It's possible we're waiting on more than one item, so don't break. 1499 // It's possible we're waiting on more than one item, so don't break.
1457 } 1500 }
1458 } 1501 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698