multi_profile_app_window_launcher_controller.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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 "chrome/browser/profiles/profile.h" 9#include "chrome/browser/profiles/profile_manager.h" 10#include "chrome/browser/ui/ash/multi_user/multi_user_util.h" 11#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" 12#include "chrome/browser/ui/host_desktop.h" 13#include "extensions/browser/app_window/native_app_window.h" 14#include "ui/aura/window.h" 15 16namespace { 17 18bool ControlsWindow(aura::Window* window) { 19 return chrome::GetHostDesktopTypeForNativeWindow(window) == 20 chrome::HOST_DESKTOP_TYPE_ASH; 21} 22 23} // namespace 24 25MultiProfileAppWindowLauncherController:: 26 MultiProfileAppWindowLauncherController(ChromeLauncherController* owner) 27 : AppWindowLauncherController(owner) {} 28 29MultiProfileAppWindowLauncherController:: 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 38void 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 68void 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 76void 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 92void 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 115void 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 127void 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 143bool 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