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. 4 5 #include "chrome/browser/ui/views/profiles/user_manager_view.h" 6 7 #include "chrome/browser/browser_process.h" 8 #include "chrome/browser/lifetime/application_lifetime.h" 9 #include "chrome/browser/profiles/profile_manager.h" 10 #include "chrome/browser/profiles/profile_metrics.h" 11 #include "chrome/browser/profiles/profile_window.h" 12 #include "chrome/browser/profiles/profiles_state.h" 13 #include "chrome/browser/ui/browser.h" 14 #include "chrome/browser/ui/browser_dialogs.h" 15 #include "chrome/browser/ui/browser_finder.h" 16 #include "chrome/browser/ui/browser_window.h" 17 #include "chrome/browser/ui/user_manager.h" 18 #include "chrome/browser/ui/views/auto_keep_alive.h" 19 #include "chrome/grit/chromium_strings.h" 20 #include "content/public/browser/web_contents.h" 21 #include "ui/base/l10n/l10n_util.h" 22 #include "ui/gfx/screen.h" 23 #include "ui/views/controls/webview/webview.h" 24 #include "ui/views/layout/fill_layout.h" 25 #include "ui/views/view.h" 26 #include "ui/views/widget/widget.h" 27 #include "ui/views/window/dialog_client_view.h" 28 29 #if defined(OS_WIN) 30 #include "chrome/browser/shell_integration.h" 31 #include "ui/base/win/shell.h" 32 #include "ui/views/win/hwnd_util.h" 33 #endif 34 35 namespace { 36 37 // An open User Manager window. There can only be one open at a time. This 38 // is reset to NULL when the window is closed. 39 UserManagerView* instance_ = NULL; 40 41 } // namespace 42 43 // UserManager ----------------------------------------------------------------- 44 45 void UserManager::Show( 46 const base::FilePath& profile_path_to_focus, 47 profiles::UserManagerTutorialMode tutorial_mode, 48 profiles::UserManagerProfileSelected profile_open_action) { 49 ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::OPEN_USER_MANAGER); 50 if (instance_) { 51 // If we are showing the User Manager after locking a profile, change the 52 // active profile to Guest. 53 profiles::SetActiveProfileToGuestIfLocked(); 54 55 // If there's a user manager window open already, just activate it. 56 instance_->GetWidget()->Activate(); 57 return; 58 } 59 60 // Create the guest profile, if necessary, and open the user manager 61 // from the guest profile. 62 profiles::CreateGuestProfileForUserManager( 63 profile_path_to_focus, 64 tutorial_mode, 65 profile_open_action, 66 base::Bind(&UserManagerView::OnGuestProfileCreated, 67 base::Passed(make_scoped_ptr(new UserManagerView)), 68 profile_path_to_focus)); 69 } 70 71 void UserManager::Hide() { 72 if (instance_) 73 instance_->GetWidget()->Close(); 74 } 75 76 bool UserManager::IsShowing() { 77 return instance_ ? instance_->GetWidget()->IsActive() : false; 78 } 79 80 // UserManagerView ------------------------------------------------------------- 81 82 UserManagerView::UserManagerView() 83 : web_view_(NULL), 84 keep_alive_(new AutoKeepAlive(NULL)) { 85 } 86 87 UserManagerView::~UserManagerView() { 88 } 89 90 // static 91 void UserManagerView::OnGuestProfileCreated( 92 scoped_ptr<UserManagerView> instance, 93 const base::FilePath& profile_path_to_focus, 94 Profile* guest_profile, 95 const std::string& url) { 96 // If we are showing the User Manager after locking a profile, change the 97 // active profile to Guest. 98 profiles::SetActiveProfileToGuestIfLocked(); 99 100 DCHECK(!instance_); 101 instance_ = instance.release(); // |instance_| takes over ownership. 102 instance_->Init(profile_path_to_focus, guest_profile, GURL(url)); 103 } 104 105 void UserManagerView::Init( 106 const base::FilePath& profile_path_to_focus, 107 Profile* guest_profile, 108 const GURL& url) { 109 web_view_ = new views::WebView(guest_profile); 110 web_view_->set_allow_accelerators(true); 111 AddChildView(web_view_); 112 SetLayoutManager(new views::FillLayout); 113 AddAccelerator(ui::Accelerator(ui::VKEY_W, ui::EF_CONTROL_DOWN)); 114 115 // If the user manager is being displayed from an existing profile, use 116 // its last active browser to determine where the user manager should be 117 // placed. This is used so that we can center the dialog on the correct 118 // monitor in a multiple-monitor setup. 119 // 120 // If |profile_path_to_focus| is empty (for example, starting up chrome 121 // when all existing profiles are locked) or we can't find an active 122 // browser, bounds will remain empty and the user manager will be centered on 123 // the default monitor by default. 124 gfx::Rect bounds; 125 if (!profile_path_to_focus.empty()) { 126 ProfileManager* manager = g_browser_process->profile_manager(); 127 if (manager) { 128 Profile* profile = manager->GetProfileByPath(profile_path_to_focus); 129 DCHECK(profile); 130 Browser* browser = chrome::FindLastActiveWithProfile(profile, 131 chrome::GetActiveDesktop()); 132 if (browser) { 133 gfx::NativeView native_view = 134 views::Widget::GetWidgetForNativeWindow( 135 browser->window()->GetNativeWindow())->GetNativeView(); 136 bounds = gfx::Screen::GetScreenFor(native_view)-> 137 GetDisplayNearestWindow(native_view).work_area(); 138 bounds.ClampToCenteredSize(gfx::Size(UserManager::kWindowWidth, 139 UserManager::kWindowHeight)); 140 } 141 } 142 } 143 144 DialogDelegate::CreateDialogWidgetWithBounds(this, NULL, NULL, bounds); 145 146 // Since the User Manager can be the only top level window, we don't 147 // want to accidentally quit all of Chrome if the user is just trying to 148 // unfocus the selected pod in the WebView. 149 GetDialogClientView()->RemoveAccelerator( 150 ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); 151 152 #if defined(OS_WIN) 153 // Set the app id for the task manager to the app id of its parent 154 ui::win::SetAppIdForWindow( 155 ShellIntegration::GetChromiumModelIdForProfile( 156 guest_profile->GetPath()), 157 views::HWNDForWidget(GetWidget())); 158 #endif 159 GetWidget()->Show(); 160 161 web_view_->LoadInitialURL(url); 162 web_view_->RequestFocus(); 163 } 164 165 bool UserManagerView::AcceleratorPressed(const ui::Accelerator& accelerator) { 166 DCHECK_EQ(ui::VKEY_W, accelerator.key_code()); 167 DCHECK_EQ(ui::EF_CONTROL_DOWN, accelerator.modifiers()); 168 GetWidget()->Close(); 169 return true; 170 } 171 172 gfx::Size UserManagerView::GetPreferredSize() const { 173 return gfx::Size(UserManager::kWindowWidth, UserManager::kWindowHeight); 174 } 175 176 bool UserManagerView::CanResize() const { 177 return true; 178 } 179 180 bool UserManagerView::CanMaximize() const { 181 return true; 182 } 183 184 bool UserManagerView::CanMinimize() const { 185 return true; 186 } 187 188 base::string16 UserManagerView::GetWindowTitle() const { 189 return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); 190 } 191 192 int UserManagerView::GetDialogButtons() const { 193 return ui::DIALOG_BUTTON_NONE; 194 } 195 196 void UserManagerView::WindowClosing() { 197 // Now that the window is closed, we can allow a new one to be opened. 198 // (WindowClosing comes in asynchronously from the call to Close() and we 199 // may have already opened a new instance). 200 if (instance_ == this) 201 instance_ = NULL; 202 } 203 204 bool UserManagerView::UseNewStyleForThisDialog() const { 205 return false; 206 } 207