Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / ui / views / profiles / user_manager_view.cc
blobeee57009c836e15fe946fafa290d10231d50b297
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;
79 // UserManager::ReauthObserver:
80 void CloseReauthDialog() override;
82 views::WebView* web_view_;
83 const std::string email_address_;
85 DISALLOW_COPY_AND_ASSIGN(ReauthDelegate);
88 ReauthDelegate::ReauthDelegate(views::WebView* web_view,
89 const std::string& email_address)
90 : UserManager::ReauthDialogObserver(
91 web_view->GetWebContents(), email_address),
92 web_view_(web_view),
93 email_address_(email_address) {
94 AddChildView(web_view_);
95 SetLayoutManager(new views::FillLayout());
97 // Load the re-auth URL, prepopulated with the user's email address.
98 // Add the index of the profile to the URL so that the inline login page
99 // knows which profile to load and update the credentials.
100 GURL url = signin::GetReauthURLWithEmail(email_address_);
101 web_view_->LoadInitialURL(url);
104 gfx::Size ReauthDelegate::GetPreferredSize() const {
105 return gfx::Size(UserManager::kReauthDialogWidth,
106 UserManager::kReauthDialogHeight);
109 bool ReauthDelegate::CanResize() const {
110 return true;
113 bool ReauthDelegate::CanMaximize() const {
114 return true;
117 bool ReauthDelegate::CanMinimize() const {
118 return true;
121 bool ReauthDelegate::UseNewStyleForThisDialog() const {
122 return false;
125 ui::ModalType ReauthDelegate::GetModalType() const {
126 return ui::MODAL_TYPE_WINDOW;
129 void ReauthDelegate::DeleteDelegate() {
130 delete this;
133 base::string16 ReauthDelegate::GetWindowTitle() const {
134 return l10n_util::GetStringUTF16(IDS_PROFILES_GAIA_SIGNIN_TITLE);
137 int ReauthDelegate::GetDialogButtons() const {
138 return ui::DIALOG_BUTTON_NONE;
141 void ReauthDelegate::CloseReauthDialog() {
142 GetWidget()->Close();
145 } // namespace
147 // UserManager -----------------------------------------------------------------
149 // static
150 void UserManager::Show(
151 const base::FilePath& profile_path_to_focus,
152 profiles::UserManagerTutorialMode tutorial_mode,
153 profiles::UserManagerProfileSelected profile_open_action) {
154 DCHECK(profile_path_to_focus != ProfileManager::GetGuestProfilePath());
156 ProfileMetrics::LogProfileOpenMethod(ProfileMetrics::OPEN_USER_MANAGER);
157 if (instance_) {
158 // If we are showing the User Manager after locking a profile, change the
159 // active profile to Guest.
160 profiles::SetActiveProfileToGuestIfLocked();
162 // Note the time we started opening the User Manager.
163 instance_->set_user_manager_started_showing(base::Time::Now());
165 // If there's a user manager window open already, just activate it.
166 instance_->GetWidget()->Activate();
167 return;
170 // Under some startup conditions, we can try twice to create the User Manager.
171 // Because creating the System profile is asynchronous, it's possible for
172 // there to then be multiple pending operations and eventually multiple
173 // User Managers.
174 if (instance_under_construction_)
175 return;
177 // Create the system profile, if necessary, and open the user manager
178 // from the system profile.
179 UserManagerView* user_manager = new UserManagerView();
180 user_manager->set_user_manager_started_showing(base::Time::Now());
181 profiles::CreateSystemProfileForUserManager(
182 profile_path_to_focus,
183 tutorial_mode,
184 profile_open_action,
185 base::Bind(&UserManagerView::OnSystemProfileCreated,
186 base::Passed(make_scoped_ptr(user_manager)),
187 base::Owned(new base::AutoReset<bool>(
188 &instance_under_construction_, true))));
191 // static
192 void UserManager::Hide() {
193 if (instance_)
194 instance_->GetWidget()->Close();
197 // static
198 bool UserManager::IsShowing() {
199 return instance_ ? instance_->GetWidget()->IsActive() : false;
202 // static
203 void UserManager::OnUserManagerShown() {
204 if (instance_)
205 instance_->LogTimeToOpen();
208 // static
209 void UserManager::ShowReauthDialog(content::BrowserContext* browser_context,
210 const std::string& email) {
211 // This method should only be called if the user manager is already showing.
212 if (!IsShowing())
213 return;
215 // The dialog delegate will be deleted when the dialog closes and the created
216 // WebView's lifetime is managed by the delegate.
217 views::DialogDelegate* delegate =
218 new ReauthDelegate(new views::WebView(browser_context), email);
219 gfx::NativeView parent = instance_->GetWidget()->GetNativeView();
220 views::DialogDelegate::CreateDialogWidget(delegate, nullptr, parent);
221 delegate->GetWidget()->Show();
224 // UserManagerView -------------------------------------------------------------
226 UserManagerView::UserManagerView()
227 : web_view_(NULL),
228 keep_alive_(new AutoKeepAlive(NULL)),
229 user_manager_started_showing_(base::Time()) {
232 UserManagerView::~UserManagerView() {
235 // static
236 void UserManagerView::OnSystemProfileCreated(
237 scoped_ptr<UserManagerView> instance,
238 base::AutoReset<bool>* pending,
239 Profile* system_profile,
240 const std::string& url) {
241 // If we are showing the User Manager after locking a profile, change the
242 // active profile to Guest.
243 profiles::SetActiveProfileToGuestIfLocked();
245 DCHECK(!instance_);
246 instance_ = instance.release(); // |instance_| takes over ownership.
247 instance_->Init(system_profile, GURL(url));
250 void UserManagerView::Init(Profile* system_profile, const GURL& url) {
251 web_view_ = new views::WebView(system_profile);
252 web_view_->set_allow_accelerators(true);
253 AddChildView(web_view_);
254 SetLayoutManager(new views::FillLayout);
255 AddAccelerator(ui::Accelerator(ui::VKEY_W, ui::EF_CONTROL_DOWN));
256 AddAccelerator(ui::Accelerator(ui::VKEY_F4, ui::EF_ALT_DOWN));
258 // If the user manager is being displayed from an existing profile, use
259 // its last active browser to determine where the user manager should be
260 // placed. This is used so that we can center the dialog on the correct
261 // monitor in a multiple-monitor setup.
263 // If the last active profile is empty (for example, starting up chrome
264 // when all existing profiles are locked), not loaded (for example, if guest
265 // was set after locking the only open profile) or we can't find an active
266 // browser, bounds will remain empty and the user manager will be centered on
267 // the default monitor by default.
269 // Note the profile is accessed via GetProfileByPath(GetLastUsedProfileDir())
270 // instead of GetLastUsedProfile(). If the last active profile isn't loaded,
271 // the latter may try to synchronously load it, which can only be done on a
272 // thread where disk IO is allowed.
273 gfx::Rect bounds;
274 ProfileManager* profile_manager = g_browser_process->profile_manager();
275 const base::FilePath& last_used_profile_path =
276 profile_manager->GetLastUsedProfileDir(profile_manager->user_data_dir());
277 Profile* profile = profile_manager->GetProfileByPath(last_used_profile_path);
278 if (profile) {
279 Browser* browser = chrome::FindLastActiveWithProfile(profile,
280 chrome::GetActiveDesktop());
281 if (browser) {
282 gfx::NativeView native_view =
283 views::Widget::GetWidgetForNativeWindow(
284 browser->window()->GetNativeWindow())->GetNativeView();
285 bounds = gfx::Screen::GetScreenFor(native_view)->
286 GetDisplayNearestWindow(native_view).work_area();
287 bounds.ClampToCenteredSize(gfx::Size(UserManager::kWindowWidth,
288 UserManager::kWindowHeight));
292 DialogDelegate::CreateDialogWidgetWithBounds(this, NULL, NULL, bounds);
294 // Since the User Manager can be the only top level window, we don't
295 // want to accidentally quit all of Chrome if the user is just trying to
296 // unfocus the selected pod in the WebView.
297 GetDialogClientView()->RemoveAccelerator(
298 ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
300 #if defined(OS_WIN)
301 // Set the app id for the task manager to the app id of its parent
302 ui::win::SetAppIdForWindow(
303 ShellIntegration::GetChromiumModelIdForProfile(
304 system_profile->GetPath()),
305 views::HWNDForWidget(GetWidget()));
306 #endif
308 #if defined(USE_ASH)
309 gfx::NativeWindow native_window = GetWidget()->GetNativeWindow();
310 ash::SetShelfItemDetailsForDialogWindow(
311 native_window, IDR_ASH_SHELF_LIST_BROWSER, native_window->title());
312 #endif
314 web_view_->LoadInitialURL(url);
315 content::RenderWidgetHostView* rwhv =
316 web_view_->GetWebContents()->GetRenderWidgetHostView();
317 if (rwhv)
318 rwhv->SetBackgroundColor(profiles::kUserManagerBackgroundColor);
320 GetWidget()->Show();
321 web_view_->RequestFocus();
324 void UserManagerView::LogTimeToOpen() {
325 if (user_manager_started_showing_ == base::Time())
326 return;
328 ProfileMetrics::LogTimeToOpenUserManager(
329 base::Time::Now() - user_manager_started_showing_);
330 user_manager_started_showing_ = base::Time();
333 bool UserManagerView::AcceleratorPressed(const ui::Accelerator& accelerator) {
334 int key = accelerator.key_code();
335 int modifier = accelerator.modifiers();
336 DCHECK((key == ui::VKEY_W && modifier == ui::EF_CONTROL_DOWN) ||
337 (key == ui::VKEY_F4 && modifier == ui::EF_ALT_DOWN));
338 GetWidget()->Close();
339 return true;
342 gfx::Size UserManagerView::GetPreferredSize() const {
343 return gfx::Size(UserManager::kWindowWidth, UserManager::kWindowHeight);
346 bool UserManagerView::CanResize() const {
347 return true;
350 bool UserManagerView::CanMaximize() const {
351 return true;
354 bool UserManagerView::CanMinimize() const {
355 return true;
358 base::string16 UserManagerView::GetWindowTitle() const {
359 return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
362 int UserManagerView::GetDialogButtons() const {
363 return ui::DIALOG_BUTTON_NONE;
366 void UserManagerView::WindowClosing() {
367 // Now that the window is closed, we can allow a new one to be opened.
368 // (WindowClosing comes in asynchronously from the call to Close() and we
369 // may have already opened a new instance).
370 if (instance_ == this)
371 instance_ = NULL;
374 bool UserManagerView::UseNewStyleForThisDialog() const {
375 return false;