• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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/multi_profile_app_window_launcher_controller.h"
6 
7 #include "apps/app_window.h"
8 #include "apps/ui/native_app_window.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/profiles/profile_manager.h"
11 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
12 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
13 #include "chrome/browser/ui/host_desktop.h"
14 #include "ui/aura/window.h"
15 
16 namespace {
17 
ControlsWindow(aura::Window * window)18 bool ControlsWindow(aura::Window* window) {
19   return chrome::GetHostDesktopTypeForNativeWindow(window) ==
20          chrome::HOST_DESKTOP_TYPE_ASH;
21 }
22 
23 }  // namespace
24 
25 MultiProfileAppWindowLauncherController::
MultiProfileAppWindowLauncherController(ChromeLauncherController * owner)26     MultiProfileAppWindowLauncherController(ChromeLauncherController* owner)
27     : AppWindowLauncherController(owner) {}
28 
29 MultiProfileAppWindowLauncherController::
~MultiProfileAppWindowLauncherController()30     ~MultiProfileAppWindowLauncherController() {
31   // We need to remove all Registry observers for added users.
32   for (AppWindowRegistryList::iterator it = multi_user_registry_.begin();
33        it != multi_user_registry_.end();
34        ++it)
35     (*it)->RemoveObserver(this);
36 }
37 
ActiveUserChanged(const std::string & user_email)38 void MultiProfileAppWindowLauncherController::ActiveUserChanged(
39     const std::string& user_email) {
40   // The active user has changed and we need to traverse our list of items to
41   // show / hide them one by one. To avoid that a user dependent state
42   // "survives" in a launcher item, we first delete all items making sure that
43   // nothing remains and then re-create them again.
44   for (AppWindowList::iterator it = app_window_list_.begin();
45        it != app_window_list_.end();
46        ++it) {
47     apps::AppWindow* app_window = *it;
48     Profile* profile =
49         Profile::FromBrowserContext(app_window->browser_context());
50     if (!multi_user_util::IsProfileFromActiveUser(profile) &&
51         IsRegisteredApp(app_window->GetNativeWindow()))
52       UnregisterApp(app_window->GetNativeWindow());
53   }
54   for (AppWindowList::iterator it = app_window_list_.begin();
55        it != app_window_list_.end();
56        ++it) {
57     apps::AppWindow* app_window = *it;
58     Profile* profile =
59         Profile::FromBrowserContext(app_window->browser_context());
60     if (multi_user_util::IsProfileFromActiveUser(profile) &&
61         !IsRegisteredApp(app_window->GetNativeWindow()) &&
62         (app_window->GetBaseWindow()->IsMinimized() ||
63          app_window->GetNativeWindow()->IsVisible()))
64       RegisterApp(*it);
65   }
66 }
67 
AdditionalUserAddedToSession(Profile * profile)68 void MultiProfileAppWindowLauncherController::AdditionalUserAddedToSession(
69     Profile* profile) {
70   // Each users AppWindowRegistry needs to be observed.
71   apps::AppWindowRegistry* registry = apps::AppWindowRegistry::Get(profile);
72   multi_user_registry_.push_back(registry);
73   registry->AddObserver(this);
74 }
75 
OnAppWindowAdded(apps::AppWindow * app_window)76 void MultiProfileAppWindowLauncherController::OnAppWindowAdded(
77     apps::AppWindow* app_window) {
78   if (!ControlsWindow(app_window->GetNativeWindow()))
79     return;
80 
81   app_window_list_.push_back(app_window);
82   Profile* profile = Profile::FromBrowserContext(app_window->browser_context());
83   // If the window got created for a non active user but the user allowed to
84   // teleport to the current user's desktop, we teleport it now.
85   if (!multi_user_util::IsProfileFromActiveUser(profile) &&
86       UserHasAppOnActiveDesktop(app_window)) {
87     chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser(
88         app_window->GetNativeWindow(), multi_user_util::GetCurrentUserId());
89   }
90 }
91 
OnAppWindowShown(apps::AppWindow * app_window)92 void MultiProfileAppWindowLauncherController::OnAppWindowShown(
93     apps::AppWindow* app_window) {
94   if (!ControlsWindow(app_window->GetNativeWindow()))
95     return;
96 
97   Profile* profile = Profile::FromBrowserContext(app_window->browser_context());
98 
99   if (multi_user_util::IsProfileFromActiveUser(profile) &&
100       !IsRegisteredApp(app_window->GetNativeWindow())) {
101     RegisterApp(app_window);
102     return;
103   }
104 
105   // The panel layout manager only manages windows which are anchored.
106   // Since this window did never had an anchor, it would stay hidden. We
107   // therefore make it visible now.
108   if (UserHasAppOnActiveDesktop(app_window) &&
109       app_window->GetNativeWindow()->type() == ui::wm::WINDOW_TYPE_PANEL &&
110       !app_window->GetNativeWindow()->layer()->GetTargetOpacity()) {
111     app_window->GetNativeWindow()->layer()->SetOpacity(1.0f);
112   }
113 }
114 
OnAppWindowHidden(apps::AppWindow * app_window)115 void MultiProfileAppWindowLauncherController::OnAppWindowHidden(
116     apps::AppWindow* app_window) {
117   if (!ControlsWindow(app_window->GetNativeWindow()))
118     return;
119 
120   Profile* profile = Profile::FromBrowserContext(app_window->browser_context());
121   if (multi_user_util::IsProfileFromActiveUser(profile) &&
122       IsRegisteredApp(app_window->GetNativeWindow())) {
123     UnregisterApp(app_window->GetNativeWindow());
124   }
125 }
126 
OnAppWindowRemoved(apps::AppWindow * app_window)127 void MultiProfileAppWindowLauncherController::OnAppWindowRemoved(
128     apps::AppWindow* app_window) {
129   if (!ControlsWindow(app_window->GetNativeWindow()))
130     return;
131 
132   // If the application is registered with AppWindowLauncher (because the user
133   // is currently active), the OnWindowDestroying observer has already (or will
134   // soon) unregister it independently from the shelf. If it was not registered
135   // we don't need to do anything anyways. As such, all which is left to do here
136   // is to get rid of our own reference.
137   AppWindowList::iterator it =
138       std::find(app_window_list_.begin(), app_window_list_.end(), app_window);
139   DCHECK(it != app_window_list_.end());
140   app_window_list_.erase(it);
141 }
142 
UserHasAppOnActiveDesktop(apps::AppWindow * app_window)143 bool MultiProfileAppWindowLauncherController::UserHasAppOnActiveDesktop(
144     apps::AppWindow* app_window) {
145   const std::string& app_id = app_window->extension_id();
146   content::BrowserContext* app_context = app_window->browser_context();
147   DCHECK(!app_context->IsOffTheRecord());
148   const std::string& current_user = multi_user_util::GetCurrentUserId();
149   chrome::MultiUserWindowManager* manager =
150       chrome::MultiUserWindowManager::GetInstance();
151   for (AppWindowList::iterator it = app_window_list_.begin();
152        it != app_window_list_.end();
153        ++it) {
154     apps::AppWindow* other_window = *it;
155     DCHECK(!other_window->browser_context()->IsOffTheRecord());
156     if (manager->IsWindowOnDesktopOfUser(other_window->GetNativeWindow(),
157                                          current_user) &&
158         app_id == other_window->extension_id() &&
159         app_context == other_window->browser_context()) {
160       return true;
161     }
162   }
163   return false;
164 }
165