| 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 edf788e835568f09ababe7ba00551395ec753a6f..e3036fab9256c0612671fbb88b2f1d24e52baa1a 100644
|
| --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
|
| +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
|
| @@ -90,7 +90,6 @@
|
| #include "ui/wm/core/window_animations.h"
|
|
|
| using extensions::Extension;
|
| -using extension_misc::kChromeAppId;
|
| using extension_misc::kGmailAppId;
|
| using content::WebContents;
|
|
|
| @@ -275,6 +274,14 @@
|
| model_->RemoveObserver(this);
|
| if (ash::Shell::HasInstance())
|
| ash::Shell::Get()->window_tree_host_manager()->RemoveObserver(this);
|
| + for (const auto& pair : id_to_item_controller_map_) {
|
| + int index = model_->ItemIndexByID(pair.first);
|
| + // A "browser proxy" is not known to the model and this removal does
|
| + // therefore not need to be propagated to the model.
|
| + if (index != -1 &&
|
| + model_->items()[index].type != ash::TYPE_BROWSER_SHORTCUT)
|
| + model_->RemoveItemAt(index);
|
| + }
|
|
|
| // Release all profile dependent resources.
|
| ReleaseProfile();
|
| @@ -318,15 +325,26 @@
|
| }
|
| }
|
|
|
| +void ChromeLauncherControllerImpl::SetShelfItemDelegate(
|
| + ash::ShelfID id,
|
| + std::unique_ptr<ash::ShelfItemDelegate> item_delegate) {
|
| + CHECK(item_delegate);
|
| + IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
|
| + CHECK(iter != id_to_item_controller_map_.end());
|
| + item_delegate->set_shelf_id(id);
|
| + iter->second = item_delegate.get();
|
| + model_->SetShelfItemDelegate(id, std::move(item_delegate));
|
| +}
|
| +
|
| void ChromeLauncherControllerImpl::CloseLauncherItem(ash::ShelfID id) {
|
| CHECK(id);
|
| if (IsPinned(id)) {
|
| // Create a new shortcut delegate.
|
| SetItemStatus(id, ash::STATUS_CLOSED);
|
| - model_->SetShelfItemDelegate(id, AppShortcutLauncherItemController::Create(
|
| - GetItem(id)->app_launch_id));
|
| + SetShelfItemDelegate(id, AppShortcutLauncherItemController::Create(
|
| + GetItem(id)->app_launch_id));
|
| } else {
|
| - RemoveShelfItem(id);
|
| + LauncherItemClosed(id);
|
| }
|
| }
|
|
|
| @@ -335,7 +353,7 @@
|
| if (item && item->status != ash::STATUS_CLOSED)
|
| UnpinRunningAppInternal(model_->ItemIndexByID(id));
|
| else
|
| - RemoveShelfItem(id);
|
| + LauncherItemClosed(id);
|
| }
|
|
|
| bool ChromeLauncherControllerImpl::IsPinned(ash::ShelfID id) {
|
| @@ -349,7 +367,7 @@
|
| const ash::ShelfItem* item = GetItem(id);
|
| if (item) {
|
| if (!IsPinned(id) && status == ash::STATUS_CLOSED)
|
| - RemoveShelfItem(id);
|
| + LauncherItemClosed(id);
|
| else
|
| SetItemStatus(id, status);
|
| } else if (status != ash::STATUS_CLOSED && !app_id.empty()) {
|
| @@ -360,7 +378,7 @@
|
| }
|
|
|
| void ChromeLauncherControllerImpl::Launch(ash::ShelfID id, int event_flags) {
|
| - ash::ShelfItemDelegate* delegate = model_->GetShelfItemDelegate(id);
|
| + ash::ShelfItemDelegate* delegate = GetShelfItemDelegate(id);
|
| if (!delegate)
|
| return; // In case invoked from menu and item closed while menu up.
|
|
|
| @@ -463,13 +481,21 @@
|
|
|
| ash::ShelfID ChromeLauncherControllerImpl::GetShelfIDForWebContents(
|
| content::WebContents* contents) {
|
| + DCHECK(contents);
|
| +
|
| std::string app_id = launcher_controller_helper()->GetAppID(contents);
|
| +
|
| if (app_id.empty() && ContentCanBeHandledByGmailApp(contents))
|
| app_id = kGmailAppId;
|
|
|
| ash::ShelfID id = GetShelfIDForAppID(app_id);
|
| - // If there is no dedicated app item, use the browser shortcut item.
|
| - return id == ash::kInvalidShelfID ? GetShelfIDForAppID(kChromeAppId) : id;
|
| +
|
| + if (app_id.empty() || !id) {
|
| + int browser_index = model_->GetItemIndexForType(ash::TYPE_BROWSER_SHORTCUT);
|
| + return model_->items()[browser_index].id;
|
| + }
|
| +
|
| + return id;
|
| }
|
|
|
| void ChromeLauncherControllerImpl::SetRefocusURLPatternForTest(
|
| @@ -478,9 +504,9 @@
|
| const ash::ShelfItem* item = GetItem(id);
|
| if (item && !IsPlatformApp(id) &&
|
| (item->type == ash::TYPE_PINNED_APP || item->type == ash::TYPE_APP)) {
|
| - ash::ShelfItemDelegate* delegate = model_->GetShelfItemDelegate(id);
|
| + ash::ShelfItemDelegate* item_delegate = GetShelfItemDelegate(id);
|
| AppShortcutLauncherItemController* item_controller =
|
| - static_cast<AppShortcutLauncherItemController*>(delegate);
|
| + static_cast<AppShortcutLauncherItemController*>(item_delegate);
|
| item_controller->set_refocus_url(url);
|
| } else {
|
| NOTREACHED() << "Invalid launcher item or type";
|
| @@ -557,9 +583,9 @@
|
|
|
| ash::MenuItemList ChromeLauncherControllerImpl::GetAppMenuItemsForTesting(
|
| const ash::ShelfItem& item) {
|
| - ash::ShelfItemDelegate* delegate = model_->GetShelfItemDelegate(item.id);
|
| - return delegate ? delegate->GetAppMenuItems(ui::EF_NONE)
|
| - : ash::MenuItemList();
|
| + ash::ShelfItemDelegate* item_delegate = GetShelfItemDelegate(item.id);
|
| + return item_delegate ? item_delegate->GetAppMenuItems(ui::EF_NONE)
|
| + : ash::MenuItemList();
|
| }
|
|
|
| std::vector<content::WebContents*>
|
| @@ -569,9 +595,9 @@
|
| // If there is no such item pinned to the launcher, no menu gets created.
|
| if (!item || item->type != ash::TYPE_PINNED_APP)
|
| return std::vector<content::WebContents*>();
|
| - ash::ShelfItemDelegate* delegate = model_->GetShelfItemDelegate(item->id);
|
| + ash::ShelfItemDelegate* item_delegate = GetShelfItemDelegate(item->id);
|
| AppShortcutLauncherItemController* item_controller =
|
| - static_cast<AppShortcutLauncherItemController*>(delegate);
|
| + static_cast<AppShortcutLauncherItemController*>(item_delegate);
|
| return item_controller->GetRunningApplications();
|
| }
|
|
|
| @@ -580,9 +606,9 @@
|
| const ash::ShelfItem* item = GetItem(GetShelfIDForAppID(app_id));
|
| if (item &&
|
| (item->type == ash::TYPE_APP || item->type == ash::TYPE_PINNED_APP)) {
|
| - ash::ShelfItemDelegate* delegate = model_->GetShelfItemDelegate(item->id);
|
| + ash::ShelfItemDelegate* item_delegate = GetShelfItemDelegate(item->id);
|
| AppWindowLauncherItemController* item_controller =
|
| - delegate->AsAppWindowLauncherItemController();
|
| + item_delegate->AsAppWindowLauncherItemController();
|
| item_controller->ActivateIndexedApp(window_index);
|
| }
|
| }
|
| @@ -646,10 +672,20 @@
|
|
|
| BrowserShortcutLauncherItemController*
|
| ChromeLauncherControllerImpl::GetBrowserShortcutLauncherItemController() {
|
| - ash::ShelfID id = GetShelfIDForAppID(kChromeAppId);
|
| - ash::mojom::ShelfItemDelegate* delegate = model_->GetShelfItemDelegate(id);
|
| - DCHECK(delegate) << "There should be always be a browser shortcut item.";
|
| - return static_cast<BrowserShortcutLauncherItemController*>(delegate);
|
| + for (const auto& pair : id_to_item_controller_map_) {
|
| + const ash::ShelfItem* item = GetItem(pair.first);
|
| + if (item && item->type == ash::TYPE_BROWSER_SHORTCUT)
|
| + return static_cast<BrowserShortcutLauncherItemController*>(pair.second);
|
| + }
|
| + NOTREACHED()
|
| + << "There should be always be a BrowserShortcutLauncherItemController.";
|
| + return nullptr;
|
| +}
|
| +
|
| +ash::ShelfItemDelegate* ChromeLauncherControllerImpl::GetShelfItemDelegate(
|
| + const ash::ShelfID 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(
|
| @@ -690,7 +726,7 @@
|
|
|
| const std::string& ChromeLauncherControllerImpl::GetLaunchIDForShelfID(
|
| ash::ShelfID id) {
|
| - ash::ShelfItemDelegate* delegate = model_->GetShelfItemDelegate(id);
|
| + ash::ShelfItemDelegate* delegate = GetShelfItemDelegate(id);
|
| return delegate ? delegate->launch_id() : base::EmptyString();
|
| }
|
|
|
| @@ -762,8 +798,6 @@
|
| // TODO(khmel): Fix this Arc application id mapping. See http://b/31703859
|
| const std::string shelf_app_id =
|
| ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(app_id);
|
| - if (shelf_app_id.empty())
|
| - return ash::kInvalidShelfID;
|
|
|
| for (const ash::ShelfItem& item : model_->items()) {
|
| // Ash's ShelfWindowWatcher handles app panel windows separately.
|
| @@ -937,12 +971,16 @@
|
| }
|
| }
|
|
|
| -void ChromeLauncherControllerImpl::RemoveShelfItem(ash::ShelfID id) {
|
| - const std::string& app_id = GetAppIDForShelfID(id);
|
| +void ChromeLauncherControllerImpl::LauncherItemClosed(ash::ShelfID id) {
|
| + IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
|
| + CHECK(iter != id_to_item_controller_map_.end());
|
| + CHECK(iter->second);
|
| + const std::string& app_id = iter->second->app_id();
|
| AppIconLoader* app_icon_loader = GetAppIconLoaderForApp(app_id);
|
| if (app_icon_loader)
|
| app_icon_loader->ClearImage(app_id);
|
| - const int index = model_->ItemIndexByID(id);
|
| + id_to_item_controller_map_.erase(iter);
|
| + int index = model_->ItemIndexByID(id);
|
| // A "browser proxy" is not known to the model and this removal does
|
| // therefore not need to be propagated to the model.
|
| if (index != -1)
|
| @@ -1062,15 +1100,19 @@
|
| int app_index = index;
|
| for (; app_index < model_->item_count(); ++app_index) {
|
| const ash::ShelfItem& item = model_->items()[app_index];
|
| - if (item.app_launch_id.app_id() == app_id &&
|
| - item.app_launch_id.launch_id() == pref_app_launch_id.launch_id()) {
|
| + const IDToItemControllerMap::iterator it =
|
| + id_to_item_controller_map_.find(item.id);
|
| + if (it != id_to_item_controller_map_.end() &&
|
| + it->second->app_id() == app_id &&
|
| + it->second->launch_id() == pref_app_launch_id.launch_id()) {
|
| break;
|
| }
|
| }
|
| if (app_index < model_->item_count()) {
|
| // Found existing pin or running app.
|
| const ash::ShelfItem item = model_->items()[app_index];
|
| - if (ItemTypeIsPinned(item)) {
|
| + if (item.type == ash::TYPE_PINNED_APP ||
|
| + item.type == ash::TYPE_BROWSER_SHORTCUT) {
|
| // Just move to required position or keep it inplace.
|
| model_->Move(app_index, index);
|
| } else {
|
| @@ -1079,7 +1121,7 @@
|
| DCHECK_EQ(model_->ItemIndexByID(item.id), index);
|
| } else {
|
| // This is fresh pin. Create new one.
|
| - DCHECK_NE(app_id, kChromeAppId);
|
| + DCHECK_NE(app_id, extension_misc::kChromeAppId);
|
| CreateAppShortcutLauncherItem(pref_app_launch_id, index);
|
| }
|
| ++index;
|
| @@ -1163,6 +1205,8 @@
|
| CHECK(item_delegate);
|
| // Ash's ShelfWindowWatcher handles app panel windows separately.
|
| DCHECK_NE(ash::TYPE_APP_PANEL, shelf_item_type);
|
| + id_to_item_controller_map_[id] = item_delegate.get();
|
| + item_delegate->set_shelf_id(id);
|
|
|
| ash::ShelfItem item;
|
| item.type = shelf_item_type;
|
| @@ -1200,12 +1244,15 @@
|
| 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(kChromeAppId);
|
| + browser_shortcut.app_launch_id =
|
| + ash::AppLaunchId(extension_misc::kChromeAppId);
|
| ash::ShelfID id = model_->next_id();
|
| model_->AddAt(0, browser_shortcut);
|
| std::unique_ptr<BrowserShortcutLauncherItemController> item_delegate =
|
| base::MakeUnique<BrowserShortcutLauncherItemController>(model_);
|
| BrowserShortcutLauncherItemController* item_controller = item_delegate.get();
|
| + item_controller->set_shelf_id(id);
|
| + id_to_item_controller_map_[id] = item_controller;
|
| model_->SetShelfItemDelegate(id, std::move(item_delegate));
|
| item_controller->UpdateBrowserItemState();
|
| }
|
| @@ -1219,8 +1266,11 @@
|
| }
|
|
|
| int ChromeLauncherControllerImpl::FindInsertionPoint() {
|
| + DCHECK_GT(model_->item_count(), 0);
|
| for (int i = model_->item_count() - 1; i > 0; --i) {
|
| - if (ItemTypeIsPinned(model_->items()[i]))
|
| + ash::ShelfItemType type = model_->items()[i].type;
|
| + DCHECK_NE(ash::TYPE_APP_LIST, type);
|
| + if (type == ash::TYPE_PINNED_APP || type == ash::TYPE_BROWSER_SHORTCUT)
|
| return i;
|
| }
|
| return 0;
|
| @@ -1294,6 +1344,11 @@
|
| old_item.app_launch_id.launch_id());
|
| ash::launcher::RemovePinPosition(profile(), app_launch_id);
|
| }
|
| +
|
| + // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we
|
| + // get into this state in the first place.
|
| + if (id_to_item_controller_map_.count(old_item.id) > 0)
|
| + id_to_item_controller_map_.erase(old_item.id);
|
| }
|
|
|
| void ChromeLauncherControllerImpl::ShelfItemMoved(int start_index,
|
| @@ -1327,6 +1382,18 @@
|
| }
|
| }
|
|
|
| +void ChromeLauncherControllerImpl::OnSetShelfItemDelegate(
|
| + ash::ShelfID id,
|
| + ash::ShelfItemDelegate* item_delegate) {
|
| + // TODO(skuhne): This fixes crbug.com/429870, but it does not answer why we
|
| + // get into this state in the first place.
|
| + IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
|
| + if (iter == id_to_item_controller_map_.end() || item_delegate == iter->second)
|
| + return;
|
| + LOG(ERROR) << "Unexpected change of shelf item delegate, id: " << id;
|
| + id_to_item_controller_map_.erase(iter);
|
| +}
|
| +
|
| ///////////////////////////////////////////////////////////////////////////////
|
| // ash::WindowTreeHostManager::Observer:
|
|
|
| @@ -1363,20 +1430,19 @@
|
| // AppIconLoaderDelegate:
|
|
|
| void ChromeLauncherControllerImpl::OnAppImageUpdated(
|
| - const std::string& app_id,
|
| + const std::string& id,
|
| const gfx::ImageSkia& image) {
|
| // TODO: need to get this working for shortcuts.
|
| for (int index = 0; index < model_->item_count(); ++index) {
|
| ash::ShelfItem item = model_->items()[index];
|
| - ash::ShelfItemDelegate* delegate = model_->GetShelfItemDelegate(item.id);
|
| - if (item.type == ash::TYPE_APP_PANEL || !delegate ||
|
| - delegate->image_set_by_controller() ||
|
| - item.app_launch_id.app_id() != app_id) {
|
| + if (GetAppIDForShelfID(item.id) != id)
|
| continue;
|
| - }
|
| + ash::ShelfItemDelegate* delegate = GetShelfItemDelegate(item.id);
|
| + if (!delegate || delegate->image_set_by_controller())
|
| + continue;
|
| item.image = image;
|
| if (arc_deferred_launcher_)
|
| - arc_deferred_launcher_->MaybeApplySpinningEffect(app_id, &item.image);
|
| + arc_deferred_launcher_->MaybeApplySpinningEffect(id, &item.image);
|
| model_->Set(index, item);
|
| // It's possible we're waiting on more than one item, so don't break.
|
| }
|
|
|