14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file. 44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h" 64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/ash_switches.h" 80f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ash/multi_profile_uma.h" 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/root_window_controller.h" 105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ash/session/session_state_delegate.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shelf/shelf.h" 124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/shell.h" 134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/shell_delegate.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shell_window_ids.h" 15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ash/system/tray/system_tray_notifier.h" 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ash/wm/maximize_mode/maximize_mode_controller.h" 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/wm/window_state.h" 184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/auto_reset.h" 190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/message_loop/message_loop.h" 204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/strings/string_util.h" 214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/browser_process.h" 224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/chrome_notification_types.h" 234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.h" 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/ash/multi_user/multi_user_util.h" 27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.h" 284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/browser.h" 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/ui/browser_finder.h" 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/browser_list.h" 314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/browser_window.h" 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/notification_service.h" 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/app_window/app_window.h" 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/app_window/app_window_registry.h" 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "google_apis/gaia/gaia_auth_util.h" 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/aura/client/aura_constants.h" 374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/aura/window.h" 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h" 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/base/ui_base_types.h" 400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ui/events/event.h" 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/message_center/message_center.h" 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/transient_window_manager.h" 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_animations.h" 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_util.h" 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace { 470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The animation time in milliseconds for a single window which is fading 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// in / out. 50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst int kAnimationTimeMS = 100; 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 52a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// The animation time in milliseconds for the fade in and / or out when 53a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// switching users. 54a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst int kUserFadeTimeMS = 110; 55a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The animation time in ms for a window which get teleported to another screen. 57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst int kTeleportAnimationTimeMS = 300; 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Checks if a given event is a user event. 60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool IsUserEvent(const ui::Event* e) { 610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (e) { 620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ui::EventType type = e->type(); 630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (type != ui::ET_CANCEL_MODE && 640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) type != ui::ET_UMA_DATA && 650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) type != ui::ET_UNKNOWN) 660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return true; 670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; 690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Test if we are currently processing a user event which might lead to a 720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// browser / app creation. 730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool IsProcessingUserEvent() { 740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // When there is a nested message loop (e.g. active menu or drag and drop 750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // operation) - we are in a nested loop and can ignore this. 760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Note: Unit tests might not have a message loop. 770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) base::MessageLoop* message_loop = base::MessageLoop::current(); 780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (message_loop && message_loop->is_running() && message_loop->IsNested()) 790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; 800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // TODO(skuhne): "Open link in new window" will come here after the menu got 820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // closed, executing the command from the nested menu loop. However at that 830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // time there is no active event processed. A solution for that need to be 840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // found past M-32. A global event handler filter (pre and post) might fix 850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // that problem in conjunction with a depth counter - but - for the menu 860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // execution we come here after the loop was finished (so it's not nested 870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // anymore) and the root window should therefore still have the event which 880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // lead to the menu invocation, but it is not. By fixing that problem this 890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // would "magically work". 90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) aura::Window::Windows root_window_list = ash::Shell::GetAllRootWindows(); 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (aura::Window::Windows::iterator it = root_window_list.begin(); 920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) it != root_window_list.end(); 930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ++it) { 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (IsUserEvent((*it)->GetHost()->dispatcher()->current_event())) 950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return true; 960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; 980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Records the type of window which was transferred to another desktop. 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void RecordUMAForTransferredWindowType(aura::Window* window) { 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // We need to figure out what kind of window this is to record the transfer. 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Browser* browser = chrome::FindBrowserWithWindow(window); 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ash::MultiProfileUMA::TeleportWindowType window_type = 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ash::MultiProfileUMA::TELEPORT_WINDOW_UNKNOWN; 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (browser) { 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (browser->profile()->IsOffTheRecord()) { 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_INCOGNITO_BROWSER; 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else if (browser->is_app()) { 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_V1_APP; 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else if (browser->is_type_popup()) { 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_POPUP; 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_BROWSER; 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Unit tests might come here without a profile manager. 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!g_browser_process->profile_manager()) 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If it is not a browser, it is probably be a V2 application. In that case 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // one of the AppWindowRegistry instances should know about it. 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::AppWindow* app_window = NULL; 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<Profile*> profiles = 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) g_browser_process->profile_manager()->GetLoadedProfiles(); 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (std::vector<Profile*>::iterator it = profiles.begin(); 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != profiles.end() && app_window == NULL; 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it++) { 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci app_window = extensions::AppWindowRegistry::Get(*it) 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ->GetAppWindowForNativeWindow(window); 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_window) { 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (app_window->window_type() == 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::AppWindow::WINDOW_TYPE_PANEL || 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci app_window->window_type() == 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::AppWindow::WINDOW_TYPE_V1_PANEL) { 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_PANEL; 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_V2_APP; 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ash::MultiProfileUMA::RecordTeleportWindowType(window_type); 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace chrome { 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A class to temporarily change the animation properties for a window. 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class AnimationSetter { 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AnimationSetter(aura::Window* window, int animation_time_in_ms) 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : window_(window), 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) previous_animation_type_( 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::GetWindowVisibilityAnimationType(window_)), 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) previous_animation_time_( 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::GetWindowVisibilityAnimationDuration(*window_)) { 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::SetWindowVisibilityAnimationType( 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_, 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::SetWindowVisibilityAnimationDuration( 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_, 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeDelta::FromMilliseconds(animation_time_in_ms)); 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~AnimationSetter() { 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::SetWindowVisibilityAnimationType(window_, 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) previous_animation_type_); 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::SetWindowVisibilityAnimationDuration( 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_, 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) previous_animation_time_); 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The window which gets used. 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::Window* window_; 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Previous animation type. 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const int previous_animation_type_; 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Previous animation time. 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::TimeDelta previous_animation_time_; 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(AnimationSetter); 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// This class keeps track of all applications which were started for a user. 1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// When an app gets created, the window will be tagged for that user. Note 1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// that the destruction does not need to be tracked here since the universal 1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// window observer will take care of that. 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass AppObserver : public extensions::AppWindowRegistry::Observer { 1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public: 1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) explicit AppObserver(const std::string& user_id) : user_id_(user_id) {} 1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual ~AppObserver() {} 1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // AppWindowRegistry::Observer overrides: 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void OnAppWindowAdded(extensions::AppWindow* app_window) OVERRIDE { 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::Window* window = app_window->GetNativeWindow(); 1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(window); 200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) MultiUserWindowManagerChromeOS::GetInstance()->SetWindowOwner(window, 2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) user_id_); 2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private: 2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string user_id_; 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(AppObserver); 2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}; 2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)MultiUserWindowManagerChromeOS::MultiUserWindowManagerChromeOS( 211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& current_user_id) 212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : current_user_id_(current_user_id), 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) notification_blocker_(new MultiUserNotificationBlockerChromeOS( 2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch message_center::MessageCenter::Get(), current_user_id)), 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) suppress_visibility_changes_(false), 216a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch animation_speed_(ANIMATION_SPEED_NORMAL) { 217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Add a session state observer to be able to monitor session changes. 218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (ash::Shell::HasInstance()) 219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ash::Shell::GetInstance()->session_state_delegate()-> 220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AddSessionStateObserver(this); 2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The BrowserListObserver would have been better to use then the old 223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // notification system, but that observer fires before the window got created. 224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) registrar_.Add(this, NOTIFICATION_BROWSER_WINDOW_READY, 225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::NotificationService::AllSources()); 2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Add an app window observer & all already running apps. 228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Profile* profile = multi_user_util::GetProfileFromUserID(current_user_id); 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (profile) 230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AddUser(profile); 2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)MultiUserWindowManagerChromeOS::~MultiUserWindowManagerChromeOS() { 234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // When the MultiUserWindowManager gets destroyed, ash::Shell is mostly gone. 235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // As such we should not try to finalize any outstanding user animations. 236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Note that the destruction of the object can be done later. 237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (animation_.get()) 238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch animation_->CancelAnimation(); 239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Remove all window observers. 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WindowToEntryMap::iterator window = window_to_entry_.begin(); 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (window != window_to_entry_.end()) { 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnWindowDestroyed(window->first); 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window = window_to_entry_.begin(); 245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Remove all app observers. 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UserIDToAppWindowObserver::iterator app_observer_iterator = 249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) user_id_to_app_observer_.begin(); 250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) while (app_observer_iterator != user_id_to_app_observer_.end()) { 251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Profile* profile = multi_user_util::GetProfileFromUserID( 252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) app_observer_iterator->first); 253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(profile); 2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::AppWindowRegistry::Get(profile) 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ->RemoveObserver(app_observer_iterator->second); 256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) delete app_observer_iterator->second; 257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) user_id_to_app_observer_.erase(app_observer_iterator); 258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) app_observer_iterator = user_id_to_app_observer_.begin(); 2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (ash::Shell::HasInstance()) 262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ash::Shell::GetInstance()->session_state_delegate()-> 263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) RemoveSessionStateObserver(this); 2648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 2658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MultiUserWindowManagerChromeOS::SetWindowOwner( 267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) aura::Window* window, 268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& user_id) { 2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Make sure the window is valid and there was no owner yet. 2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(window); 2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(!user_id.empty()); 2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (GetWindowOwner(window) == user_id) 2734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(GetWindowOwner(window).empty()); 2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) window_to_entry_[window] = new WindowEntry(user_id); 2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Remember the initial visibility of the window. 2780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) window_to_entry_[window]->set_show(window->IsVisible()); 2790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Add observers to track state changes. 2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) window->AddObserver(this); 282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::TransientWindowManager::Get(window)->AddObserver(this); 2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Check if this window was created due to a user interaction. If it was, 2850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // transfer it to the current user. 2860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (IsProcessingUserEvent()) 2870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) window_to_entry_[window]->set_show_for_user(current_user_id_); 2880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Add all transient children to our set of windows. Note that the function 2900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // will add the children but not the owner to the transient children map. 2910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) AddTransientOwnerRecursive(window, window); 2920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Notify entry adding. 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryAdded(window)); 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!IsWindowOnDesktopOfUser(window, current_user_id_)) 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetWindowVisibility(window, false, 0); 2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const std::string& MultiUserWindowManagerChromeOS::GetWindowOwner( 301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) aura::Window* window) const { 302010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) WindowToEntryMap::const_iterator it = window_to_entry_.find(window); 303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return it != window_to_entry_.end() ? it->second->owner() 304a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : base::EmptyString(); 3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MultiUserWindowManagerChromeOS::ShowWindowForUser( 308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) aura::Window* window, 309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& user_id) { 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string previous_owner(GetUserPresentingWindow(window)); 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ShowWindowForUserIntern(window, user_id)) 3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The window switched to a new desktop and we have to switch to that desktop, 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // but only when it was on the visible desktop and the the target is not the 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // visible desktop. 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (user_id == current_user_id_ || previous_owner != current_user_id_) 3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ash::Shell::GetInstance()->session_state_delegate()->SwitchActiveUser( 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_id); 3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool MultiUserWindowManagerChromeOS::AreWindowsSharedAmongUsers() const { 324010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) WindowToEntryMap::const_iterator it = window_to_entry_.begin(); 3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (; it != window_to_entry_.end(); ++it) { 3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (it->second->owner() != it->second->show_for_user()) 3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MultiUserWindowManagerChromeOS::GetOwnersOfVisibleWindows( 333010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) std::set<std::string>* user_ids) const { 334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (WindowToEntryMap::const_iterator it = window_to_entry_.begin(); 335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) it != window_to_entry_.end(); 336010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ++it) { 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it->first->IsVisible()) 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_ids->insert(it->second->owner()); 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool MultiUserWindowManagerChromeOS::IsWindowOnDesktopOfUser( 3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) aura::Window* window, 344010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::string& user_id) const { 3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& presenting_user = GetUserPresentingWindow(window); 3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return presenting_user.empty() || presenting_user == user_id; 3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const std::string& MultiUserWindowManagerChromeOS::GetUserPresentingWindow( 350010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) aura::Window* window) const { 351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) WindowToEntryMap::const_iterator it = window_to_entry_.find(window); 3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If the window is not owned by anyone it is shown on all desktops and we 3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // return the empty string. 3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (it == window_to_entry_.end()) 355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return base::EmptyString(); 3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Otherwise we ask the object for its desktop. 3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return it->second->show_for_user(); 3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MultiUserWindowManagerChromeOS::AddUser(content::BrowserContext* context) { 361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(context); 362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& user_id = multi_user_util::GetUserIDFromProfile(profile); 363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (user_id_to_app_observer_.find(user_id) != user_id_to_app_observer_.end()) 364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) user_id_to_app_observer_[user_id] = new AppObserver(user_id); 3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::AppWindowRegistry::Get(profile) 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ->AddObserver(user_id_to_app_observer_[user_id]); 369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Account all existing application windows of this user accordingly. 3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const extensions::AppWindowRegistry::AppWindowList& app_windows = 3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::AppWindowRegistry::Get(profile)->app_windows(); 3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::AppWindowRegistry::AppWindowList::const_iterator it = 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_windows.begin(); 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (; it != app_windows.end(); ++it) 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) user_id_to_app_observer_[user_id]->OnAppWindowAdded(*it); 377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Account all existing browser windows of this user accordingly. 379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserList* browser_list = BrowserList::GetInstance(HOST_DESKTOP_TYPE_ASH); 380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BrowserList::const_iterator browser_it = browser_list->begin(); 381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (; browser_it != browser_list->end(); ++browser_it) { 382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if ((*browser_it)->profile()->GetOriginalProfile() == profile) 383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AddBrowserWindow(*browser_it); 384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MultiUserWindowManagerChromeOS::AddObserver(Observer* observer) { 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) observers_.AddObserver(observer); 3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MultiUserWindowManagerChromeOS::RemoveObserver(Observer* observer) { 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) observers_.RemoveObserver(observer); 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MultiUserWindowManagerChromeOS::ActiveUserChanged( 396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& user_id) { 3974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(user_id != current_user_id_); 398c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // This needs to be set before the animation starts. 3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) current_user_id_ = user_id; 400c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 401c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch animation_.reset( 402a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch new UserSwichAnimatorChromeOS( 403a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch this, user_id, GetAdjustedAnimationTimeInMS(kUserFadeTimeMS))); 404010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Call notifier here instead of observing ActiveUserChanged because 405010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // this must happen after MultiUserWindowManagerChromeOS is notified. 406010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ash::Shell::GetInstance() 407010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ->system_tray_notifier() 408010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ->NotifyMediaCaptureChanged(); 4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) { 4120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (GetWindowOwner(window).empty()) { 4130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // This must be a window in the transient chain - remove it and its 4140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // children from the owner. 4150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) RemoveTransientOwnerRecursive(window); 4160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 4170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::TransientWindowManager::Get(window)->RemoveObserver(this); 4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Remove the window from the owners list. 4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) delete window_to_entry_[window]; 4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) window_to_entry_.erase(window); 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Notify entry change. 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryRemoved(window)); 4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanging( 4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) aura::Window* window, bool visible) { 4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // This command gets called first and immediately when show or hide gets 4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // called. We remember here the desired state for restoration IF we were 4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // not ourselves issuing the call. 4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Note also that using the OnWindowVisibilityChanged callback cannot be 4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // used for this. 4340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (suppress_visibility_changes_) 4350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 4360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) WindowToEntryMap::iterator it = window_to_entry_.find(window); 4380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // If the window is not owned by anyone it is shown on all desktops. 4390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (it != window_to_entry_.end()) { 4400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Remember what was asked for so that we can restore this when the user's 4410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // desktop gets restored. 4420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) it->second->set_show(visible); 4430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } else { 4440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) TransientWindowToVisibility::iterator it = 4450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) transient_window_to_visibility_.find(window); 4460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (it != transient_window_to_visibility_.end()) 4470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) it->second = visible; 4484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 451f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanged( 4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) aura::Window* window, bool visible) { 4530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (suppress_visibility_changes_) 4540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 4550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Don't allow to make the window visible if it shouldn't be. 4570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (visible && !IsWindowOnDesktopOfUser(window, current_user_id_)) { 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetWindowVisibility(window, false, 0); 4590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 4600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 4610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) aura::Window* owned_parent = GetOwningWindowInTransientChain(window); 4620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (owned_parent && owned_parent != window && visible && 4630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) !IsWindowOnDesktopOfUser(owned_parent, current_user_id_)) 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetWindowVisibility(window, false, 0); 4650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 4660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MultiUserWindowManagerChromeOS::OnTransientChildAdded( 4680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) aura::Window* window, 4690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) aura::Window* transient_window) { 4700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!GetWindowOwner(window).empty()) { 4710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) AddTransientOwnerRecursive(transient_window, window); 4720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 4730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 4740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) aura::Window* owned_parent = 4750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) GetOwningWindowInTransientChain(transient_window); 4760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!owned_parent) 4770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 4780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) AddTransientOwnerRecursive(transient_window, owned_parent); 4800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 4810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MultiUserWindowManagerChromeOS::OnTransientChildRemoved( 4830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) aura::Window* window, 4840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) aura::Window* transient_window) { 4850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Remove the transient child if the window itself is owned, or one of the 4860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // windows in its transient parents chain. 4870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!GetWindowOwner(window).empty() || 4880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) GetOwningWindowInTransientChain(window)) 4890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) RemoveTransientOwnerRecursive(transient_window); 4904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 492f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MultiUserWindowManagerChromeOS::Observe( 4934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int type, 4944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const content::NotificationSource& source, 4954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const content::NotificationDetails& details) { 496f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (type == NOTIFICATION_BROWSER_WINDOW_READY) 4974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AddBrowserWindow(content::Source<Browser>(source).ptr()); 4984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 500a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid MultiUserWindowManagerChromeOS::SetAnimationSpeedForTest( 501a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch MultiUserWindowManagerChromeOS::AnimationSpeed speed) { 502a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch animation_speed_ = speed; 5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool MultiUserWindowManagerChromeOS::IsAnimationRunningForTest() { 506c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return animation_.get() != NULL && !animation_->IsAnimationFinished(); 5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 509010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const std::string& MultiUserWindowManagerChromeOS::GetCurrentUserForTest() 510010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const { 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return current_user_id_; 5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool MultiUserWindowManagerChromeOS::ShowWindowForUserIntern( 5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::Window* window, 5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& user_id) { 5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If there is either no owner, or the owner is the current user, no action 5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // is required. 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& owner = GetWindowOwner(window); 5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (owner.empty() || 5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (owner == user_id && IsWindowOnDesktopOfUser(window, user_id))) 5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool minimized = ash::wm::GetWindowState(window)->IsMinimized(); 5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Check that we are not trying to transfer ownership of a minimized window. 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (user_id != owner && minimized) 5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (minimized) { 5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If it is minimized it falls back to the original desktop. 5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ash::MultiProfileUMA::RecordTeleportAction( 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ash::MultiProfileUMA::TELEPORT_WINDOW_RETURN_BY_MINIMIZE); 5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If the window was transferred without getting minimized, we should record 5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the window type. 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RecordUMAForTransferredWindowType(window); 5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WindowToEntryMap::iterator it = window_to_entry_.find(window); 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it->second->set_show_for_user(user_id); 5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Show the window if the added user is the current one. 5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (user_id == current_user_id_) { 5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only show the window if it should be shown according to its state. 5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it->second->show()) 5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetWindowVisibility(window, true, kTeleportAnimationTimeMS); 5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetWindowVisibility(window, false, kTeleportAnimationTimeMS); 5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Notify entry change. 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryChanged(window)); 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 556f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MultiUserWindowManagerChromeOS::SetWindowVisibility( 5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::Window* window, bool visible, int animation_time_in_ms) { 5584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (window->IsVisible() == visible) 5594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 5604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 561f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Hiding a system modal dialog should not be allowed. Instead we switch to 562f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // the user which is showing the system modal window. 563f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Note that in some cases (e.g. unit test) windows might not have a root 564f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // window. 565f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!visible && window->GetRootWindow()) { 566f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Get the system modal container for the window's root window. 567f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) aura::Window* system_modal_container = 568f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) window->GetRootWindow()->GetChildById( 569c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ash::kShellWindowId_SystemModalContainer); 570f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (window->parent() == system_modal_container) { 571f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The window is system modal and we need to find the parent which owns 572f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // it so that we can switch to the desktop accordingly. 573f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string user_id = GetUserPresentingWindow(window); 574f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (user_id.empty()) { 575f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) aura::Window* owning_window = GetOwningWindowInTransientChain(window); 576f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(owning_window); 577f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) user_id = GetUserPresentingWindow(owning_window); 578f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!user_id.empty()); 579f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 580f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ash::Shell::GetInstance()->session_state_delegate()->SwitchActiveUser( 581f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) user_id); 582f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 583f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 584f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 585f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // To avoid that these commands are recorded as any other commands, we are 5874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // suppressing any window entry changes while this is going on. 5884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true); 5894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (visible) { 5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShowWithTransientChildrenRecursive(window, animation_time_in_ms); 5920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } else { 5930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (window->HasFocus()) 5940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) window->Blur(); 5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetWindowVisible(window, false, animation_time_in_ms); 5960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 5970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 5980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 599c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid MultiUserWindowManagerChromeOS::AddBrowserWindow(Browser* browser) { 600c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // A unit test (e.g. CrashRestoreComplexTest.RestoreSessionForThreeUsers) can 601c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // come here with no valid window. 602c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!browser->window() || !browser->window()->GetNativeWindow()) 603c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 604c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch SetWindowOwner(browser->window()->GetNativeWindow(), 605c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch multi_user_util::GetUserIDFromProfile(browser->profile())); 606c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 607c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 608f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MultiUserWindowManagerChromeOS::ShowWithTransientChildrenRecursive( 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::Window* window, int animation_time_in_ms) { 6100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) aura::Window::Windows::const_iterator it = 611a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::GetTransientChildren(window).begin(); 612a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (; it != wm::GetTransientChildren(window).end(); ++it) 6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShowWithTransientChildrenRecursive(*it, animation_time_in_ms); 6140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 6150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // We show all children which were not explicitly hidden. 6160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) TransientWindowToVisibility::iterator it2 = 6170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) transient_window_to_visibility_.find(window); 6180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (it2 == transient_window_to_visibility_.end() || it2->second) 6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetWindowVisible(window, true, animation_time_in_ms); 6200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 6210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)aura::Window* MultiUserWindowManagerChromeOS::GetOwningWindowInTransientChain( 623010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) aura::Window* window) const { 6240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!GetWindowOwner(window).empty()) 6250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return NULL; 626a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) aura::Window* parent = wm::GetTransientParent(window); 6270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) while (parent) { 6280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!GetWindowOwner(parent).empty()) 6290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return parent; 630a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) parent = wm::GetTransientParent(parent); 6310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 6320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return NULL; 6330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 6340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 635f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MultiUserWindowManagerChromeOS::AddTransientOwnerRecursive( 6360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) aura::Window* window, 6370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) aura::Window* owned_parent) { 6380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // First add all child windows. 6390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) aura::Window::Windows::const_iterator it = 640a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::GetTransientChildren(window).begin(); 641a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (; it != wm::GetTransientChildren(window).end(); ++it) 6420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) AddTransientOwnerRecursive(*it, owned_parent); 6430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 6440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // If this window is the owned window, we do not have to handle it again. 6450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (window == owned_parent) 6460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 6470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 6480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Remember the current visibility. 6490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) DCHECK(transient_window_to_visibility_.find(window) == 6500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) transient_window_to_visibility_.end()); 6510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) transient_window_to_visibility_[window] = window->IsVisible(); 6520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Add observers to track state changes. 6540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) window->AddObserver(this); 655a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::TransientWindowManager::Get(window)->AddObserver(this); 6560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 6570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Hide the window if it should not be shown. Note that this hide operation 6580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // will hide recursively this and all children - but we have already collected 6590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // their initial view state. 6600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!IsWindowOnDesktopOfUser(owned_parent, current_user_id_)) 6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetWindowVisibility(window, false, kAnimationTimeMS); 6620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 6630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 664f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MultiUserWindowManagerChromeOS::RemoveTransientOwnerRecursive( 6650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) aura::Window* window) { 6660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // First remove all child windows. 6670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) aura::Window::Windows::const_iterator it = 668a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::GetTransientChildren(window).begin(); 669a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (; it != wm::GetTransientChildren(window).end(); ++it) 6700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) RemoveTransientOwnerRecursive(*it); 6710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 6720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Find from transient window storage the visibility for the given window, 6730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // set the visibility accordingly and delete the window from the map. 6740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) TransientWindowToVisibility::iterator visibility_item = 6750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) transient_window_to_visibility_.find(window); 6760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) DCHECK(visibility_item != transient_window_to_visibility_.end()); 6770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 6780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) window->RemoveObserver(this); 679a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wm::TransientWindowManager::Get(window)->RemoveObserver(this); 6800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 6810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bool unowned_view_state = visibility_item->second; 6820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) transient_window_to_visibility_.erase(visibility_item); 6830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (unowned_view_state && !window->IsVisible()) { 6840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // To prevent these commands from being recorded as any other commands, we 6850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // are suppressing any window entry changes while this is going on. 6860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Instead of calling SetWindowVisible, only show gets called here since all 6870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // dependents have been shown previously already. 6880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true); 6890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) window->Show(); 6900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 6914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 6924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 6935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MultiUserWindowManagerChromeOS::SetWindowVisible( 6945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::Window* window, 6955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool visible, 6965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int animation_time_in_ms) { 6975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The MaximizeModeWindowManager will not handle invisible windows since they 6985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // are not user activatable. Since invisible windows are not being tracked, 6995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // we tell it to maximize / track this window now before it gets shown, to 7005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // reduce animation jank from multiple resizes. 7015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (visible) 7025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ash::Shell::GetInstance()->maximize_mode_controller()->AddWindow(window); 7035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AnimationSetter animation_setter( 7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window, 706a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch GetAdjustedAnimationTimeInMS(animation_time_in_ms)); 7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (visible) 7095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window->Show(); 7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window->Hide(); 7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Make sure that animations have no influence on the window state after the 7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // call. 7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(visible, window->IsVisible()); 7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 718a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochint MultiUserWindowManagerChromeOS::GetAdjustedAnimationTimeInMS( 719010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int default_time_in_ms) const { 720a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return animation_speed_ == ANIMATION_SPEED_NORMAL ? default_time_in_ms : 721a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch (animation_speed_ == ANIMATION_SPEED_FAST ? 10 : 0); 722a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 723a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 7244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace chrome 725