 Chromium Code Reviews
 Chromium Code Reviews Issue 2771663002:
  mash: Refactor ChromeLauncherController's ShelfDelegate code.  (Closed)
    
  
    Issue 2771663002:
  mash: Refactor ChromeLauncherController's ShelfDelegate code.  (Closed) 
  | Index: chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc | 
| diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc | 
| index 27283fd03dbdb64323eaac6cc332c69bd87eb336..615362e0802d3662ef4cda046fbdf1c9ce5d428d 100644 | 
| --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc | 
| +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc | 
| @@ -350,33 +350,9 @@ void ChromeLauncherControllerImpl::CloseLauncherItem(ash::ShelfID id) { | 
| } | 
| } | 
| -void ChromeLauncherControllerImpl::Pin(ash::ShelfID id) { | 
| - DCHECK(HasShelfIDToAppIDMapping(id)); | 
| +void ChromeLauncherControllerImpl::UnpinShelfItemInternal(ash::ShelfID id) { | 
| 
James Cook
2017/03/23 16:43:49
nit: move to match header order (it's short, I don
 
msw
2017/03/23 18:08:10
Left as-is. The ordering in this file is a mess...
 | 
| const ash::ShelfItem* item = GetItem(id); | 
| - if (item && item->type == ash::TYPE_APP) | 
| - SetItemType(id, ash::TYPE_PINNED_APP); | 
| - else if (!item || item->type != ash::TYPE_PINNED_APP) | 
| - return; | 
| - | 
| - SyncPinPosition(id); | 
| -} | 
| - | 
| -void ChromeLauncherControllerImpl::Unpin(ash::ShelfID id) { | 
| - UnpinAndUpdatePrefs(id, true /* update_prefs */); | 
| -} | 
| - | 
| -void ChromeLauncherControllerImpl::UnpinAndUpdatePrefs(ash::ShelfID id, | 
| - bool update_prefs) { | 
| LauncherItemController* controller = GetLauncherItemController(id); | 
| - CHECK(controller); | 
| - | 
| - if (update_prefs) { | 
| - ash::launcher::RemovePinPosition( | 
| - profile(), | 
| - ash::AppLaunchId(GetAppIDForShelfID(id), GetLaunchIDForShelfID(id))); | 
| - } | 
| - | 
| - const ash::ShelfItem* item = GetItem(id); | 
| if (item && (item->status != ash::STATUS_CLOSED || controller->locked())) | 
| UnpinRunningAppInternal(model_->ItemIndexByID(id)); | 
| else | 
| @@ -389,16 +365,6 @@ bool ChromeLauncherControllerImpl::IsPinned(ash::ShelfID id) { | 
| item->type == ash::TYPE_BROWSER_SHORTCUT); | 
| } | 
| -void ChromeLauncherControllerImpl::TogglePinned(ash::ShelfID id) { | 
| - if (!HasShelfIDToAppIDMapping(id)) | 
| - return; // May happen if item closed with menu open. | 
| - | 
| - if (IsPinned(id)) | 
| - Unpin(id); | 
| - else | 
| - Pin(id); | 
| -} | 
| - | 
| void ChromeLauncherControllerImpl::LockV1AppWithID(const std::string& app_id) { | 
| ash::ShelfID id = GetShelfIDForAppID(app_id); | 
| if (id == ash::kInvalidShelfID) { | 
| @@ -444,9 +410,6 @@ bool ChromeLauncherControllerImpl::IsOpen(ash::ShelfID id) { | 
| } | 
| bool ChromeLauncherControllerImpl::IsPlatformApp(ash::ShelfID id) { | 
| - if (!HasShelfIDToAppIDMapping(id)) | 
| - return false; | 
| - | 
| std::string app_id = GetAppIDForShelfID(id); | 
| const Extension* extension = GetExtensionForAppID(app_id, profile()); | 
| // An extension can be synced / updated at any time and therefore not be | 
| @@ -731,9 +694,8 @@ ChromeLauncherControllerImpl::GetBrowserShortcutLauncherItemController() { | 
| LauncherItemController* ChromeLauncherControllerImpl::GetLauncherItemController( | 
| const ash::ShelfID id) { | 
| - if (!HasShelfIDToAppIDMapping(id)) | 
| - return nullptr; | 
| - return id_to_item_controller_map_[id]; | 
| + IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id); | 
| + return iter == id_to_item_controller_map_.end() ? nullptr : iter->second; | 
| } | 
| bool ChromeLauncherControllerImpl::ShelfBoundsChangesProbablyWithUser( | 
| @@ -836,68 +798,91 @@ void ChromeLauncherControllerImpl::AttachProfile(Profile* profile_to_attach) { | 
| ash::ShelfID ChromeLauncherControllerImpl::GetShelfIDForAppID( | 
| const std::string& app_id) { | 
| - // Get shelf id for app_id and empty launch_id. | 
| + // Get shelf id for |app_id| and an empty |launch_id|. | 
| return GetShelfIDForAppIDAndLaunchID(app_id, std::string()); | 
| } | 
| ash::ShelfID ChromeLauncherControllerImpl::GetShelfIDForAppIDAndLaunchID( | 
| const std::string& app_id, | 
| 
James Cook
2017/03/23 16:43:49
Not for this CL: WDYT of converting this to use Ap
 
msw
2017/03/23 18:08:10
I'm very much in favor of that; I thought about do
 | 
| const std::string& launch_id) { | 
| + // TODO(khmel): Fix this Arc application id mapping. See http://b/31703859 | 
| const std::string shelf_app_id = | 
| ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(app_id); | 
| 
James Cook
2017/03/23 16:43:49
Wow, this is terrible. It implies that app_id is a
 
msw
2017/03/23 18:08:10
Yeah, this is a bad pattern. Yury said he'll work
 | 
| - for (const auto& id_to_item_controller_pair : id_to_item_controller_map_) { | 
| - if (id_to_item_controller_pair.second->app_id() == shelf_app_id && | 
| - id_to_item_controller_pair.second->launch_id() == launch_id) { | 
| - return id_to_item_controller_pair.first; | 
| + | 
| + for (const ash::ShelfItem& item : model_->items()) { | 
| + // Ash's ShelfWindowWatcher handles app panel windows separately. | 
| + if (item.type != ash::TYPE_APP_PANEL && | 
| + item.app_launch_id.app_id() == shelf_app_id && | 
| + item.app_launch_id.launch_id() == launch_id) { | 
| + return item.id; | 
| } | 
| } | 
| return ash::kInvalidShelfID; | 
| } | 
| -bool ChromeLauncherControllerImpl::HasShelfIDToAppIDMapping( | 
| - ash::ShelfID id) const { | 
| - return id_to_item_controller_map_.find(id) != | 
| - id_to_item_controller_map_.end(); | 
| -} | 
| - | 
| const std::string& ChromeLauncherControllerImpl::GetAppIDForShelfID( | 
| ash::ShelfID id) { | 
| - LauncherItemController* controller = GetLauncherItemController(id); | 
| - if (controller) | 
| - return controller->app_id(); | 
| ash::ShelfItems::const_iterator item = model_->ItemByID(id); | 
| return item != model_->items().end() ? item->app_launch_id.app_id() | 
| : base::EmptyString(); | 
| } | 
| void ChromeLauncherControllerImpl::PinAppWithID(const std::string& app_id) { | 
| + // TODO(khmel): Fix this Arc application id mapping. See http://b/31703859 | 
| const std::string shelf_app_id = | 
| ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(app_id); | 
| - if (GetPinnableForAppID(shelf_app_id, profile()) == | 
| - AppListControllerDelegate::PIN_EDITABLE) | 
| - DoPinAppWithID(shelf_app_id); | 
| - else | 
| - NOTREACHED(); | 
| + | 
| + // Requests to pin should only be be made for apps with editable pin states. | 
| + DCHECK_EQ(GetPinnableForAppID(shelf_app_id, profile()), | 
| + AppListControllerDelegate::PIN_EDITABLE); | 
| + | 
| + // If the app is already pinned, do nothing and return. | 
| + if (IsAppPinned(shelf_app_id)) | 
| + return; | 
| + | 
| + // If there is an existing item, convert that to a pinned item. | 
| + ash::ShelfID shelf_id = GetShelfIDForAppID(shelf_app_id); | 
| + if (shelf_id != ash::kInvalidShelfID) { | 
| + DCHECK_EQ(GetItem(shelf_id)->type, ash::TYPE_APP); | 
| + DCHECK(!GetItem(shelf_id)->pinned_by_policy); | 
| + SetItemType(shelf_id, ash::TYPE_PINNED_APP); | 
| 
James Cook
2017/03/23 16:43:50
Do you need to trigger sync after this?
 
msw
2017/03/23 18:08:10
Good catch! I missed that! Fixed (but maybe I ruin
 | 
| + return; | 
| + } | 
| + | 
| + // Create a new pinned item for the app. | 
| + shelf_id = CreateAppShortcutLauncherItem(ash::AppLaunchId(shelf_app_id), | 
| + model_->item_count()); | 
| + | 
| + // TODO(msw): Trigger pref updates in ShelfModelObserver overrides. | 
| + SyncPinPosition(shelf_id); | 
| } | 
| 
James Cook
2017/03/23 16:43:49
beautiful function, btw. I like the blocks with si
 
msw
2017/03/23 18:08:10
Acknowledged.
 | 
| bool ChromeLauncherControllerImpl::IsAppPinned(const std::string& app_id) { | 
| + // TODO(khmel): Fix this Arc application id mapping. See http://b/31703859 | 
| const std::string shelf_app_id = | 
| ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(app_id); | 
| - for (const auto& pair : id_to_item_controller_map_) { | 
| - if (IsPinned(pair.first) && pair.second->app_id() == shelf_app_id) | 
| - return true; | 
| - } | 
| - return false; | 
| + | 
| + return IsPinned(GetShelfIDForAppID(shelf_app_id)); | 
| } | 
| void ChromeLauncherControllerImpl::UnpinAppWithID(const std::string& app_id) { | 
| + // TODO(khmel): Fix this Arc application id mapping. See http://b/31703859 | 
| const std::string shelf_app_id = | 
| ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(app_id); | 
| - if (GetPinnableForAppID(shelf_app_id, profile()) == | 
| - AppListControllerDelegate::PIN_EDITABLE) | 
| - DoUnpinAppWithID(shelf_app_id, true /* update_prefs */); | 
| - else | 
| - NOTREACHED(); | 
| + | 
| + // Requests to unpin should only be be made for apps with editable pin states. | 
| + DCHECK_EQ(GetPinnableForAppID(shelf_app_id, profile()), | 
| + AppListControllerDelegate::PIN_EDITABLE); | 
| + | 
| + // If the app is already not pinned, do nothing and return. | 
| + if (!IsAppPinned(shelf_app_id)) | 
| + return; | 
| + | 
| + // TODO(msw): Trigger pref updates in ShelfModelObserver overrides. | 
| + ash::launcher::RemovePinPosition(profile(), ash::AppLaunchId(shelf_app_id)); | 
| + | 
| + // Unpin the shelf item. | 
| + UnpinShelfItemInternal(GetShelfIDForAppID(shelf_app_id)); | 
| } | 
| /////////////////////////////////////////////////////////////////////////////// | 
| @@ -932,15 +917,16 @@ void ChromeLauncherControllerImpl::OnAppUninstalledPrepared( | 
| // Since we might have windowed apps of this type which might have | 
| // outstanding locks which needs to be removed. | 
| const Profile* profile = Profile::FromBrowserContext(browser_context); | 
| - if (GetShelfIDForAppID(app_id)) | 
| + ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); | 
| + if (shelf_id != ash::kInvalidShelfID) | 
| CloseWindowedAppsFromRemovedExtension(app_id, profile); | 
| if (IsAppPinned(app_id)) { | 
| - if (profile == this->profile()) { | 
| - // Some apps may be removed locally. Don't remove pin position from sync | 
| - // model. When needed, it is automatically deleted on app list model | 
| - // update. | 
| - DoUnpinAppWithID(app_id, false /* update_prefs */); | 
| + if (profile == this->profile() && shelf_id != ash::kInvalidShelfID) { | 
| + // Some apps may be removed locally. Unpin the item without removing the | 
| + // pin position from profile preferences. When needed, it is automatically | 
| + // deleted on app list model update. | 
| + UnpinShelfItemInternal(shelf_id); | 
| } | 
| AppIconLoader* app_icon_loader = GetAppIconLoaderForApp(app_id); | 
| if (app_icon_loader) | 
| @@ -1032,30 +1018,6 @@ void ChromeLauncherControllerImpl::LauncherItemClosed(ash::ShelfID id) { | 
| model_->RemoveItemAt(index); | 
| } | 
| -void ChromeLauncherControllerImpl::DoPinAppWithID(const std::string& app_id) { | 
| - // If there is an item, do nothing and return. | 
| - if (IsAppPinned(app_id)) | 
| - return; | 
| - | 
| - ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); | 
| - if (shelf_id) { | 
| - // App item exists, pin it | 
| - Pin(shelf_id); | 
| - } else { | 
| - // Otherwise, create a shortcut item for it. | 
| - shelf_id = CreateAppShortcutLauncherItem(ash::AppLaunchId(app_id), | 
| - model_->item_count()); | 
| - SyncPinPosition(shelf_id); | 
| - } | 
| -} | 
| - | 
| -void ChromeLauncherControllerImpl::DoUnpinAppWithID(const std::string& app_id, | 
| - bool update_prefs) { | 
| - ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); | 
| - if (shelf_id && IsPinned(shelf_id)) | 
| - UnpinAndUpdatePrefs(shelf_id, update_prefs); | 
| -} | 
| - | 
| void ChromeLauncherControllerImpl::PinRunningAppInternal( | 
| int index, | 
| ash::ShelfID shelf_id) { | 
| @@ -1138,7 +1100,7 @@ void ChromeLauncherControllerImpl::ScheduleUpdateAppLaunchersFromPref() { | 
| void ChromeLauncherControllerImpl::UpdateAppLaunchersFromPref() { | 
| // There are various functions which will trigger a |SyncPinPosition| call | 
| - // like a direct call to |DoPinAppWithID|, or an indirect call to the menu | 
| + // like a direct call to |PinAppWithID|, or an indirect call to the menu | 
| // model which will use weights to re-arrange the icons to new positions. | 
| // Since this function is meant to synchronize the "is state" with the | 
| // "sync state", it makes no sense to store any changes by this function back | 
| @@ -1203,23 +1165,10 @@ void ChromeLauncherControllerImpl::UpdateAppLaunchersFromPref() { | 
| // At second step remove any pin to the right from the current index. | 
| while (index < model_->item_count()) { | 
| const ash::ShelfItem item = model_->items()[index]; | 
| - if (item.type != ash::TYPE_PINNED_APP) { | 
| + if (item.type == ash::TYPE_PINNED_APP) | 
| + UnpinShelfItemInternal(item.id); | 
| + else | 
| ++index; | 
| - continue; | 
| - } | 
| - | 
| - const LauncherItemController* controller = | 
| - GetLauncherItemController(item.id); | 
| - DCHECK(controller); | 
| - DCHECK_NE(controller->app_id(), extension_misc::kChromeAppId); | 
| - | 
| - if (item.status != ash::STATUS_CLOSED || controller->locked()) { | 
| - UnpinRunningAppInternal(index); | 
| - // Note, item can be moved to the right due weighting in shelf model. | 
| - DCHECK_GE(model_->ItemIndexByID(item.id), index); | 
| - } else { | 
| - LauncherItemClosed(item.id); | 
| - } | 
| } | 
| UpdatePolicyPinnedAppsFromPrefs(); | 
| @@ -1287,7 +1236,7 @@ ash::ShelfID ChromeLauncherControllerImpl::InsertAppLauncherItem( | 
| int index, | 
| ash::ShelfItemType shelf_item_type) { | 
| ash::ShelfID id = model_->next_id(); | 
| - CHECK(!HasShelfIDToAppIDMapping(id)); | 
| + CHECK(!GetItem(id)); | 
| CHECK(controller); | 
| // Ash's ShelfWindowWatcher handles app panel windows separately. | 
| DCHECK_NE(ash::TYPE_APP_PANEL, shelf_item_type); | 
| @@ -1325,6 +1274,8 @@ void ChromeLauncherControllerImpl::CreateBrowserShortcutLauncherItem() { | 
| ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 
| browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32); | 
| browser_shortcut.title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); | 
| + browser_shortcut.app_launch_id = | 
| + ash::AppLaunchId(extension_misc::kChromeAppId); | 
| ash::ShelfID id = model_->next_id(); | 
| model_->AddAt(0, browser_shortcut); | 
| BrowserShortcutLauncherItemController* controller = | 
| @@ -1432,7 +1383,7 @@ void ChromeLauncherControllerImpl::ShelfItemMoved(int start_index, | 
| // We remember the moved item position if it is either pinnable or | 
| // it is the app list with the alternate shelf layout. | 
| DCHECK_NE(ash::TYPE_APP_LIST, item.type); | 
| - if (HasShelfIDToAppIDMapping(item.id) && IsPinned(item.id)) | 
| + if (IsPinned(item.id)) | 
| SyncPinPosition(item.id); | 
| } |