1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/ui/ash/launcher/app_window_launcher_controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "apps/app_window.h"
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/shelf_util.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_util.h"
117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/stringprintf.h"
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/ui/host_desktop.h"
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "extensions/common/extension.h"
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/wm/public/activation_client.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using apps::AppWindow;
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string GetAppShelfId(AppWindow* app_window) {
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (app_window->window_type_is_panel())
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return base::StringPrintf("panel:%d", app_window->session_id().id());
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return app_window->extension_id();
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ControlsWindow(aura::Window* window) {
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return chrome::GetHostDesktopTypeForNativeWindow(window) ==
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)         chrome::HOST_DESKTOP_TYPE_ASH;
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AppWindowLauncherController::AppWindowLauncherController(
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChromeLauncherController* owner)
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : owner_(owner), activation_client_(NULL) {
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  apps::AppWindowRegistry* registry =
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      apps::AppWindowRegistry::Get(owner->profile());
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  registry_.insert(registry);
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  registry->AddObserver(this);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ash::Shell::HasInstance()) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ash::Shell::GetInstance()->GetPrimaryRootWindow()) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      activation_client_ = aura::client::GetActivationClient(
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ash::Shell::GetInstance()->GetPrimaryRootWindow());
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (activation_client_)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        activation_client_->AddObserver(this);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AppWindowLauncherController::~AppWindowLauncherController() {
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (std::set<apps::AppWindowRegistry*>::iterator it = registry_.begin();
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != registry_.end();
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       ++it)
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    (*it)->RemoveObserver(this);
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (activation_client_)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    activation_client_->RemoveObserver(this);
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (WindowToAppShelfIdMap::iterator iter =
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           window_to_app_shelf_id_map_.begin();
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       iter != window_to_app_shelf_id_map_.end();
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       ++iter) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iter->first->RemoveObserver(this);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppWindowLauncherController::AdditionalUserAddedToSession(
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Profile* profile) {
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // TODO(skuhne): This was added for the legacy side by side mode in M32. If
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // this mode gets no longer pursued this special case can be removed.
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (chrome::MultiUserWindowManager::GetMultiProfileMode() !=
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_MIXED)
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  apps::AppWindowRegistry* registry = apps::AppWindowRegistry::Get(profile);
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (registry_.find(registry) != registry_.end())
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  registry->AddObserver(this);
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  registry_.insert(registry);
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppWindowLauncherController::OnAppWindowIconChanged(
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AppWindow* app_window) {
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ControlsWindow(app_window->GetNativeWindow()))
901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const std::string app_shelf_id = GetAppShelfId(app_window);
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppControllerMap::iterator iter = app_controller_map_.find(app_shelf_id);
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (iter == app_controller_map_.end())
951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AppWindowLauncherItemController* controller = iter->second;
971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  controller->set_image_set_by_controller(true);
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  owner_->SetLauncherItemImage(controller->shelf_id(),
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               app_window->app_icon().AsImageSkia());
1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void AppWindowLauncherController::OnAppWindowShown(AppWindow* app_window) {
103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  aura::Window* window = app_window->GetNativeWindow();
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!ControlsWindow(window))
105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!IsRegisteredApp(window))
108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    RegisterApp(app_window);
109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void AppWindowLauncherController::OnAppWindowHidden(AppWindow* app_window) {
112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  aura::Window* window = app_window->GetNativeWindow();
113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!ControlsWindow(window))
114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (IsRegisteredApp(window))
117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    UnregisterApp(window);
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Called from aura::Window::~Window(), before delegate_->OnWindowDestroyed()
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// which destroys AppWindow, so both |window| and the associated AppWindow
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// are valid here.
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppWindowLauncherController::OnWindowDestroying(aura::Window* window) {
1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!ControlsWindow(window))
1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  UnregisterApp(window);
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppWindowLauncherController::OnWindowActivated(aura::Window* new_active,
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                    aura::Window* old_active) {
1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Make the newly active window the active (first) entry in the controller.
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AppWindowLauncherItemController* new_controller =
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ControllerForWindow(new_active);
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (new_controller) {
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    new_controller->SetActiveWindow(new_active);
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    owner_->SetItemStatus(new_controller->shelf_id(), ash::STATUS_ACTIVE);
1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Mark the old active window's launcher item as running (if different).
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AppWindowLauncherItemController* old_controller =
1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ControllerForWindow(old_active);
1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (old_controller && old_controller != new_controller)
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    owner_->SetItemStatus(old_controller->shelf_id(), ash::STATUS_RUNNING);
1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppWindowLauncherController::RegisterApp(AppWindow* app_window) {
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aura::Window* window = app_window->GetNativeWindow();
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Get the app's shelf identifier and add an entry to the map.
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(window_to_app_shelf_id_map_.find(window) ==
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         window_to_app_shelf_id_map_.end());
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const std::string app_shelf_id = GetAppShelfId(app_window);
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  window_to_app_shelf_id_map_[window] = app_shelf_id;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->AddObserver(this);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find or create an item controller and launcher item.
156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string app_id = app_window->extension_id();
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ash::ShelfItemStatus status = ash::wm::IsActiveWindow(window)
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    ? ash::STATUS_ACTIVE
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    : ash::STATUS_RUNNING;
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppControllerMap::iterator iter = app_controller_map_.find(app_shelf_id);
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ash::ShelfID shelf_id = 0;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter != app_controller_map_.end()) {
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    AppWindowLauncherItemController* controller = iter->second;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(controller->app_id() == app_id);
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    shelf_id = controller->shelf_id();
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    controller->AddAppWindow(app_window, status);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LauncherItemController::Type type =
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        app_window->window_type_is_panel()
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            ? LauncherItemController::TYPE_APP_PANEL
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            : LauncherItemController::TYPE_APP;
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    AppWindowLauncherItemController* controller =
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        new AppWindowLauncherItemController(type, app_shelf_id, app_id, owner_);
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    controller->AddAppWindow(app_window, status);
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If the app shelf id is not unique, and there is already a shelf
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // item for this app id (e.g. pinned), use that shelf item.
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (app_shelf_id == app_id)
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      shelf_id = owner_->GetShelfIDForAppID(app_id);
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (shelf_id == 0) {
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      shelf_id = owner_->CreateAppLauncherItem(controller, app_id, status);
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Restore any existing app icon and flag as set.
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const gfx::Image& app_icon = app_window->app_icon();
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!app_icon.IsEmpty()) {
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        owner_->SetLauncherItemImage(shelf_id, app_icon.AsImageSkia());
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        controller->set_image_set_by_controller(true);
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      owner_->SetItemController(shelf_id, controller);
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string app_shelf_id = GetAppShelfId(app_window);
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    app_controller_map_[app_shelf_id] = controller;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  owner_->SetItemStatus(shelf_id, status);
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ash::SetShelfIDForWindow(shelf_id, window);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppWindowLauncherController::UnregisterApp(aura::Window* window) {
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WindowToAppShelfIdMap::iterator iter1 =
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      window_to_app_shelf_id_map_.find(window);
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(iter1 != window_to_app_shelf_id_map_.end());
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string app_shelf_id = iter1->second;
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  window_to_app_shelf_id_map_.erase(iter1);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->RemoveObserver(this);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppControllerMap::iterator iter2 = app_controller_map_.find(app_shelf_id);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(iter2 != app_controller_map_.end());
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AppWindowLauncherItemController* controller = iter2->second;
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  controller->RemoveAppWindowForWindow(window);
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (controller->app_window_count() == 0) {
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If this is the last window associated with the app shelf id, close the
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // shelf item.
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ash::ShelfID shelf_id = controller->shelf_id();
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    owner_->CloseLauncherItem(shelf_id);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    app_controller_map_.erase(iter2);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool AppWindowLauncherController::IsRegisteredApp(aura::Window* window) {
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return window_to_app_shelf_id_map_.find(window) !=
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)         window_to_app_shelf_id_map_.end();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Private Methods
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AppWindowLauncherItemController*
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AppWindowLauncherController::ControllerForWindow(aura::Window* window) {
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WindowToAppShelfIdMap::iterator iter1 =
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      window_to_app_shelf_id_map_.find(window);
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (iter1 == window_to_app_shelf_id_map_.end())
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string app_shelf_id = iter1->second;
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AppControllerMap::iterator iter2 = app_controller_map_.find(app_shelf_id);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter2 == app_controller_map_.end())
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return iter2->second;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
237