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