- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / ash / launcher / shell_window_launcher_controller.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h"
6
7 #include "apps/shell_window.h"
8 #include "ash/shell.h"
9 #include "ash/wm/window_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
13 #include "chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.h"
14 #include "chrome/browser/ui/host_desktop.h"
15 #include "ui/aura/client/activation_client.h"
16 #include "ui/aura/root_window.h"
17
18 #if defined(OS_CHROMEOS)
19 #include "chrome/browser/ui/ash/multi_user_window_manager.h"
20 #endif
21
22 using apps::ShellWindow;
23
24 namespace {
25
26 std::string GetAppLauncherId(ShellWindow* shell_window) {
27   if (shell_window->window_type_is_panel())
28     return base::StringPrintf("panel:%d", shell_window->session_id().id());
29   return shell_window->extension()->id();
30 }
31
32 bool ControlsWindow(aura::Window* window) {
33   return chrome::GetHostDesktopTypeForNativeWindow(window) ==
34       chrome::HOST_DESKTOP_TYPE_ASH;
35 }
36
37 }  // namespace
38
39 ShellWindowLauncherController::ShellWindowLauncherController(
40     ChromeLauncherController* owner)
41     : owner_(owner),
42       activation_client_(NULL) {
43   apps::ShellWindowRegistry* registry =
44       apps::ShellWindowRegistry::Get(owner->profile());
45   registry_.insert(registry);
46   registry->AddObserver(this);
47   if (ash::Shell::HasInstance()) {
48     if (ash::Shell::GetInstance()->GetPrimaryRootWindow()) {
49       activation_client_ = aura::client::GetActivationClient(
50           ash::Shell::GetInstance()->GetPrimaryRootWindow());
51       if (activation_client_)
52         activation_client_->AddObserver(this);
53     }
54   }
55 }
56
57 ShellWindowLauncherController::~ShellWindowLauncherController() {
58   for (std::set<apps::ShellWindowRegistry*>::iterator it = registry_.begin();
59       it != registry_.end(); ++it)
60     (*it)->RemoveObserver(this);
61
62   if (activation_client_)
63     activation_client_->RemoveObserver(this);
64   for (WindowToAppLauncherIdMap::iterator iter =
65            window_to_app_launcher_id_map_.begin();
66        iter != window_to_app_launcher_id_map_.end(); ++iter) {
67     iter->first->RemoveObserver(this);
68   }
69 }
70
71 void ShellWindowLauncherController::AdditionalUserAddedToSession(
72     Profile* profile) {
73 #if defined(OS_CHROMEOS)
74   // TODO(skuhne): This was added for the legacy side by side mode in M32. If
75   // this mode gets no longer pursued this special case can be removed.
76   if (chrome::MultiUserWindowManager::GetMultiProfileMode() !=
77           chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_MIXED)
78     return;
79
80   apps::ShellWindowRegistry* registry = apps::ShellWindowRegistry::Get(profile);
81   if (registry_.find(registry) != registry_.end())
82     return;
83
84   registry->AddObserver(this);
85   registry_.insert(registry);
86 #endif
87 }
88
89 void ShellWindowLauncherController::OnShellWindowAdded(
90     ShellWindow* shell_window) {
91   if (!ControlsWindow(shell_window->GetNativeWindow()))
92     return;
93   RegisterApp(shell_window);
94 }
95
96 void ShellWindowLauncherController::OnShellWindowIconChanged(
97     ShellWindow* shell_window) {
98   if (!ControlsWindow(shell_window->GetNativeWindow()))
99     return;
100
101   const std::string app_launcher_id = GetAppLauncherId(shell_window);
102   AppControllerMap::iterator iter = app_controller_map_.find(app_launcher_id);
103   if (iter == app_controller_map_.end())
104     return;
105   ShellWindowLauncherItemController* controller = iter->second;
106   controller->set_image_set_by_controller(true);
107   owner_->SetLauncherItemImage(controller->launcher_id(),
108                                shell_window->app_icon().AsImageSkia());
109 }
110
111 void ShellWindowLauncherController::OnShellWindowRemoved(
112     ShellWindow* shell_window) {
113   // Do nothing here; shell_window->window() has already been deleted and
114   // OnWindowDestroying() has been called, doing the removal.
115 }
116
117 // Called from aura::Window::~Window(), before delegate_->OnWindowDestroyed()
118 // which destroys ShellWindow, so both |window| and the associated ShellWindow
119 // are valid here.
120 void ShellWindowLauncherController::OnWindowDestroying(aura::Window* window) {
121   if (!ControlsWindow(window))
122     return;
123   UnregisterApp(window);
124 }
125
126 void ShellWindowLauncherController::OnWindowActivated(
127     aura::Window* new_active,
128     aura::Window* old_active) {
129   // Make the newly active window the active (first) entry in the controller.
130   ShellWindowLauncherItemController* new_controller =
131       ControllerForWindow(new_active);
132   if (new_controller) {
133     new_controller->SetActiveWindow(new_active);
134     owner_->SetItemStatus(new_controller->launcher_id(), ash::STATUS_ACTIVE);
135   }
136
137   // Mark the old active window's launcher item as running (if different).
138   ShellWindowLauncherItemController* old_controller =
139       ControllerForWindow(old_active);
140   if (old_controller && old_controller != new_controller)
141     owner_->SetItemStatus(old_controller->launcher_id(), ash::STATUS_RUNNING);
142 }
143
144 void ShellWindowLauncherController::RegisterApp(ShellWindow* shell_window) {
145   aura::Window* window = shell_window->GetNativeWindow();
146   // Get the app's launcher identifier and add an entry to the map.
147   DCHECK(window_to_app_launcher_id_map_.find(window) ==
148          window_to_app_launcher_id_map_.end());
149   const std::string app_launcher_id = GetAppLauncherId(shell_window);
150   window_to_app_launcher_id_map_[window] = app_launcher_id;
151   window->AddObserver(this);
152
153   // Find or create an item controller and launcher item.
154   std::string app_id = shell_window->extension()->id();
155   ash::LauncherItemStatus status = ash::wm::IsActiveWindow(window) ?
156       ash::STATUS_ACTIVE : ash::STATUS_RUNNING;
157   AppControllerMap::iterator iter = app_controller_map_.find(app_launcher_id);
158   ash::LauncherID launcher_id = 0;
159   if (iter != app_controller_map_.end()) {
160     ShellWindowLauncherItemController* controller = iter->second;
161     DCHECK(controller->app_id() == app_id);
162     launcher_id = controller->launcher_id();
163     controller->AddShellWindow(shell_window, status);
164   } else {
165     LauncherItemController::Type type = shell_window->window_type_is_panel()
166         ? LauncherItemController::TYPE_APP_PANEL
167         : LauncherItemController::TYPE_APP;
168     ShellWindowLauncherItemController* controller =
169         new ShellWindowLauncherItemController(
170             type, app_launcher_id, app_id, owner_);
171     controller->AddShellWindow(shell_window, status);
172     // If the app launcher id is not unique, and there is already a launcher
173     // item for this app id (e.g. pinned), use that launcher item.
174     if (app_launcher_id == app_id)
175       launcher_id = owner_->GetLauncherIDForAppID(app_id);
176     if (launcher_id == 0)
177       launcher_id = owner_->CreateAppLauncherItem(controller, app_id, status);
178     else
179       owner_->SetItemController(launcher_id, controller);
180     const std::string app_launcher_id = GetAppLauncherId(shell_window);
181     app_controller_map_[app_launcher_id] = controller;
182   }
183   owner_->SetItemStatus(launcher_id, status);
184 }
185
186 void ShellWindowLauncherController::UnregisterApp(aura::Window* window) {
187   WindowToAppLauncherIdMap::iterator iter1 =
188       window_to_app_launcher_id_map_.find(window);
189   DCHECK(iter1 != window_to_app_launcher_id_map_.end());
190   std::string app_launcher_id = iter1->second;
191   window_to_app_launcher_id_map_.erase(iter1);
192   window->RemoveObserver(this);
193
194   AppControllerMap::iterator iter2 = app_controller_map_.find(app_launcher_id);
195   DCHECK(iter2 != app_controller_map_.end());
196   ShellWindowLauncherItemController* controller = iter2->second;
197   controller->RemoveShellWindowForWindow(window);
198   if (controller->shell_window_count() == 0) {
199     // If this is the last window associated with the app launcher id, close the
200     // launcher item.
201     ash::LauncherID launcher_id = controller->launcher_id();
202     owner_->CloseLauncherItem(launcher_id);
203     app_controller_map_.erase(iter2);
204   }
205 }
206
207 bool ShellWindowLauncherController::IsRegisteredApp(aura::Window* window) {
208   return window_to_app_launcher_id_map_.find(window) !=
209       window_to_app_launcher_id_map_.end();
210 }
211
212 // Private Methods
213
214 ShellWindowLauncherItemController*
215 ShellWindowLauncherController::ControllerForWindow(
216     aura::Window* window) {
217   WindowToAppLauncherIdMap::iterator iter1 =
218       window_to_app_launcher_id_map_.find(window);
219   if (iter1 == window_to_app_launcher_id_map_.end())
220     return NULL;
221   std::string app_launcher_id = iter1->second;
222   AppControllerMap::iterator iter2 = app_controller_map_.find(app_launcher_id);
223   if (iter2 == app_controller_map_.end())
224     return NULL;
225   return iter2->second;
226 }