Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / views / profiles / user_manager_view.cc
blob8e6c6a7498a9ecd1fb3546edad864dd8848bcd0d
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/memory/scoped_ptr.h"
8 #include "base/time/time.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/lifetime/application_lifetime.h"
11 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
12 #include "chrome/browser/profiles/profile_manager.h"
13 #include "chrome/browser/profiles/profile_metrics.h"
14 #include "chrome/browser/profiles/profile_window.h"
15 #include "chrome/browser/profiles/profiles_state.h"
16 #include "chrome/browser/signin/signin_promo.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_dialogs.h"
19 #include "chrome/browser/ui/browser_finder.h"
20 #include "chrome/browser/ui/browser_window.h"
21 #include "chrome/browser/ui/user_manager.h"
22 #include "chrome/browser/ui/views/auto_keep_alive.h"
23 #include "chrome/browser/ui/views/browser_dialogs.h"
24 #include "chrome/grit/chromium_strings.h"
25 #include "chrome/grit/generated_resources.h"
26 #include "components/guest_view/browser/guest_view_manager.h"
27 #include "content/public/browser/navigation_details.h"
28 #include "content/public/browser/render_widget_host_view.h"
29 #include "content/public/browser/web_contents.h"
30 #include "google_apis/gaia/gaia_urls.h"
31 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/gfx/screen.h"
33 #include "ui/views/controls/webview/webview.h"
34 #include "ui/views/layout/fill_layout.h"
35 #include "ui/views/view.h"
36 #include "ui/views/widget/widget.h"
37 #include "ui/views/window/dialog_client_view.h"
38 #include "ui/views/window/dialog_delegate.h"
40 #if defined(OS_WIN)
41 #include "chrome/browser/shell_integration.h"
42 #include "ui/base/win/shell.h"
43 #include "ui/views/win/hwnd_util.h"
44 #endif
46 #if defined(USE_ASH)
47 #include "ash/shelf/shelf_util.h"
48 #include "ash/wm/window_util.h"
49 #include "grit/ash_resources.h"
50 #endif
52 namespace {
54 // An open User Manager window. There can only be one open at a time. This
55 // is reset to NULL when the window is closed.
56 UserManagerView* instance_ = NULL;
57 bool instance_under_construction_ = false;
59 class ReauthDelegate : public views::DialogDelegateView,
60 public UserManager::ReauthDialogObserver {
61 public:
62 ReauthDelegate(views::WebView* web_view,
63 const std::string& email_address);
64 ~ReauthDelegate() override {}
66 private:
67 ReauthDelegate();
68 // views::DialogDelegate:
69 gfx::Size GetPreferredSize() const override;
70 bool CanResize() const override;
71 bool CanMaximize() const override;
72 bool CanMinimize() const override;
73 bool UseNewStyleForThisDialog() const override;
74 ui::ModalType GetModalType() const override;
75 void DeleteDelegate() override;
76 base::string16 GetWindowTitle() const override;
77 int GetDialogButtons() const override;
78 views::View* GetInitiallyFocusedView() override;
80 // UserManager::ReauthObserver:
81 void CloseReauthDialog() override;
83 views::WebView* web_view_;
84 const std::string email_address_;
86 DISALLOW_COPY_AND_ASSIGN(ReauthDelegate);
89 ReauthDelegate::ReauthDelegate(views::WebView* web_view,
90 const std::string& email_address)
91 : UserManager::ReauthDialogObserver(
92 web_view->GetWebContents(), email_address),
93 web_view_(web_view),
94 email_address_(email_address) {
95 AddChildView(web_view_);
96 SetLayoutManager(new views::FillLayout());
98 // Load the re-auth URL, prepopulated with the user's email address.
99 // Add the index of the profile to the URL so that the inline login page
100 // knows which profile to load and update the credentials.
101 GURL url = signin::GetReauthURLWithEmail(email_address_);
102 web_view_->LoadInitialURL(url);
105 gfx::Size ReauthDelegate::GetPreferredSize() const {
106 return gfx::Size(UserManager::kReauthDialogWidth,
107 UserManager::kReauthDialogHeight);
110 bool ReauthDelegate::CanResize() const {
111 return true;
114 bool ReauthDelegate::CanMaximize() const {
115 return true;
118 bool ReauthDelegate::CanMinimize() const {
119 return true;
122 bool ReauthDelegate::UseNewStyleForThisDialog() const {
123 return false;
126 ui::ModalType ReauthDelegate::GetModalType() const {
127 return ui::MODAL_TYPE_WINDOW;
130 void ReauthDelegate::DeleteDelegate() {
131 delete this;
134 base::string16 ReauthDelegate::GetWindowTitle() const {
135 return l10n_util::GetStringUTF16(IDS_PROFILES_GAIA_SIGNIN_TITLE);
138 int ReauthDelegate::GetDialogButtons() const {
139 return ui::DIALOG_BUTTON_NONE;
142 views::View* ReauthDelegate::GetInitiallyFocusedView() {
143 return static_cast<views::View*>(web_view_);
146 void ReauthDelegate::CloseReauthDialog() {
147 GetWidget()->Close();
150 } // namespace
152 // UserManager -----------------------------------------------------------------
154 // static
155 void UserManager::Show(
156 const base::FilePath& profile_path_to_focus,
157 profiles::UserManagerTutorialMode tutorial_mode,
158 profiles::UserManagerProfileSelected profile_open_action) {
159 DCHECK(profile_path_to_focus != ProfileManager::GetGuestProfilePath());
161 ProfileMetrics::LogProfileOpenMethod(ProfileMetrics::OPEN_USER_MANAGER);
162 if (instance_) {
163 // If we are showing the User Manager after locking a profile, change the
164 // active profile to Guest.
165 profiles::SetActiveProfileToGuestIfLocked();
167 // Note the time we started opening the User Manager.
168 instance_->set_user_manager_started_showing(base::Time::Now());
170 // If there's a user manager window open already, just activate it.
171 instance_->GetWidget()->Activate();
172 return;
175 // Under some startup conditions, we can try twice to create the User Manager.
176 // Because creating the System profile is asynchronous, it's possible for
177 // there to then be multiple pending operations and eventually multiple
178 // User Managers.
179 if (instance_under_construction_)
180 return;
182 // Create the system profile, if necessary, and open the user manager
183 // from the system profile.
184 UserManagerView* user_manager = new UserManagerView();
185 user_manager->set_user_manager_started_showing(base::Time::Now());
186 profiles::CreateSystemProfileForUserManager(
187 profile_path_to_focus,
188 tutorial_mode,
189 profile_open_action,
190 base::Bind(&UserManagerView::OnSystemProfileCreated,
191 base::Passed(make_scoped_ptr(user_manager)),
192 base::Owned(new base::AutoReset<bool>(
193 &instance_under_construction_, true))));
196 // static
197 void UserManager::Hide() {
198 if (instance_)
199 instance_->GetWidget()->Close();
202 // static
203 bool UserManager::IsShowing() {
204 return instance_ ? instance_->GetWidget()->IsActive() : false;
207 // static
208 void UserManager::OnUserManagerShown() {
209 if (instance_)
210 instance_->LogTimeToOpen();
213 // static
214 void UserManager::ShowReauthDialog(content::BrowserContext* browser_context,
215 const std::string& email) {
216 // This method should only be called if the user manager is already showing.
217 if (!IsShowing())
218 return;
220 // The dialog delegate will be deleted when the dialog closes and the created
221 // WebView's lifetime is managed by the delegate.
222 views::DialogDelegate* delegate =
223 new ReauthDelegate(new views::WebView(browser_context), email);
224 gfx::NativeView parent = instance_->GetWidget()->GetNativeView();
225 views::DialogDelegate::CreateDialogWidget(delegate, nullptr, parent);
226 delegate->GetWidget()->Show();
229 // UserManagerView -------------------------------------------------------------
231 UserManagerView::UserManagerView()
232 : web_view_(NULL),
233 keep_alive_(new AutoKeepAlive(NULL)),
234 user_manager_started_showing_(base::Time()) {
237 UserManagerView::~UserManagerView() {
240 // static
241 void UserManagerView::OnSystemProfileCreated(
242 scoped_ptr<UserManagerView> instance,
243 base::AutoReset<bool>* pending,
244 Profile* system_profile,
245 const std::string& url) {
246 // If we are showing the User Manager after locking a profile, change the
247 // active profile to Guest.
248 profiles::SetActiveProfileToGuestIfLocked();
250 DCHECK(!instance_);
251 instance_ = instance.release(); // |instance_| takes over ownership.
252 instance_->Init(system_profile, GURL(url));
255 void UserManagerView::Init(Profile* system_profile, const GURL& url) {
256 web_view_ = new views::WebView(system_profile);
257 web_view_->set_allow_accelerators(true);
258 AddChildView(web_view_);
259 SetLayoutManager(new views::FillLayout);
260 AddAccelerator(ui::Accelerator(ui::VKEY_W, ui::EF_CONTROL_DOWN));
261 AddAccelerator(ui::Accelerator(ui::VKEY_F4, ui::EF_ALT_DOWN));
263 // If the user manager is being displayed from an existing profile, use
264 // its last active browser to determine where the user manager should be
265 // placed. This is used so that we can center the dialog on the correct
266 // monitor in a multiple-monitor setup.
268 // If the last active profile is empty (for example, starting up chrome
269 // when all existing profiles are locked), not loaded (for example, if guest
270 // was set after locking the only open profile) or we can't find an active
271 // browser, bounds will remain empty and the user manager will be centered on
272 // the default monitor by default.
274 // Note the profile is accessed via GetProfileByPath(GetLastUsedProfileDir())
275 // instead of GetLastUsedProfile(). If the last active profile isn't loaded,
276 // the latter may try to synchronously load it, which can only be done on a
277 // thread where disk IO is allowed.
278 gfx::Rect bounds;
279 ProfileManager* profile_manager = g_browser_process->profile_manager();
280 const base::FilePath& last_used_profile_path =
281 profile_manager->GetLastUsedProfileDir(profile_manager->user_data_dir());
282 Profile* profile = profile_manager->GetProfileByPath(last_used_profile_path);
283 if (profile) {
284 Browser* browser = chrome::FindLastActiveWithProfile(profile,
285 chrome::GetActiveDesktop());
286 if (browser) {
287 gfx::NativeView native_view =
288 views::Widget::GetWidgetForNativeWindow(
289 browser->window()->GetNativeWindow())->GetNativeView();
290 bounds = gfx::Screen::GetScreenFor(native_view)->
291 GetDisplayNearestWindow(native_view).work_area();
292 bounds.ClampToCenteredSize(gfx::Size(UserManager::kWindowWidth,
293 UserManager::kWindowHeight));
297 DialogDelegate::CreateDialogWidgetWithBounds(this, NULL, NULL, bounds);
299 // Since the User Manager can be the only top level window, we don't
300 // want to accidentally quit all of Chrome if the user is just trying to
301 // unfocus the selected pod in the WebView.
302 GetDialogClientView()->RemoveAccelerator(
303 ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
305 #if defined(OS_WIN)
306 // Set the app id for the task manager to the app id of its parent
307 ui::win::SetAppIdForWindow(
308 ShellIntegration::GetChromiumModelIdForProfile(
309 system_profile->GetPath()),
310 views::HWNDForWidget(GetWidget()));
311 #endif
313 #if defined(USE_ASH)
314 gfx::NativeWindow native_window = GetWidget()->GetNativeWindow();
315 ash::SetShelfItemDetailsForDialogWindow(
316 native_window, IDR_ASH_SHELF_LIST_BROWSER, native_window->title());
317 #endif
319 web_view_->LoadInitialURL(url);
320 content::RenderWidgetHostView* rwhv =
321 web_view_->GetWebContents()->GetRenderWidgetHostView();
322 if (rwhv)
323 rwhv->SetBackgroundColor(profiles::kUserManagerBackgroundColor);
325 GetWidget()->Show();
326 web_view_->RequestFocus();
329 void UserManagerView::LogTimeToOpen() {
330 if (user_manager_started_showing_ == base::Time())
331 return;
333 ProfileMetrics::LogTimeToOpenUserManager(
334 base::Time::Now() - user_manager_started_showing_);
335 user_manager_started_showing_ = base::Time();
338 bool UserManagerView::AcceleratorPressed(const ui::Accelerator& accelerator) {
339 int key = accelerator.key_code();
340 int modifier = accelerator.modifiers();
341 DCHECK((key == ui::VKEY_W && modifier == ui::EF_CONTROL_DOWN) ||
342 (key == ui::VKEY_F4 && modifier == ui::EF_ALT_DOWN));
343 GetWidget()->Close();
344 return true;
347 gfx::Size UserManagerView::GetPreferredSize() const {
348 return gfx::Size(UserManager::kWindowWidth, UserManager::kWindowHeight);
351 bool UserManagerView::CanResize() const {
352 return true;
355 bool UserManagerView::CanMaximize() const {
356 return true;
359 bool UserManagerView::CanMinimize() const {
360 return true;
363 base::string16 UserManagerView::GetWindowTitle() const {
364 return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
367 int UserManagerView::GetDialogButtons() const {
368 return ui::DIALOG_BUTTON_NONE;
371 void UserManagerView::WindowClosing() {
372 // Now that the window is closed, we can allow a new one to be opened.
373 // (WindowClosing comes in asynchronously from the call to Close() and we
374 // may have already opened a new instance).
375 if (instance_ == this)
376 instance_ = NULL;
379 bool UserManagerView::UseNewStyleForThisDialog() const {
380 return false;