1 // Copyright 2013 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/webui/signin/user_manager_screen_handler.h"
8 #include "base/value_conversions.h"
9 #include "base/values.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/profiles/avatar_menu.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/profiles/profile_info_cache.h"
14 #include "chrome/browser/profiles/profile_info_cache_observer.h"
15 #include "chrome/browser/profiles/profile_info_util.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/profiles/profile_window.h"
18 #include "chrome/browser/profiles/profiles_state.h"
19 #include "chrome/browser/ui/browser_dialogs.h"
20 #include "chrome/browser/ui/browser_finder.h"
21 #include "chrome/browser/ui/singleton_tabs.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/browser/web_contents_view.h"
24 #include "content/public/browser/web_ui.h"
25 #include "grit/browser_resources.h"
26 #include "grit/chromium_strings.h"
27 #include "grit/generated_resources.h"
28 #include "third_party/skia/include/core/SkBitmap.h"
29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/webui/web_ui_util.h"
31 #include "ui/gfx/image/image_util.h"
33 #if defined(ENABLE_MANAGED_USERS)
34 #include "chrome/browser/managed_mode/managed_user_service.h"
38 // User dictionary keys.
39 const char kKeyUsername[] = "username";
40 const char kKeyDisplayName[]= "displayName";
41 const char kKeyEmailAddress[] = "emailAddress";
42 const char kKeyProfilePath[] = "profilePath";
43 const char kKeyPublicAccount[] = "publicAccount";
44 const char kKeyLocallyManagedUser[] = "locallyManagedUser";
45 const char kKeySignedIn[] = "signedIn";
46 const char kKeyCanRemove[] = "canRemove";
47 const char kKeyIsOwner[] = "isOwner";
48 const char kKeyIsDesktop[] = "isDesktopUser";
49 const char kKeyAvatarUrl[] = "userImage";
50 const char kKeyNeedsSignin[] = "needsSignin";
52 // JS API callback names.
53 const char kJsApiUserManagerInitialize[] = "userManagerInitialize";
54 const char kJsApiUserManagerAddUser[] = "addUser";
55 const char kJsApiUserManagerLaunchGuest[] = "launchGuest";
56 const char kJsApiUserManagerLaunchUser[] = "launchUser";
57 const char kJsApiUserManagerRemoveUser[] = "removeUser";
59 const size_t kAvatarIconSize = 180;
61 void HandleAndDoNothing(const base::ListValue* args) {
64 // This callback is run if the only profile has been deleted, and a new
65 // profile has been created to replace it.
66 void OpenNewWindowForProfile(
67 chrome::HostDesktopType desktop_type,
69 Profile::CreateStatus status) {
70 if (status != Profile::CREATE_STATUS_INITIALIZED)
72 profiles::FindOrCreateNewWindowForProfile(
74 chrome::startup::IS_PROCESS_STARTUP,
75 chrome::startup::IS_FIRST_RUN,
80 std::string GetAvatarImageAtIndex(
81 size_t index, const ProfileInfoCache& info_cache) {
82 bool is_gaia_picture =
83 info_cache.IsUsingGAIAPictureOfProfileAtIndex(index) &&
84 info_cache.GetGAIAPictureOfProfileAtIndex(index);
86 gfx::Image icon = profiles::GetSizedAvatarIconWithBorder(
87 info_cache.GetAvatarIconOfProfileAtIndex(index),
88 is_gaia_picture, kAvatarIconSize, kAvatarIconSize);
89 return webui::GetBitmapDataUrl(icon.AsBitmap());
94 // ProfileUpdateObserver ------------------------------------------------------
96 class UserManagerScreenHandler::ProfileUpdateObserver
97 : public ProfileInfoCacheObserver {
99 ProfileUpdateObserver(
100 ProfileManager* profile_manager, UserManagerScreenHandler* handler)
101 : profile_manager_(profile_manager),
102 user_manager_handler_(handler) {
103 DCHECK(profile_manager_);
104 DCHECK(user_manager_handler_);
105 profile_manager_->GetProfileInfoCache().AddObserver(this);
108 virtual ~ProfileUpdateObserver() {
109 DCHECK(profile_manager_);
110 profile_manager_->GetProfileInfoCache().RemoveObserver(this);
114 // ProfileInfoCacheObserver implementation:
115 // If any change has been made to a profile, propagate it to all the
116 // visible user manager screens.
117 virtual void OnProfileAdded(const base::FilePath& profile_path) OVERRIDE {
118 user_manager_handler_->SendUserList();
121 virtual void OnProfileWasRemoved(const base::FilePath& profile_path,
122 const string16& profile_name) OVERRIDE {
123 user_manager_handler_->SendUserList();
126 virtual void OnProfileWillBeRemoved(
127 const base::FilePath& profile_path) OVERRIDE {
128 // No-op. When the profile is actually removed, OnProfileWasRemoved
132 virtual void OnProfileNameChanged(const base::FilePath& profile_path,
133 const string16& old_profile_name) OVERRIDE {
134 user_manager_handler_->SendUserList();
137 virtual void OnProfileAvatarChanged(
138 const base::FilePath& profile_path) OVERRIDE {
139 user_manager_handler_->SendUserList();
142 ProfileManager* profile_manager_;
144 UserManagerScreenHandler* user_manager_handler_; // Weak; owns us.
146 DISALLOW_COPY_AND_ASSIGN(ProfileUpdateObserver);
149 // UserManagerScreenHandler ---------------------------------------------------
151 UserManagerScreenHandler::UserManagerScreenHandler()
152 : desktop_type_(chrome::GetActiveDesktop()) {
153 profileInfoCacheObserver_.reset(
154 new UserManagerScreenHandler::ProfileUpdateObserver(
155 g_browser_process->profile_manager(), this));
158 UserManagerScreenHandler::~UserManagerScreenHandler() {
161 void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) {
163 web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen");
164 desktop_type_ = chrome::GetHostDesktopTypeForNativeView(
165 web_ui()->GetWebContents()->GetView()->GetNativeView());
168 void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) {
169 profiles::CreateAndSwitchToNewProfile(desktop_type_,
170 base::Bind(&chrome::HideUserManager));
173 void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
175 const Value* profile_path_value;
176 if (!args->Get(0, &profile_path_value))
179 base::FilePath profile_path;
180 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
183 // This handler could have been called in managed mode, for example because
184 // the user fiddled with the web inspector. Silently return in this case.
185 if (Profile::FromWebUI(web_ui())->IsManaged())
188 if (!profiles::IsMultipleProfilesEnabled())
191 g_browser_process->profile_manager()->ScheduleProfileForDeletion(
193 base::Bind(&OpenNewWindowForProfile, desktop_type_));
196 void UserManagerScreenHandler::HandleLaunchGuest(const base::ListValue* args) {
197 profiles::SwitchToGuestProfile(desktop_type_,
198 base::Bind(&chrome::HideUserManager));
201 void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) {
202 string16 emailAddress;
203 string16 displayName;
205 if (!args->GetString(0, &emailAddress) ||
206 !args->GetString(1, &displayName)) {
211 ProfileInfoCache& info_cache =
212 g_browser_process->profile_manager()->GetProfileInfoCache();
214 for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) {
215 if (info_cache.GetUserNameOfProfileAtIndex(i) == emailAddress &&
216 info_cache.GetNameOfProfileAtIndex(i) == displayName) {
217 base::FilePath path = info_cache.GetPathOfProfileAtIndex(i);
218 profiles::SwitchToProfile(path, chrome::GetActiveDesktop(), true,
219 base::Bind(&chrome::HideUserManager));
225 void UserManagerScreenHandler::RegisterMessages() {
226 web_ui()->RegisterMessageCallback(kJsApiUserManagerInitialize,
227 base::Bind(&UserManagerScreenHandler::HandleInitialize,
228 base::Unretained(this)));
229 web_ui()->RegisterMessageCallback(kJsApiUserManagerAddUser,
230 base::Bind(&UserManagerScreenHandler::HandleAddUser,
231 base::Unretained(this)));
232 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchGuest,
233 base::Bind(&UserManagerScreenHandler::HandleLaunchGuest,
234 base::Unretained(this)));
235 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchUser,
236 base::Bind(&UserManagerScreenHandler::HandleLaunchUser,
237 base::Unretained(this)));
238 web_ui()->RegisterMessageCallback(kJsApiUserManagerRemoveUser,
239 base::Bind(&UserManagerScreenHandler::HandleRemoveUser,
240 base::Unretained(this)));
242 const content::WebUI::MessageCallback& kDoNothingCallback =
243 base::Bind(&HandleAndDoNothing);
245 // Unused callbacks from screen_account_picker.js
246 web_ui()->RegisterMessageCallback("accountPickerReady", kDoNothingCallback);
247 web_ui()->RegisterMessageCallback("loginUIStateChanged", kDoNothingCallback);
248 web_ui()->RegisterMessageCallback("hideCaptivePortal", kDoNothingCallback);
249 // Unused callbacks from display_manager.js
250 web_ui()->RegisterMessageCallback("showAddUser", kDoNothingCallback);
251 web_ui()->RegisterMessageCallback("loadWallpaper", kDoNothingCallback);
252 web_ui()->RegisterMessageCallback("updateCurrentScreen", kDoNothingCallback);
253 web_ui()->RegisterMessageCallback("loginVisible", kDoNothingCallback);
254 // Unused callbacks from user_pod_row.js
255 web_ui()->RegisterMessageCallback("focusPod", kDoNothingCallback);
258 void UserManagerScreenHandler::GetLocalizedValues(
259 base::DictionaryValue* localized_strings) {
261 localized_strings->SetString("signedIn",
262 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_ACTIVE_USER));
263 localized_strings->SetString("signinButton",
264 l10n_util::GetStringUTF16(IDS_LOGIN_BUTTON));
265 localized_strings->SetString("addUser",
266 l10n_util::GetStringUTF16(IDS_ADD_USER_BUTTON));
267 localized_strings->SetString("cancel", l10n_util::GetStringUTF16(IDS_CANCEL));
268 localized_strings->SetString("browseAsGuest",
269 l10n_util::GetStringUTF16(IDS_GO_INCOGNITO_BUTTON));
270 localized_strings->SetString("signOutUser",
271 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_SIGN_OUT));
273 // For AccountPickerScreen.
274 localized_strings->SetString("screenType", "login-add-user");
275 localized_strings->SetString("highlightStrength", "normal");
276 localized_strings->SetString("title",
277 l10n_util::GetStringUTF16(IDS_USER_MANAGER_SCREEN_TITLE));
278 localized_strings->SetString("passwordHint",
279 l10n_util::GetStringUTF16(IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT));
280 localized_strings->SetString("podMenuButtonAccessibleName",
281 l10n_util::GetStringUTF16(IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME));
282 localized_strings->SetString("podMenuRemoveItemAccessibleName",
283 l10n_util::GetStringUTF16(
284 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME));
285 localized_strings->SetString("removeUser",
286 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON));
287 localized_strings->SetString("passwordFieldAccessibleName",
288 l10n_util::GetStringUTF16(IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME));
289 localized_strings->SetString("bootIntoWallpaper", "off");
291 // For AccountPickerScreen, the remove user warning overlay.
292 localized_strings->SetString("removeUserWarningButtonTitle",
293 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON));
294 localized_strings->SetString("removeUserWarningText",
295 l10n_util::GetStringUTF16(
296 IDS_LOGIN_POD_USER_REMOVE_WARNING));
298 // Strings needed for the user_pod_template public account div, but not ever
299 // actually displayed for desktop users.
300 localized_strings->SetString("publicAccountReminder", string16());
301 localized_strings->SetString("publicAccountEnter", string16());
302 localized_strings->SetString("publicAccountEnterAccessibleName", string16());
303 localized_strings->SetString("multiple-signin-banner-text", string16());
306 void UserManagerScreenHandler::SendUserList() {
307 ListValue users_list;
308 base::FilePath active_profile_path =
309 web_ui()->GetWebContents()->GetBrowserContext()->GetPath();
310 const ProfileInfoCache& info_cache =
311 g_browser_process->profile_manager()->GetProfileInfoCache();
313 // If the active user is a managed user, then they may not perform
314 // certain actions (i.e. delete another user).
315 bool active_user_is_managed = Profile::FromWebUI(web_ui())->IsManaged();
316 for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) {
317 DictionaryValue* profile_value = new DictionaryValue();
319 base::FilePath profile_path = info_cache.GetPathOfProfileAtIndex(i);
320 bool is_active_user = (profile_path == active_profile_path);
322 profile_value->SetString(
323 kKeyUsername, info_cache.GetUserNameOfProfileAtIndex(i));
324 profile_value->SetString(
325 kKeyEmailAddress, info_cache.GetUserNameOfProfileAtIndex(i));
326 profile_value->SetString(
327 kKeyDisplayName, info_cache.GetNameOfProfileAtIndex(i));
328 profile_value->SetString(kKeyProfilePath, profile_path.MaybeAsASCII());
329 profile_value->SetBoolean(kKeyPublicAccount, false);
330 profile_value->SetBoolean(kKeyLocallyManagedUser, false);
331 profile_value->SetBoolean(kKeySignedIn, is_active_user);
332 profile_value->SetBoolean(
333 kKeyNeedsSignin, info_cache.ProfileIsSigninRequiredAtIndex(i));
334 profile_value->SetBoolean(kKeyIsOwner, false);
335 profile_value->SetBoolean(kKeyCanRemove, !active_user_is_managed);
336 profile_value->SetBoolean(kKeyIsDesktop, true);
337 profile_value->SetString(
338 kKeyAvatarUrl, GetAvatarImageAtIndex(i, info_cache));
340 // The row of user pods should display the active user first.
342 users_list.Insert(0, profile_value);
344 users_list.Append(profile_value);
347 web_ui()->CallJavascriptFunction("login.AccountPickerScreen.loadUsers",
348 users_list, base::FundamentalValue(false), base::FundamentalValue(true));