multi_profile_app_window_launcher_controller.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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" 81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h" 10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/ash/multi_user/multi_user_util.h" 11effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" 121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/ui/host_desktop.h" 13effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/aura/window.h" 141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace { 161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool ControlsWindow(aura::Window* window) { 181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return chrome::GetHostDesktopTypeForNativeWindow(window) == 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome::HOST_DESKTOP_TYPE_ASH; 201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} // namespace 231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MultiProfileAppWindowLauncherController:: 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MultiProfileAppWindowLauncherController(ChromeLauncherController* owner) 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : AppWindowLauncherController(owner) {} 271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MultiProfileAppWindowLauncherController:: 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ~MultiProfileAppWindowLauncherController() { 301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // We need to remove all Registry observers for added users. 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AppWindowRegistryList::iterator it = multi_user_registry_.begin(); 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != multi_user_registry_.end(); 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) 341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) (*it)->RemoveObserver(this); 351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MultiProfileAppWindowLauncherController::ActiveUserChanged( 381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::string& user_email) { 391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // The active user has changed and we need to traverse our list of items to 401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // show / hide them one by one. To avoid that a user dependent state 411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // "survives" in a launcher item, we first delete all items making sure that 421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // nothing remains and then re-create them again. 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AppWindowList::iterator it = app_window_list_.begin(); 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != app_window_list_.end(); 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps::AppWindow* app_window = *it; 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile = 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile::FromBrowserContext(app_window->browser_context()); 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!multi_user_util::IsProfileFromActiveUser(profile) && 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IsRegisteredApp(app_window->GetNativeWindow())) 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UnregisterApp(app_window->GetNativeWindow()); 521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AppWindowList::iterator it = app_window_list_.begin(); 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != app_window_list_.end(); 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps::AppWindow* app_window = *it; 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile = 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile::FromBrowserContext(app_window->browser_context()); 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (multi_user_util::IsProfileFromActiveUser(profile) && 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !IsRegisteredApp(app_window->GetNativeWindow())) 611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) RegisterApp(*it); 621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MultiProfileAppWindowLauncherController::AdditionalUserAddedToSession( 661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Profile* profile) { 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Each users AppWindowRegistry needs to be observed. 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps::AppWindowRegistry* registry = apps::AppWindowRegistry::Get(profile); 691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) multi_user_registry_.push_back(registry); 701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) registry->AddObserver(this); 711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MultiProfileAppWindowLauncherController::OnAppWindowAdded( 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps::AppWindow* app_window) { 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ControlsWindow(app_window->GetNativeWindow())) 761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return; 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_window_list_.push_back(app_window); 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); 79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (multi_user_util::IsProfileFromActiveUser(profile)) { 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RegisterApp(app_window); 81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else { 82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If the window got created for a non active user but the user allowed to 83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // teleport to the current user's desktop, we teleport it now. 84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (UserHasAppOnActiveDesktop(app_window)) { 85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser( 86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_window->GetNativeWindow(), 87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch multi_user_util::GetCurrentUserId()); 88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (app_window->GetNativeWindow()->type() == ui::wm::WINDOW_TYPE_PANEL && 89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch !app_window->GetNativeWindow()->layer()->GetTargetOpacity()) { 90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // The panel layout manager only manages windows which are anchored. 91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Since this window did never had an anchor, it would stay hidden. We 92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // therefore make it visible now. 93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_window->GetNativeWindow()->layer()->SetOpacity(1.0f); 94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MultiProfileAppWindowLauncherController::OnAppWindowRemoved( 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps::AppWindow* app_window) { 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ControlsWindow(app_window->GetNativeWindow())) 1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return; 1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If the application is registered with AppWindowLauncher (because the user 1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // is currently active), the OnWindowDestroying observer has already (or will 1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // soon) unregister it independently from the shelf. If it was not registered 1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // we don't need to do anything anyways. As such, all which is left to do here 1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // is to get rid of our own reference. 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppWindowList::iterator it = 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::find(app_window_list_.begin(), app_window_list_.end(), app_window); 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(it != app_window_list_.end()); 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_window_list_.erase(it); 1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool MultiProfileAppWindowLauncherController::UserHasAppOnActiveDesktop( 116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch apps::AppWindow* app_window) { 117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::string& app_id = app_window->extension_id(); 118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch content::BrowserContext* app_context = app_window->browser_context(); 119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!app_context->IsOffTheRecord()); 120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::string& current_user = multi_user_util::GetCurrentUserId(); 121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chrome::MultiUserWindowManager* manager = 122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chrome::MultiUserWindowManager::GetInstance(); 123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (AppWindowList::iterator it = app_window_list_.begin(); 124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it != app_window_list_.end(); 125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++it) { 126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch apps::AppWindow* other_window = *it; 127effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!other_window->browser_context()->IsOffTheRecord()); 128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (manager->IsWindowOnDesktopOfUser(other_window->GetNativeWindow(), 129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch current_user) && 130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_id == other_window->extension_id() && 131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_context == other_window->browser_context()) { 132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return true; 133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 137