1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// found in the LICENSE file. 41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/ui/ash/launcher/multi_profile_app_window_launcher_controller.h" 61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "apps/app_window.h" 8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "apps/ui/native_app_window.h" 91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h" 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/ash/multi_user/multi_user_util.h" 12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" 131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/ui/host_desktop.h" 14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/aura/window.h" 151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace { 171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ControlsWindow(aura::Window* window) { 191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return chrome::GetHostDesktopTypeForNativeWindow(window) == 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome::HOST_DESKTOP_TYPE_ASH; 211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} // namespace 241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MultiProfileAppWindowLauncherController:: 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MultiProfileAppWindowLauncherController(ChromeLauncherController* owner) 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : AppWindowLauncherController(owner) {} 281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MultiProfileAppWindowLauncherController:: 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ~MultiProfileAppWindowLauncherController() { 311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // We need to remove all Registry observers for added users. 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AppWindowRegistryList::iterator it = multi_user_registry_.begin(); 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != multi_user_registry_.end(); 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) 351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) (*it)->RemoveObserver(this); 361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MultiProfileAppWindowLauncherController::ActiveUserChanged( 391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::string& user_email) { 401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // The active user has changed and we need to traverse our list of items to 411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // show / hide them one by one. To avoid that a user dependent state 421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // "survives" in a launcher item, we first delete all items making sure that 431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // nothing remains and then re-create them again. 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AppWindowList::iterator it = app_window_list_.begin(); 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != app_window_list_.end(); 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps::AppWindow* app_window = *it; 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile = 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile::FromBrowserContext(app_window->browser_context()); 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!multi_user_util::IsProfileFromActiveUser(profile) && 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IsRegisteredApp(app_window->GetNativeWindow())) 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UnregisterApp(app_window->GetNativeWindow()); 531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AppWindowList::iterator it = app_window_list_.begin(); 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != app_window_list_.end(); 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps::AppWindow* app_window = *it; 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile = 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile::FromBrowserContext(app_window->browser_context()); 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (multi_user_util::IsProfileFromActiveUser(profile) && 61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) !IsRegisteredApp(app_window->GetNativeWindow()) && 62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) (app_window->GetBaseWindow()->IsMinimized() || 63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) app_window->GetNativeWindow()->IsVisible())) 641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) RegisterApp(*it); 651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MultiProfileAppWindowLauncherController::AdditionalUserAddedToSession( 691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Profile* profile) { 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Each users AppWindowRegistry needs to be observed. 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps::AppWindowRegistry* registry = apps::AppWindowRegistry::Get(profile); 721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) multi_user_registry_.push_back(registry); 731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) registry->AddObserver(this); 741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MultiProfileAppWindowLauncherController::OnAppWindowAdded( 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps::AppWindow* app_window) { 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ControlsWindow(app_window->GetNativeWindow())) 791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return; 80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_window_list_.push_back(app_window); 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); 83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // If the window got created for a non active user but the user allowed to 84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // teleport to the current user's desktop, we teleport it now. 85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!multi_user_util::IsProfileFromActiveUser(profile) && 86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) UserHasAppOnActiveDesktop(app_window)) { 87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser( 88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) app_window->GetNativeWindow(), multi_user_util::GetCurrentUserId()); 89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MultiProfileAppWindowLauncherController::OnAppWindowShown( 93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) apps::AppWindow* app_window) { 94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!ControlsWindow(app_window->GetNativeWindow())) 95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); 98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (multi_user_util::IsProfileFromActiveUser(profile) && 100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) !IsRegisteredApp(app_window->GetNativeWindow())) { 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RegisterApp(app_window); 102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The panel layout manager only manages windows which are anchored. 106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Since this window did never had an anchor, it would stay hidden. We 107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // therefore make it visible now. 108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (UserHasAppOnActiveDesktop(app_window) && 109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) app_window->GetNativeWindow()->type() == ui::wm::WINDOW_TYPE_PANEL && 110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) !app_window->GetNativeWindow()->layer()->GetTargetOpacity()) { 111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) app_window->GetNativeWindow()->layer()->SetOpacity(1.0f); 112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void MultiProfileAppWindowLauncherController::OnAppWindowHidden( 116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) apps::AppWindow* app_window) { 117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!ControlsWindow(app_window->GetNativeWindow())) 118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); 121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (multi_user_util::IsProfileFromActiveUser(profile) && 122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) IsRegisteredApp(app_window->GetNativeWindow())) { 123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) UnregisterApp(app_window->GetNativeWindow()); 124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MultiProfileAppWindowLauncherController::OnAppWindowRemoved( 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps::AppWindow* app_window) { 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ControlsWindow(app_window->GetNativeWindow())) 1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return; 1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If the application is registered with AppWindowLauncher (because the user 1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // is currently active), the OnWindowDestroying observer has already (or will 1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // soon) unregister it independently from the shelf. If it was not registered 1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // we don't need to do anything anyways. As such, all which is left to do here 1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // is to get rid of our own reference. 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppWindowList::iterator it = 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::find(app_window_list_.begin(), app_window_list_.end(), app_window); 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(it != app_window_list_.end()); 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_window_list_.erase(it); 1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool MultiProfileAppWindowLauncherController::UserHasAppOnActiveDesktop( 144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch apps::AppWindow* app_window) { 145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::string& app_id = app_window->extension_id(); 146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch content::BrowserContext* app_context = app_window->browser_context(); 147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!app_context->IsOffTheRecord()); 148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::string& current_user = multi_user_util::GetCurrentUserId(); 149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chrome::MultiUserWindowManager* manager = 150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chrome::MultiUserWindowManager::GetInstance(); 151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (AppWindowList::iterator it = app_window_list_.begin(); 152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it != app_window_list_.end(); 153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++it) { 154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch apps::AppWindow* other_window = *it; 155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!other_window->browser_context()->IsOffTheRecord()); 156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (manager->IsWindowOnDesktopOfUser(other_window->GetNativeWindow(), 157effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch current_user) && 158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_id == other_window->extension_id() && 159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_context == other_window->browser_context()) { 160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return true; 161effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 162effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 165