1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/profiles/user_manager_view.h"
7 #include "base/time/time.h"
8 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/lifetime/application_lifetime.h"
10 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
11 #include "chrome/browser/profiles/profile_manager.h"
12 #include "chrome/browser/profiles/profile_metrics.h"
13 #include "chrome/browser/profiles/profile_window.h"
14 #include "chrome/browser/profiles/profiles_state.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_dialogs.h"
17 #include "chrome/browser/ui/browser_finder.h"
18 #include "chrome/browser/ui/browser_window.h"
19 #include "chrome/browser/ui/user_manager.h"
20 #include "chrome/browser/ui/views/auto_keep_alive.h"
21 #include "chrome/grit/chromium_strings.h"
22 #include "content/public/browser/render_widget_host_view.h"
23 #include "content/public/browser/web_contents.h"
24 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/gfx/screen.h"
26 #include "ui/views/controls/webview/webview.h"
27 #include "ui/views/layout/fill_layout.h"
28 #include "ui/views/view.h"
29 #include "ui/views/widget/widget.h"
30 #include "ui/views/window/dialog_client_view.h"
33 #include "chrome/browser/shell_integration.h"
34 #include "ui/base/win/shell.h"
35 #include "ui/views/win/hwnd_util.h"
39 #include "ash/shelf/shelf_util.h"
40 #include "ash/wm/window_util.h"
41 #include "grit/ash_resources.h"
46 // An open User Manager window. There can only be one open at a time. This
47 // is reset to NULL when the window is closed.
48 UserManagerView
* instance_
= NULL
;
52 // UserManager -----------------------------------------------------------------
54 void UserManager::Show(
55 const base::FilePath
& profile_path_to_focus
,
56 profiles::UserManagerTutorialMode tutorial_mode
,
57 profiles::UserManagerProfileSelected profile_open_action
) {
58 DCHECK(profile_path_to_focus
!= ProfileManager::GetGuestProfilePath());
60 ProfileMetrics::LogProfileOpenMethod(ProfileMetrics::OPEN_USER_MANAGER
);
62 // If we are showing the User Manager after locking a profile, change the
63 // active profile to Guest.
64 profiles::SetActiveProfileToGuestIfLocked();
66 // Note the time we started opening the User Manager.
67 instance_
->set_user_manager_started_showing(base::Time::Now());
69 // If there's a user manager window open already, just activate it.
70 instance_
->GetWidget()->Activate();
74 // Create the system profile, if necessary, and open the user manager
75 // from the system profile.
76 UserManagerView
* user_manager
= new UserManagerView();
77 user_manager
->set_user_manager_started_showing(base::Time::Now());
78 profiles::CreateSystemProfileForUserManager(
79 profile_path_to_focus
,
82 base::Bind(&UserManagerView::OnSystemProfileCreated
,
83 base::Passed(make_scoped_ptr(user_manager
))));
86 void UserManager::Hide() {
88 instance_
->GetWidget()->Close();
91 bool UserManager::IsShowing() {
92 return instance_
? instance_
->GetWidget()->IsActive() : false;
95 void UserManager::OnUserManagerShown() {
97 instance_
->LogTimeToOpen();
100 // UserManagerView -------------------------------------------------------------
102 UserManagerView::UserManagerView()
104 keep_alive_(new AutoKeepAlive(NULL
)),
105 user_manager_started_showing_(base::Time()) {
108 UserManagerView::~UserManagerView() {
112 void UserManagerView::OnSystemProfileCreated(
113 scoped_ptr
<UserManagerView
> instance
,
114 Profile
* system_profile
,
115 const std::string
& url
) {
116 // If we are showing the User Manager after locking a profile, change the
117 // active profile to Guest.
118 profiles::SetActiveProfileToGuestIfLocked();
121 instance_
= instance
.release(); // |instance_| takes over ownership.
122 instance_
->Init(system_profile
, GURL(url
));
125 void UserManagerView::Init(Profile
* system_profile
, const GURL
& url
) {
126 web_view_
= new views::WebView(system_profile
);
127 web_view_
->set_allow_accelerators(true);
128 AddChildView(web_view_
);
129 SetLayoutManager(new views::FillLayout
);
130 AddAccelerator(ui::Accelerator(ui::VKEY_W
, ui::EF_CONTROL_DOWN
));
131 AddAccelerator(ui::Accelerator(ui::VKEY_F4
, ui::EF_ALT_DOWN
));
133 // If the user manager is being displayed from an existing profile, use
134 // its last active browser to determine where the user manager should be
135 // placed. This is used so that we can center the dialog on the correct
136 // monitor in a multiple-monitor setup.
138 // If the last active profile is empty (for example, starting up chrome
139 // when all existing profiles are locked), not loaded (for example, if guest
140 // was set after locking the only open profile) or we can't find an active
141 // browser, bounds will remain empty and the user manager will be centered on
142 // the default monitor by default.
144 // Note the profile is accessed via GetProfileByPath(GetLastUsedProfileDir())
145 // instead of GetLastUsedProfile(). If the last active profile isn't loaded,
146 // the latter may try to synchronously load it, which can only be done on a
147 // thread where disk IO is allowed.
149 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
150 const base::FilePath
& last_used_profile_path
=
151 profile_manager
->GetLastUsedProfileDir(profile_manager
->user_data_dir());
152 Profile
* profile
= profile_manager
->GetProfileByPath(last_used_profile_path
);
154 Browser
* browser
= chrome::FindLastActiveWithProfile(profile
,
155 chrome::GetActiveDesktop());
157 gfx::NativeView native_view
=
158 views::Widget::GetWidgetForNativeWindow(
159 browser
->window()->GetNativeWindow())->GetNativeView();
160 bounds
= gfx::Screen::GetScreenFor(native_view
)->
161 GetDisplayNearestWindow(native_view
).work_area();
162 bounds
.ClampToCenteredSize(gfx::Size(UserManager::kWindowWidth
,
163 UserManager::kWindowHeight
));
167 DialogDelegate::CreateDialogWidgetWithBounds(this, NULL
, NULL
, bounds
);
169 // Since the User Manager can be the only top level window, we don't
170 // want to accidentally quit all of Chrome if the user is just trying to
171 // unfocus the selected pod in the WebView.
172 GetDialogClientView()->RemoveAccelerator(
173 ui::Accelerator(ui::VKEY_ESCAPE
, ui::EF_NONE
));
176 // Set the app id for the task manager to the app id of its parent
177 ui::win::SetAppIdForWindow(
178 ShellIntegration::GetChromiumModelIdForProfile(
179 system_profile
->GetPath()),
180 views::HWNDForWidget(GetWidget()));
184 gfx::NativeWindow native_window
= GetWidget()->GetNativeWindow();
185 ash::SetShelfItemDetailsForDialogWindow(
186 native_window
, IDR_ASH_SHELF_LIST_BROWSER
, native_window
->title());
189 web_view_
->LoadInitialURL(url
);
190 content::RenderWidgetHostView
* rwhv
=
191 web_view_
->GetWebContents()->GetRenderWidgetHostView();
193 rwhv
->SetBackgroundColor(profiles::kUserManagerBackgroundColor
);
196 web_view_
->RequestFocus();
199 void UserManagerView::LogTimeToOpen() {
200 if (user_manager_started_showing_
== base::Time())
203 ProfileMetrics::LogTimeToOpenUserManager(
204 base::Time::Now() - user_manager_started_showing_
);
205 user_manager_started_showing_
= base::Time();
208 bool UserManagerView::AcceleratorPressed(const ui::Accelerator
& accelerator
) {
209 int key
= accelerator
.key_code();
210 int modifier
= accelerator
.modifiers();
211 DCHECK((key
== ui::VKEY_W
&& modifier
== ui::EF_CONTROL_DOWN
) ||
212 (key
== ui::VKEY_F4
&& modifier
== ui::EF_ALT_DOWN
));
213 GetWidget()->Close();
217 gfx::Size
UserManagerView::GetPreferredSize() const {
218 return gfx::Size(UserManager::kWindowWidth
, UserManager::kWindowHeight
);
221 bool UserManagerView::CanResize() const {
225 bool UserManagerView::CanMaximize() const {
229 bool UserManagerView::CanMinimize() const {
233 base::string16
UserManagerView::GetWindowTitle() const {
234 return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME
);
237 int UserManagerView::GetDialogButtons() const {
238 return ui::DIALOG_BUTTON_NONE
;
241 void UserManagerView::WindowClosing() {
242 // Now that the window is closed, we can allow a new one to be opened.
243 // (WindowClosing comes in asynchronously from the call to Close() and we
244 // may have already opened a new instance).
245 if (instance_
== this)
249 bool UserManagerView::UseNewStyleForThisDialog() const {