| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h" | 5 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h" |
| 6 | 6 |
| 7 #include "ash/ash_switches.h" | 7 #include "ash/ash_switches.h" |
| 8 #include "ash/multi_profile_uma.h" | 8 #include "ash/multi_profile_uma.h" |
| 9 #include "ash/root_window_controller.h" | 9 #include "ash/root_window_controller.h" |
| 10 #include "ash/session/session_state_delegate.h" | 10 #include "ash/session/session_state_delegate.h" |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 const std::string& user_id, | 221 const std::string& user_id, |
| 222 KeyedServiceShutdownNotifier::Subscription* shutdown_notification) | 222 KeyedServiceShutdownNotifier::Subscription* shutdown_notification) |
| 223 : user_id_(user_id), | 223 : user_id_(user_id), |
| 224 profile_shutdown_notification_(shutdown_notification) {} | 224 profile_shutdown_notification_(shutdown_notification) {} |
| 225 ~AppObserver() override {} | 225 ~AppObserver() override {} |
| 226 | 226 |
| 227 // AppWindowRegistry::Observer overrides: | 227 // AppWindowRegistry::Observer overrides: |
| 228 void OnAppWindowAdded(extensions::AppWindow* app_window) override { | 228 void OnAppWindowAdded(extensions::AppWindow* app_window) override { |
| 229 aura::Window* window = app_window->GetNativeWindow(); | 229 aura::Window* window = app_window->GetNativeWindow(); |
| 230 DCHECK(window); | 230 DCHECK(window); |
| 231 MultiUserWindowManagerChromeOS::GetInstance()->SetWindowOwner(window, | 231 MultiUserWindowManagerChromeOS::GetInstance()->SetWindowOwner( |
| 232 user_id_); | 232 window, AccountId::FromUserEmail(user_id_)); |
| 233 } | 233 } |
| 234 | 234 |
| 235 private: | 235 private: |
| 236 std::string user_id_; | 236 std::string user_id_; |
| 237 | 237 |
| 238 // This notification is triggered when the profile gets destroyed (during | 238 // This notification is triggered when the profile gets destroyed (during |
| 239 // shutdown process). | 239 // shutdown process). |
| 240 // The callback (stored in notification) destroyes AppObserver object. | 240 // The callback (stored in notification) destroyes AppObserver object. |
| 241 scoped_ptr<KeyedServiceShutdownNotifier::Subscription> | 241 scoped_ptr<KeyedServiceShutdownNotifier::Subscription> |
| 242 profile_shutdown_notification_; | 242 profile_shutdown_notification_; |
| 243 | 243 |
| 244 DISALLOW_COPY_AND_ASSIGN(AppObserver); | 244 DISALLOW_COPY_AND_ASSIGN(AppObserver); |
| 245 }; | 245 }; |
| 246 | 246 |
| 247 MultiUserWindowManagerChromeOS::MultiUserWindowManagerChromeOS( | 247 MultiUserWindowManagerChromeOS::MultiUserWindowManagerChromeOS( |
| 248 const std::string& current_user_id) | 248 const AccountId& current_account_id) |
| 249 : current_user_id_(current_user_id), | 249 : current_account_id_(current_account_id), |
| 250 notification_blocker_(new MultiUserNotificationBlockerChromeOS( | 250 notification_blocker_(new MultiUserNotificationBlockerChromeOS( |
| 251 message_center::MessageCenter::Get(), current_user_id)), | 251 message_center::MessageCenter::Get(), |
| 252 current_account_id)), |
| 252 suppress_visibility_changes_(false), | 253 suppress_visibility_changes_(false), |
| 253 animation_speed_(ANIMATION_SPEED_NORMAL) { | 254 animation_speed_(ANIMATION_SPEED_NORMAL) {} |
| 254 } | |
| 255 | 255 |
| 256 MultiUserWindowManagerChromeOS::~MultiUserWindowManagerChromeOS() { | 256 MultiUserWindowManagerChromeOS::~MultiUserWindowManagerChromeOS() { |
| 257 // When the MultiUserWindowManager gets destroyed, ash::Shell is mostly gone. | 257 // When the MultiUserWindowManager gets destroyed, ash::Shell is mostly gone. |
| 258 // As such we should not try to finalize any outstanding user animations. | 258 // As such we should not try to finalize any outstanding user animations. |
| 259 // Note that the destruction of the object can be done later. | 259 // Note that the destruction of the object can be done later. |
| 260 if (animation_.get()) | 260 if (animation_.get()) |
| 261 animation_->CancelAnimation(); | 261 animation_->CancelAnimation(); |
| 262 | 262 |
| 263 // Remove all window observers. | 263 // Remove all window observers. |
| 264 WindowToEntryMap::iterator window = window_to_entry_.begin(); | 264 WindowToEntryMap::iterator window = window_to_entry_.begin(); |
| 265 while (window != window_to_entry_.end()) { | 265 while (window != window_to_entry_.end()) { |
| 266 OnWindowDestroyed(window->first); | 266 OnWindowDestroyed(window->first); |
| 267 window = window_to_entry_.begin(); | 267 window = window_to_entry_.begin(); |
| 268 } | 268 } |
| 269 | 269 |
| 270 // Remove all app observers. | 270 // Remove all app observers. |
| 271 UserIDToAppWindowObserver::iterator app_observer_iterator = | 271 AccountIdToAppWindowObserver::iterator app_observer_iterator = |
| 272 user_id_to_app_observer_.begin(); | 272 account_id_to_app_observer_.begin(); |
| 273 while (app_observer_iterator != user_id_to_app_observer_.end()) { | 273 while (app_observer_iterator != account_id_to_app_observer_.end()) { |
| 274 Profile* profile = multi_user_util::GetProfileFromUserID( | 274 Profile* profile = |
| 275 app_observer_iterator->first); | 275 multi_user_util::GetProfileFromAccountId(app_observer_iterator->first); |
| 276 CHECK(profile) << "profile not found for:" << app_observer_iterator->first; | 276 CHECK(profile) << "profile not found for:" |
| 277 << app_observer_iterator->first.GetUserEmail(); |
| 277 RemoveUser(app_observer_iterator->first, profile); | 278 RemoveUser(app_observer_iterator->first, profile); |
| 278 app_observer_iterator = user_id_to_app_observer_.begin(); | 279 app_observer_iterator = account_id_to_app_observer_.begin(); |
| 279 } | 280 } |
| 280 | 281 |
| 281 if (ash::Shell::HasInstance()) | 282 if (ash::Shell::HasInstance()) |
| 282 ash::Shell::GetInstance()->session_state_delegate()-> | 283 ash::Shell::GetInstance()->session_state_delegate()-> |
| 283 RemoveSessionStateObserver(this); | 284 RemoveSessionStateObserver(this); |
| 284 } | 285 } |
| 285 | 286 |
| 286 void MultiUserWindowManagerChromeOS::Init() { | 287 void MultiUserWindowManagerChromeOS::Init() { |
| 287 // Since we are setting the SessionStateObserver and adding the user, this | 288 // Since we are setting the SessionStateObserver and adding the user, this |
| 288 // function should get called only once. | 289 // function should get called only once. |
| 289 DCHECK(user_id_to_app_observer_.find(current_user_id_) == | 290 DCHECK(account_id_to_app_observer_.find(current_account_id_) == |
| 290 user_id_to_app_observer_.end()); | 291 account_id_to_app_observer_.end()); |
| 291 | 292 |
| 292 // Add a session state observer to be able to monitor session changes. | 293 // Add a session state observer to be able to monitor session changes. |
| 293 if (ash::Shell::HasInstance()) { | 294 if (ash::Shell::HasInstance()) { |
| 294 ash::Shell::GetInstance()->session_state_delegate()-> | 295 ash::Shell::GetInstance()->session_state_delegate()-> |
| 295 AddSessionStateObserver(this); | 296 AddSessionStateObserver(this); |
| 296 } | 297 } |
| 297 | 298 |
| 298 // The BrowserListObserver would have been better to use then the old | 299 // The BrowserListObserver would have been better to use then the old |
| 299 // notification system, but that observer fires before the window got created. | 300 // notification system, but that observer fires before the window got created. |
| 300 registrar_.Add(this, NOTIFICATION_BROWSER_WINDOW_READY, | 301 registrar_.Add(this, NOTIFICATION_BROWSER_WINDOW_READY, |
| 301 content::NotificationService::AllSources()); | 302 content::NotificationService::AllSources()); |
| 302 | 303 |
| 303 // Add an app window observer & all already running apps. | 304 // Add an app window observer & all already running apps. |
| 304 Profile* profile = multi_user_util::GetProfileFromUserID(current_user_id_); | 305 Profile* profile = |
| 306 multi_user_util::GetProfileFromAccountId(current_account_id_); |
| 305 if (profile) | 307 if (profile) |
| 306 AddUser(profile); | 308 AddUser(profile); |
| 307 } | 309 } |
| 308 | 310 |
| 309 void MultiUserWindowManagerChromeOS::SetWindowOwner( | 311 void MultiUserWindowManagerChromeOS::SetWindowOwner( |
| 310 aura::Window* window, | 312 aura::Window* window, |
| 311 const std::string& user_id) { | 313 const AccountId& account_id) { |
| 312 // Make sure the window is valid and there was no owner yet. | 314 // Make sure the window is valid and there was no owner yet. |
| 313 DCHECK(window); | 315 DCHECK(window); |
| 314 DCHECK(!user_id.empty()); | 316 DCHECK(account_id.is_valid()); |
| 315 if (GetWindowOwner(window) == user_id) | 317 if (GetWindowOwner(window) == account_id) |
| 316 return; | 318 return; |
| 317 DCHECK(GetWindowOwner(window).empty()); | 319 DCHECK(GetWindowOwner(window).empty()); |
| 318 window_to_entry_[window] = new WindowEntry(user_id); | 320 window_to_entry_[window] = new WindowEntry(account_id); |
| 319 | 321 |
| 320 // Remember the initial visibility of the window. | 322 // Remember the initial visibility of the window. |
| 321 window_to_entry_[window]->set_show(window->IsVisible()); | 323 window_to_entry_[window]->set_show(window->IsVisible()); |
| 322 | 324 |
| 323 // Add observers to track state changes. | 325 // Add observers to track state changes. |
| 324 window->AddObserver(this); | 326 window->AddObserver(this); |
| 325 wm::TransientWindowManager::Get(window)->AddObserver(this); | 327 wm::TransientWindowManager::Get(window)->AddObserver(this); |
| 326 | 328 |
| 327 // Check if this window was created due to a user interaction. If it was, | 329 // Check if this window was created due to a user interaction. If it was, |
| 328 // transfer it to the current user. | 330 // transfer it to the current user. |
| 329 if (IsProcessingUserEvent()) | 331 if (IsProcessingUserEvent()) |
| 330 window_to_entry_[window]->set_show_for_user(current_user_id_); | 332 window_to_entry_[window]->set_show_for_user(current_account_id_); |
| 331 | 333 |
| 332 // Add all transient children to our set of windows. Note that the function | 334 // Add all transient children to our set of windows. Note that the function |
| 333 // will add the children but not the owner to the transient children map. | 335 // will add the children but not the owner to the transient children map. |
| 334 AddTransientOwnerRecursive(window, window); | 336 AddTransientOwnerRecursive(window, window); |
| 335 | 337 |
| 336 // Notify entry adding. | 338 // Notify entry adding. |
| 337 FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryAdded(window)); | 339 FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryAdded(window)); |
| 338 | 340 |
| 339 if (!IsWindowOnDesktopOfUser(window, current_user_id_)) | 341 if (!IsWindowOnDesktopOfUser(window, current_account_id_)) |
| 340 SetWindowVisibility(window, false, 0); | 342 SetWindowVisibility(window, false, 0); |
| 341 } | 343 } |
| 342 | 344 |
| 343 const std::string& MultiUserWindowManagerChromeOS::GetWindowOwner( | 345 const AccountId& MultiUserWindowManagerChromeOS::GetWindowOwner( |
| 344 aura::Window* window) const { | 346 aura::Window* window) const { |
| 345 WindowToEntryMap::const_iterator it = window_to_entry_.find(window); | 347 WindowToEntryMap::const_iterator it = window_to_entry_.find(window); |
| 346 return it != window_to_entry_.end() ? it->second->owner() | 348 return it != window_to_entry_.end() ? it->second->owner() : EmptyAccountId(); |
| 347 : base::EmptyString(); | |
| 348 } | 349 } |
| 349 | 350 |
| 350 void MultiUserWindowManagerChromeOS::ShowWindowForUser( | 351 void MultiUserWindowManagerChromeOS::ShowWindowForUser( |
| 351 aura::Window* window, | 352 aura::Window* window, |
| 352 const std::string& user_id) { | 353 const AccountId& account_id) { |
| 353 std::string previous_owner(GetUserPresentingWindow(window)); | 354 const AccountId previous_owner(GetUserPresentingWindow(window)); |
| 354 if (!ShowWindowForUserIntern(window, user_id)) | 355 if (!ShowWindowForUserIntern(window, account_id)) |
| 355 return; | 356 return; |
| 356 // The window switched to a new desktop and we have to switch to that desktop, | 357 // The window switched to a new desktop and we have to switch to that desktop, |
| 357 // but only when it was on the visible desktop and the the target is not the | 358 // but only when it was on the visible desktop and the the target is not the |
| 358 // visible desktop. | 359 // visible desktop. |
| 359 if (user_id == current_user_id_ || previous_owner != current_user_id_) | 360 if (account_id == current_account_id_ || |
| 361 previous_owner != current_account_id_) |
| 360 return; | 362 return; |
| 361 | 363 |
| 362 ash::Shell::GetInstance()->session_state_delegate()->SwitchActiveUser( | 364 ash::Shell::GetInstance()->session_state_delegate()->SwitchActiveUser( |
| 363 user_id); | 365 account_id); |
| 364 } | 366 } |
| 365 | 367 |
| 366 bool MultiUserWindowManagerChromeOS::AreWindowsSharedAmongUsers() const { | 368 bool MultiUserWindowManagerChromeOS::AreWindowsSharedAmongUsers() const { |
| 367 WindowToEntryMap::const_iterator it = window_to_entry_.begin(); | 369 WindowToEntryMap::const_iterator it = window_to_entry_.begin(); |
| 368 for (; it != window_to_entry_.end(); ++it) { | 370 for (; it != window_to_entry_.end(); ++it) { |
| 369 if (it->second->owner() != it->second->show_for_user()) | 371 if (it->second->owner() != it->second->show_for_user()) |
| 370 return true; | 372 return true; |
| 371 } | 373 } |
| 372 return false; | 374 return false; |
| 373 } | 375 } |
| 374 | 376 |
| 375 void MultiUserWindowManagerChromeOS::GetOwnersOfVisibleWindows( | 377 void MultiUserWindowManagerChromeOS::GetOwnersOfVisibleWindows( |
| 376 std::set<std::string>* user_ids) const { | 378 std::set<AccountId>* account_ids) const { |
| 377 for (WindowToEntryMap::const_iterator it = window_to_entry_.begin(); | 379 for (WindowToEntryMap::const_iterator it = window_to_entry_.begin(); |
| 378 it != window_to_entry_.end(); | 380 it != window_to_entry_.end(); |
| 379 ++it) { | 381 ++it) { |
| 380 if (it->first->IsVisible()) | 382 if (it->first->IsVisible()) |
| 381 user_ids->insert(it->second->owner()); | 383 account_ids->insert(it->second->owner()); |
| 382 } | 384 } |
| 383 } | 385 } |
| 384 | 386 |
| 385 bool MultiUserWindowManagerChromeOS::IsWindowOnDesktopOfUser( | 387 bool MultiUserWindowManagerChromeOS::IsWindowOnDesktopOfUser( |
| 386 aura::Window* window, | 388 aura::Window* window, |
| 387 const std::string& user_id) const { | 389 const AccountId& account_id) const { |
| 388 const std::string& presenting_user = GetUserPresentingWindow(window); | 390 const AccountId& presenting_user = GetUserPresentingWindow(window); |
| 389 return presenting_user.empty() || presenting_user == user_id; | 391 return (!presenting_user.is_valid()) || presenting_user == account_id; |
| 390 } | 392 } |
| 391 | 393 |
| 392 const std::string& MultiUserWindowManagerChromeOS::GetUserPresentingWindow( | 394 const AccountId& MultiUserWindowManagerChromeOS::GetUserPresentingWindow( |
| 393 aura::Window* window) const { | 395 aura::Window* window) const { |
| 394 WindowToEntryMap::const_iterator it = window_to_entry_.find(window); | 396 WindowToEntryMap::const_iterator it = window_to_entry_.find(window); |
| 395 // If the window is not owned by anyone it is shown on all desktops and we | 397 // If the window is not owned by anyone it is shown on all desktops and we |
| 396 // return the empty string. | 398 // return the empty string. |
| 397 if (it == window_to_entry_.end()) | 399 if (it == window_to_entry_.end()) |
| 398 return base::EmptyString(); | 400 return EmptyAccountId(); |
| 399 // Otherwise we ask the object for its desktop. | 401 // Otherwise we ask the object for its desktop. |
| 400 return it->second->show_for_user(); | 402 return it->second->show_for_user(); |
| 401 } | 403 } |
| 402 | 404 |
| 403 void MultiUserWindowManagerChromeOS::AddUser(content::BrowserContext* context) { | 405 void MultiUserWindowManagerChromeOS::AddUser(content::BrowserContext* context) { |
| 404 Profile* profile = Profile::FromBrowserContext(context); | 406 Profile* profile = Profile::FromBrowserContext(context); |
| 405 const std::string& user_id = multi_user_util::GetUserIDFromProfile(profile); | 407 const AccountId& account_id( |
| 406 if (user_id_to_app_observer_.find(user_id) != user_id_to_app_observer_.end()) | 408 multi_user_util::GetAccountIdFromProfile(profile)); |
| 409 if (account_id_to_app_observer_.find(account_id) != |
| 410 account_id_to_app_observer_.end()) |
| 407 return; | 411 return; |
| 408 | 412 |
| 409 scoped_ptr<KeyedServiceShutdownNotifier::Subscription> notification = | 413 scoped_ptr<KeyedServiceShutdownNotifier::Subscription> notification = |
| 410 MultiUserWindowManagerCrOSShutdownNotifierFactory::GetInstance() | 414 MultiUserWindowManagerCrOSShutdownNotifierFactory::GetInstance() |
| 411 ->Get(profile) | 415 ->Get(profile) |
| 412 ->Subscribe(base::Bind(&MultiUserWindowManagerChromeOS::RemoveUser, | 416 ->Subscribe(base::Bind(&MultiUserWindowManagerChromeOS::RemoveUser, |
| 413 base::Unretained(this), user_id, | 417 base::Unretained(this), account_id, |
| 414 base::Unretained(profile))); | 418 base::Unretained(profile))); |
| 415 | 419 |
| 416 user_id_to_app_observer_[user_id] = | 420 account_id_to_app_observer_[account_id] = |
| 417 new AppObserver(user_id, notification.release()); | 421 new AppObserver(account_id.GetUserEmail(), notification.release()); |
| 418 extensions::AppWindowRegistry::Get(profile) | 422 extensions::AppWindowRegistry::Get(profile) |
| 419 ->AddObserver(user_id_to_app_observer_[user_id]); | 423 ->AddObserver(account_id_to_app_observer_[account_id]); |
| 420 | 424 |
| 421 // Account all existing application windows of this user accordingly. | 425 // Account all existing application windows of this user accordingly. |
| 422 const extensions::AppWindowRegistry::AppWindowList& app_windows = | 426 const extensions::AppWindowRegistry::AppWindowList& app_windows = |
| 423 extensions::AppWindowRegistry::Get(profile)->app_windows(); | 427 extensions::AppWindowRegistry::Get(profile)->app_windows(); |
| 424 extensions::AppWindowRegistry::AppWindowList::const_iterator it = | 428 extensions::AppWindowRegistry::AppWindowList::const_iterator it = |
| 425 app_windows.begin(); | 429 app_windows.begin(); |
| 426 for (; it != app_windows.end(); ++it) | 430 for (; it != app_windows.end(); ++it) |
| 427 user_id_to_app_observer_[user_id]->OnAppWindowAdded(*it); | 431 account_id_to_app_observer_[account_id]->OnAppWindowAdded(*it); |
| 428 | 432 |
| 429 // Account all existing browser windows of this user accordingly. | 433 // Account all existing browser windows of this user accordingly. |
| 430 BrowserList* browser_list = BrowserList::GetInstance(HOST_DESKTOP_TYPE_ASH); | 434 BrowserList* browser_list = BrowserList::GetInstance(HOST_DESKTOP_TYPE_ASH); |
| 431 BrowserList::const_iterator browser_it = browser_list->begin(); | 435 BrowserList::const_iterator browser_it = browser_list->begin(); |
| 432 for (; browser_it != browser_list->end(); ++browser_it) { | 436 for (; browser_it != browser_list->end(); ++browser_it) { |
| 433 if ((*browser_it)->profile()->GetOriginalProfile() == profile) | 437 if ((*browser_it)->profile()->GetOriginalProfile() == profile) |
| 434 AddBrowserWindow(*browser_it); | 438 AddBrowserWindow(*browser_it); |
| 435 } | 439 } |
| 436 // When adding another user to the session, we auto switch users. | 440 // When adding another user to the session, we auto switch users. |
| 437 if (user_id_to_app_observer_.size() == 1) | 441 if (account_id_to_app_observer_.size() == 1) |
| 438 return; | 442 return; |
| 439 | 443 |
| 440 // Don't do anything special in case of user session restore after crash. | 444 // Don't do anything special in case of user session restore after crash. |
| 441 // In that case session restore process will automatically switch to the | 445 // In that case session restore process will automatically switch to the |
| 442 // last active user session after whole process is complete. | 446 // last active user session after whole process is complete. |
| 443 if (!chromeos::UserSessionManager::GetInstance()-> | 447 if (!chromeos::UserSessionManager::GetInstance()-> |
| 444 UserSessionsRestoreInProgress()) { | 448 UserSessionsRestoreInProgress()) { |
| 445 // Immediately hide the windows of the current user. | 449 // Immediately hide the windows of the current user. |
| 446 base::AutoReset<AnimationSpeed> animation_speed(&animation_speed_, | 450 base::AutoReset<AnimationSpeed> animation_speed(&animation_speed_, |
| 447 ANIMATION_SPEED_DISABLED); | 451 ANIMATION_SPEED_DISABLED); |
| 448 ActiveUserChanged(user_id); | 452 ActiveUserChanged(account_id); |
| 449 } | 453 } |
| 450 } | 454 } |
| 451 | 455 |
| 452 void MultiUserWindowManagerChromeOS::AddObserver(Observer* observer) { | 456 void MultiUserWindowManagerChromeOS::AddObserver(Observer* observer) { |
| 453 observers_.AddObserver(observer); | 457 observers_.AddObserver(observer); |
| 454 } | 458 } |
| 455 | 459 |
| 456 void MultiUserWindowManagerChromeOS::RemoveObserver(Observer* observer) { | 460 void MultiUserWindowManagerChromeOS::RemoveObserver(Observer* observer) { |
| 457 observers_.RemoveObserver(observer); | 461 observers_.RemoveObserver(observer); |
| 458 } | 462 } |
| 459 | 463 |
| 460 void MultiUserWindowManagerChromeOS::ActiveUserChanged( | 464 void MultiUserWindowManagerChromeOS::ActiveUserChanged( |
| 461 const std::string& user_id) { | 465 const AccountId& account_id) { |
| 462 // This needs to be set before the animation starts. | 466 // This needs to be set before the animation starts. |
| 463 current_user_id_ = user_id; | 467 current_account_id_ = account_id; |
| 464 | 468 |
| 465 // Here to avoid a very nasty race condition, we must destruct any previously | 469 // Here to avoid a very nasty race condition, we must destruct any previously |
| 466 // created animation before creating a new one. Otherwise, the newly | 470 // created animation before creating a new one. Otherwise, the newly |
| 467 // constructed will hide all windows of the old user in the first step of the | 471 // constructed will hide all windows of the old user in the first step of the |
| 468 // animation only to be reshown again by the destructor of the old animation. | 472 // animation only to be reshown again by the destructor of the old animation. |
| 469 animation_.reset(); | 473 animation_.reset(); |
| 470 animation_.reset( | 474 animation_.reset(new UserSwitchAnimatorChromeOS( |
| 471 new UserSwitchAnimatorChromeOS( | 475 this, account_id, GetAdjustedAnimationTimeInMS(kUserFadeTimeMS))); |
| 472 this, user_id, GetAdjustedAnimationTimeInMS(kUserFadeTimeMS))); | |
| 473 // Call notifier here instead of observing ActiveUserChanged because | 476 // Call notifier here instead of observing ActiveUserChanged because |
| 474 // this must happen after MultiUserWindowManagerChromeOS is notified. | 477 // this must happen after MultiUserWindowManagerChromeOS is notified. |
| 475 ash::Shell::GetInstance() | 478 ash::Shell::GetInstance() |
| 476 ->system_tray_notifier() | 479 ->system_tray_notifier() |
| 477 ->NotifyMediaCaptureChanged(); | 480 ->NotifyMediaCaptureChanged(); |
| 478 } | 481 } |
| 479 | 482 |
| 480 void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) { | 483 void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) { |
| 481 if (GetWindowOwner(window).empty()) { | 484 if (GetWindowOwner(window).empty()) { |
| 482 // This must be a window in the transient chain - remove it and its | 485 // This must be a window in the transient chain - remove it and its |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 it->second = visible; | 519 it->second = visible; |
| 517 } | 520 } |
| 518 } | 521 } |
| 519 | 522 |
| 520 void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanged( | 523 void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanged( |
| 521 aura::Window* window, bool visible) { | 524 aura::Window* window, bool visible) { |
| 522 if (suppress_visibility_changes_) | 525 if (suppress_visibility_changes_) |
| 523 return; | 526 return; |
| 524 | 527 |
| 525 // Don't allow to make the window visible if it shouldn't be. | 528 // Don't allow to make the window visible if it shouldn't be. |
| 526 if (visible && !IsWindowOnDesktopOfUser(window, current_user_id_)) { | 529 if (visible && !IsWindowOnDesktopOfUser(window, current_account_id_)) { |
| 527 SetWindowVisibility(window, false, 0); | 530 SetWindowVisibility(window, false, 0); |
| 528 return; | 531 return; |
| 529 } | 532 } |
| 530 aura::Window* owned_parent = GetOwningWindowInTransientChain(window); | 533 aura::Window* owned_parent = GetOwningWindowInTransientChain(window); |
| 531 if (owned_parent && owned_parent != window && visible && | 534 if (owned_parent && owned_parent != window && visible && |
| 532 !IsWindowOnDesktopOfUser(owned_parent, current_user_id_)) | 535 !IsWindowOnDesktopOfUser(owned_parent, current_account_id_)) |
| 533 SetWindowVisibility(window, false, 0); | 536 SetWindowVisibility(window, false, 0); |
| 534 } | 537 } |
| 535 | 538 |
| 536 void MultiUserWindowManagerChromeOS::OnTransientChildAdded( | 539 void MultiUserWindowManagerChromeOS::OnTransientChildAdded( |
| 537 aura::Window* window, | 540 aura::Window* window, |
| 538 aura::Window* transient_window) { | 541 aura::Window* transient_window) { |
| 539 if (!GetWindowOwner(window).empty()) { | 542 if (!GetWindowOwner(window).empty()) { |
| 540 AddTransientOwnerRecursive(transient_window, window); | 543 AddTransientOwnerRecursive(transient_window, window); |
| 541 return; | 544 return; |
| 542 } | 545 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 568 | 571 |
| 569 void MultiUserWindowManagerChromeOS::SetAnimationSpeedForTest( | 572 void MultiUserWindowManagerChromeOS::SetAnimationSpeedForTest( |
| 570 MultiUserWindowManagerChromeOS::AnimationSpeed speed) { | 573 MultiUserWindowManagerChromeOS::AnimationSpeed speed) { |
| 571 animation_speed_ = speed; | 574 animation_speed_ = speed; |
| 572 } | 575 } |
| 573 | 576 |
| 574 bool MultiUserWindowManagerChromeOS::IsAnimationRunningForTest() { | 577 bool MultiUserWindowManagerChromeOS::IsAnimationRunningForTest() { |
| 575 return animation_.get() != NULL && !animation_->IsAnimationFinished(); | 578 return animation_.get() != NULL && !animation_->IsAnimationFinished(); |
| 576 } | 579 } |
| 577 | 580 |
| 578 const std::string& MultiUserWindowManagerChromeOS::GetCurrentUserForTest() | 581 const AccountId& MultiUserWindowManagerChromeOS::GetCurrentUserForTest() const { |
| 579 const { | 582 return current_account_id_; |
| 580 return current_user_id_; | |
| 581 } | 583 } |
| 582 | 584 |
| 583 bool MultiUserWindowManagerChromeOS::ShowWindowForUserIntern( | 585 bool MultiUserWindowManagerChromeOS::ShowWindowForUserIntern( |
| 584 aura::Window* window, | 586 aura::Window* window, |
| 585 const std::string& user_id) { | 587 const AccountId& account_id) { |
| 586 // If there is either no owner, or the owner is the current user, no action | 588 // If there is either no owner, or the owner is the current user, no action |
| 587 // is required. | 589 // is required. |
| 588 const std::string& owner = GetWindowOwner(window); | 590 const AccountId& owner = GetWindowOwner(window); |
| 589 if (owner.empty() || | 591 if ((!owner.is_valid()) || |
| 590 (owner == user_id && IsWindowOnDesktopOfUser(window, user_id))) | 592 (owner == account_id && IsWindowOnDesktopOfUser(window, account_id))) |
| 591 return false; | 593 return false; |
| 592 | 594 |
| 593 bool minimized = ash::wm::GetWindowState(window)->IsMinimized(); | 595 bool minimized = ash::wm::GetWindowState(window)->IsMinimized(); |
| 594 // Check that we are not trying to transfer ownership of a minimized window. | 596 // Check that we are not trying to transfer ownership of a minimized window. |
| 595 if (user_id != owner && minimized) | 597 if (account_id != owner && minimized) |
| 596 return false; | 598 return false; |
| 597 | 599 |
| 598 if (minimized) { | 600 if (minimized) { |
| 599 // If it is minimized it falls back to the original desktop. | 601 // If it is minimized it falls back to the original desktop. |
| 600 ash::MultiProfileUMA::RecordTeleportAction( | 602 ash::MultiProfileUMA::RecordTeleportAction( |
| 601 ash::MultiProfileUMA::TELEPORT_WINDOW_RETURN_BY_MINIMIZE); | 603 ash::MultiProfileUMA::TELEPORT_WINDOW_RETURN_BY_MINIMIZE); |
| 602 } else { | 604 } else { |
| 603 // If the window was transferred without getting minimized, we should record | 605 // If the window was transferred without getting minimized, we should record |
| 604 // the window type. | 606 // the window type. |
| 605 RecordUMAForTransferredWindowType(window); | 607 RecordUMAForTransferredWindowType(window); |
| 606 } | 608 } |
| 607 | 609 |
| 608 WindowToEntryMap::iterator it = window_to_entry_.find(window); | 610 WindowToEntryMap::iterator it = window_to_entry_.find(window); |
| 609 it->second->set_show_for_user(user_id); | 611 it->second->set_show_for_user(account_id); |
| 610 | 612 |
| 611 // Show the window if the added user is the current one. | 613 // Show the window if the added user is the current one. |
| 612 if (user_id == current_user_id_) { | 614 if (account_id == current_account_id_) { |
| 613 // Only show the window if it should be shown according to its state. | 615 // Only show the window if it should be shown according to its state. |
| 614 if (it->second->show()) | 616 if (it->second->show()) |
| 615 SetWindowVisibility(window, true, kTeleportAnimationTimeMS); | 617 SetWindowVisibility(window, true, kTeleportAnimationTimeMS); |
| 616 } else { | 618 } else { |
| 617 SetWindowVisibility(window, false, kTeleportAnimationTimeMS); | 619 SetWindowVisibility(window, false, kTeleportAnimationTimeMS); |
| 618 } | 620 } |
| 619 | 621 |
| 620 // Notify entry change. | 622 // Notify entry change. |
| 621 FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryChanged(window)); | 623 FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryChanged(window)); |
| 622 return true; | 624 return true; |
| 623 } | 625 } |
| 624 | 626 |
| 625 void MultiUserWindowManagerChromeOS::SetWindowVisibility( | 627 void MultiUserWindowManagerChromeOS::SetWindowVisibility( |
| 626 aura::Window* window, bool visible, int animation_time_in_ms) { | 628 aura::Window* window, bool visible, int animation_time_in_ms) { |
| 627 if (window->IsVisible() == visible) | 629 if (window->IsVisible() == visible) |
| 628 return; | 630 return; |
| 629 | 631 |
| 630 // Hiding a system modal dialog should not be allowed. Instead we switch to | 632 // Hiding a system modal dialog should not be allowed. Instead we switch to |
| 631 // the user which is showing the system modal window. | 633 // the user which is showing the system modal window. |
| 632 // Note that in some cases (e.g. unit test) windows might not have a root | 634 // Note that in some cases (e.g. unit test) windows might not have a root |
| 633 // window. | 635 // window. |
| 634 if (!visible && window->GetRootWindow()) { | 636 if (!visible && window->GetRootWindow()) { |
| 635 // Get the system modal container for the window's root window. | 637 // Get the system modal container for the window's root window. |
| 636 aura::Window* system_modal_container = | 638 aura::Window* system_modal_container = |
| 637 window->GetRootWindow()->GetChildById( | 639 window->GetRootWindow()->GetChildById( |
| 638 ash::kShellWindowId_SystemModalContainer); | 640 ash::kShellWindowId_SystemModalContainer); |
| 639 if (window->parent() == system_modal_container) { | 641 if (window->parent() == system_modal_container) { |
| 640 // The window is system modal and we need to find the parent which owns | 642 // The window is system modal and we need to find the parent which owns |
| 641 // it so that we can switch to the desktop accordingly. | 643 // it so that we can switch to the desktop accordingly. |
| 642 std::string user_id = GetUserPresentingWindow(window); | 644 AccountId account_id = GetUserPresentingWindow(window); |
| 643 if (user_id.empty()) { | 645 if (!account_id.is_valid()) { |
| 644 aura::Window* owning_window = GetOwningWindowInTransientChain(window); | 646 aura::Window* owning_window = GetOwningWindowInTransientChain(window); |
| 645 DCHECK(owning_window); | 647 DCHECK(owning_window); |
| 646 user_id = GetUserPresentingWindow(owning_window); | 648 account_id = GetUserPresentingWindow(owning_window); |
| 647 DCHECK(!user_id.empty()); | 649 DCHECK(account_id.is_valid()); |
| 648 } | 650 } |
| 649 ash::Shell::GetInstance()->session_state_delegate()->SwitchActiveUser( | 651 ash::Shell::GetInstance()->session_state_delegate()->SwitchActiveUser( |
| 650 user_id); | 652 account_id); |
| 651 return; | 653 return; |
| 652 } | 654 } |
| 653 } | 655 } |
| 654 | 656 |
| 655 // To avoid that these commands are recorded as any other commands, we are | 657 // To avoid that these commands are recorded as any other commands, we are |
| 656 // suppressing any window entry changes while this is going on. | 658 // suppressing any window entry changes while this is going on. |
| 657 base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true); | 659 base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true); |
| 658 | 660 |
| 659 if (visible) | 661 if (visible) |
| 660 ShowWithTransientChildrenRecursive(window, animation_time_in_ms); | 662 ShowWithTransientChildrenRecursive(window, animation_time_in_ms); |
| 661 else | 663 else |
| 662 SetWindowVisible(window, false, animation_time_in_ms); | 664 SetWindowVisible(window, false, animation_time_in_ms); |
| 663 } | 665 } |
| 664 | 666 |
| 665 void MultiUserWindowManagerChromeOS::AddBrowserWindow(Browser* browser) { | 667 void MultiUserWindowManagerChromeOS::AddBrowserWindow(Browser* browser) { |
| 666 // A unit test (e.g. CrashRestoreComplexTest.RestoreSessionForThreeUsers) can | 668 // A unit test (e.g. CrashRestoreComplexTest.RestoreSessionForThreeUsers) can |
| 667 // come here with no valid window. | 669 // come here with no valid window. |
| 668 if (!browser->window() || !browser->window()->GetNativeWindow()) | 670 if (!browser->window() || !browser->window()->GetNativeWindow()) |
| 669 return; | 671 return; |
| 670 SetWindowOwner(browser->window()->GetNativeWindow(), | 672 SetWindowOwner(browser->window()->GetNativeWindow(), |
| 671 multi_user_util::GetUserIDFromProfile(browser->profile())); | 673 multi_user_util::GetAccountIdFromProfile(browser->profile())); |
| 672 } | 674 } |
| 673 | 675 |
| 674 void MultiUserWindowManagerChromeOS::ShowWithTransientChildrenRecursive( | 676 void MultiUserWindowManagerChromeOS::ShowWithTransientChildrenRecursive( |
| 675 aura::Window* window, int animation_time_in_ms) { | 677 aura::Window* window, int animation_time_in_ms) { |
| 676 aura::Window::Windows::const_iterator it = | 678 aura::Window::Windows::const_iterator it = |
| 677 wm::GetTransientChildren(window).begin(); | 679 wm::GetTransientChildren(window).begin(); |
| 678 for (; it != wm::GetTransientChildren(window).end(); ++it) | 680 for (; it != wm::GetTransientChildren(window).end(); ++it) |
| 679 ShowWithTransientChildrenRecursive(*it, animation_time_in_ms); | 681 ShowWithTransientChildrenRecursive(*it, animation_time_in_ms); |
| 680 | 682 |
| 681 // We show all children which were not explicitly hidden. | 683 // We show all children which were not explicitly hidden. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 transient_window_to_visibility_.end()); | 718 transient_window_to_visibility_.end()); |
| 717 transient_window_to_visibility_[window] = window->IsVisible(); | 719 transient_window_to_visibility_[window] = window->IsVisible(); |
| 718 | 720 |
| 719 // Add observers to track state changes. | 721 // Add observers to track state changes. |
| 720 window->AddObserver(this); | 722 window->AddObserver(this); |
| 721 wm::TransientWindowManager::Get(window)->AddObserver(this); | 723 wm::TransientWindowManager::Get(window)->AddObserver(this); |
| 722 | 724 |
| 723 // Hide the window if it should not be shown. Note that this hide operation | 725 // Hide the window if it should not be shown. Note that this hide operation |
| 724 // will hide recursively this and all children - but we have already collected | 726 // will hide recursively this and all children - but we have already collected |
| 725 // their initial view state. | 727 // their initial view state. |
| 726 if (!IsWindowOnDesktopOfUser(owned_parent, current_user_id_)) | 728 if (!IsWindowOnDesktopOfUser(owned_parent, current_account_id_)) |
| 727 SetWindowVisibility(window, false, kAnimationTimeMS); | 729 SetWindowVisibility(window, false, kAnimationTimeMS); |
| 728 } | 730 } |
| 729 | 731 |
| 730 void MultiUserWindowManagerChromeOS::RemoveTransientOwnerRecursive( | 732 void MultiUserWindowManagerChromeOS::RemoveTransientOwnerRecursive( |
| 731 aura::Window* window) { | 733 aura::Window* window) { |
| 732 // First remove all child windows. | 734 // First remove all child windows. |
| 733 aura::Window::Windows::const_iterator it = | 735 aura::Window::Windows::const_iterator it = |
| 734 wm::GetTransientChildren(window).begin(); | 736 wm::GetTransientChildren(window).begin(); |
| 735 for (; it != wm::GetTransientChildren(window).end(); ++it) | 737 for (; it != wm::GetTransientChildren(window).end(); ++it) |
| 736 RemoveTransientOwnerRecursive(*it); | 738 RemoveTransientOwnerRecursive(*it); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 780 // call. | 782 // call. |
| 781 DCHECK_EQ(visible, window->IsVisible()); | 783 DCHECK_EQ(visible, window->IsVisible()); |
| 782 } | 784 } |
| 783 | 785 |
| 784 int MultiUserWindowManagerChromeOS::GetAdjustedAnimationTimeInMS( | 786 int MultiUserWindowManagerChromeOS::GetAdjustedAnimationTimeInMS( |
| 785 int default_time_in_ms) const { | 787 int default_time_in_ms) const { |
| 786 return animation_speed_ == ANIMATION_SPEED_NORMAL ? default_time_in_ms : | 788 return animation_speed_ == ANIMATION_SPEED_NORMAL ? default_time_in_ms : |
| 787 (animation_speed_ == ANIMATION_SPEED_FAST ? 10 : 0); | 789 (animation_speed_ == ANIMATION_SPEED_FAST ? 10 : 0); |
| 788 } | 790 } |
| 789 | 791 |
| 790 void MultiUserWindowManagerChromeOS::RemoveUser(const std::string& user_id, | 792 void MultiUserWindowManagerChromeOS::RemoveUser(const AccountId& account_id, |
| 791 Profile* profile) { | 793 Profile* profile) { |
| 792 UserIDToAppWindowObserver::iterator app_observer_iterator = | 794 AccountIdToAppWindowObserver::iterator app_observer_iterator = |
| 793 user_id_to_app_observer_.find(user_id); | 795 account_id_to_app_observer_.find(account_id); |
| 794 DCHECK(app_observer_iterator != user_id_to_app_observer_.end()) | 796 DCHECK(app_observer_iterator != account_id_to_app_observer_.end()) |
| 795 << "User id '" << user_id << "', profile=" << profile | 797 << "User id '" << account_id.GetUserEmail() << "', profile=" << profile |
| 796 << " was not found."; | 798 << " was not found."; |
| 797 if (app_observer_iterator == user_id_to_app_observer_.end()) | 799 if (app_observer_iterator == account_id_to_app_observer_.end()) |
| 798 return; | 800 return; |
| 799 | 801 |
| 800 extensions::AppWindowRegistry::Get(profile) | 802 extensions::AppWindowRegistry::Get(profile) |
| 801 ->RemoveObserver(app_observer_iterator->second); | 803 ->RemoveObserver(app_observer_iterator->second); |
| 802 delete app_observer_iterator->second; | 804 delete app_observer_iterator->second; |
| 803 user_id_to_app_observer_.erase(app_observer_iterator); | 805 account_id_to_app_observer_.erase(app_observer_iterator); |
| 804 } | 806 } |
| 805 | 807 |
| 806 } // namespace chrome | 808 } // namespace chrome |
| OLD | NEW |