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