- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / signin / user_manager_screen_handler.cc
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.
4
5 #include "chrome/browser/ui/webui/signin/user_manager_screen_handler.h"
6
7 #include "base/bind.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"
32
33 #if defined(ENABLE_MANAGED_USERS)
34 #include "chrome/browser/managed_mode/managed_user_service.h"
35 #endif
36
37 namespace {
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";
51
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";
58
59 const size_t kAvatarIconSize = 180;
60
61 void HandleAndDoNothing(const base::ListValue* args) {
62 }
63
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,
68     Profile* profile,
69     Profile::CreateStatus status) {
70   if (status != Profile::CREATE_STATUS_INITIALIZED)
71     return;
72   profiles::FindOrCreateNewWindowForProfile(
73     profile,
74     chrome::startup::IS_PROCESS_STARTUP,
75     chrome::startup::IS_FIRST_RUN,
76     desktop_type,
77     false);
78 }
79
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);
85
86   gfx::Image icon = profiles::GetSizedAvatarIconWithBorder(
87       info_cache.GetAvatarIconOfProfileAtIndex(index),
88       is_gaia_picture, kAvatarIconSize, kAvatarIconSize);
89   return webui::GetBitmapDataUrl(icon.AsBitmap());
90 }
91
92 } // namespace
93
94 // ProfileUpdateObserver ------------------------------------------------------
95
96 class UserManagerScreenHandler::ProfileUpdateObserver
97     : public ProfileInfoCacheObserver {
98  public:
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);
106   }
107
108   virtual ~ProfileUpdateObserver() {
109     DCHECK(profile_manager_);
110     profile_manager_->GetProfileInfoCache().RemoveObserver(this);
111   }
112
113  private:
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();
119   }
120
121   virtual void OnProfileWasRemoved(const base::FilePath& profile_path,
122                                    const string16& profile_name) OVERRIDE {
123     user_manager_handler_->SendUserList();
124   }
125
126   virtual void OnProfileWillBeRemoved(
127       const base::FilePath& profile_path) OVERRIDE {
128     // No-op. When the profile is actually removed, OnProfileWasRemoved
129     // will be called.
130   }
131
132   virtual void OnProfileNameChanged(const base::FilePath& profile_path,
133                                     const string16& old_profile_name) OVERRIDE {
134     user_manager_handler_->SendUserList();
135   }
136
137   virtual void OnProfileAvatarChanged(
138       const base::FilePath& profile_path) OVERRIDE {
139     user_manager_handler_->SendUserList();
140   }
141
142   ProfileManager* profile_manager_;
143
144   UserManagerScreenHandler* user_manager_handler_;  // Weak; owns us.
145
146   DISALLOW_COPY_AND_ASSIGN(ProfileUpdateObserver);
147 };
148
149 // UserManagerScreenHandler ---------------------------------------------------
150
151 UserManagerScreenHandler::UserManagerScreenHandler()
152     : desktop_type_(chrome::GetActiveDesktop()) {
153   profileInfoCacheObserver_.reset(
154       new UserManagerScreenHandler::ProfileUpdateObserver(
155           g_browser_process->profile_manager(), this));
156 }
157
158 UserManagerScreenHandler::~UserManagerScreenHandler() {
159 }
160
161 void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) {
162   SendUserList();
163   web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen");
164   desktop_type_ = chrome::GetHostDesktopTypeForNativeView(
165       web_ui()->GetWebContents()->GetView()->GetNativeView());
166 }
167
168 void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) {
169   profiles::CreateAndSwitchToNewProfile(desktop_type_,
170                                         base::Bind(&chrome::HideUserManager));
171 }
172
173 void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
174   DCHECK(args);
175   const Value* profile_path_value;
176   if (!args->Get(0, &profile_path_value))
177     return;
178
179   base::FilePath profile_path;
180   if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
181     return;
182
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())
186     return;
187
188   if (!profiles::IsMultipleProfilesEnabled())
189     return;
190
191   g_browser_process->profile_manager()->ScheduleProfileForDeletion(
192       profile_path,
193       base::Bind(&OpenNewWindowForProfile, desktop_type_));
194 }
195
196 void UserManagerScreenHandler::HandleLaunchGuest(const base::ListValue* args) {
197   profiles::SwitchToGuestProfile(desktop_type_,
198                                  base::Bind(&chrome::HideUserManager));
199 }
200
201 void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) {
202   string16 emailAddress;
203   string16 displayName;
204
205   if (!args->GetString(0, &emailAddress) ||
206       !args->GetString(1, &displayName)) {
207     NOTREACHED();
208     return;
209   }
210
211   ProfileInfoCache& info_cache =
212       g_browser_process->profile_manager()->GetProfileInfoCache();
213
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));
220       break;
221     }
222   }
223 }
224
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)));
241
242   const content::WebUI::MessageCallback& kDoNothingCallback =
243       base::Bind(&HandleAndDoNothing);
244
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);
256 }
257
258 void UserManagerScreenHandler::GetLocalizedValues(
259     base::DictionaryValue* localized_strings) {
260   // For Control Bar.
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));
272
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");
290
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));
297
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());
304  }
305
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();
312
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();
318
319     base::FilePath profile_path = info_cache.GetPathOfProfileAtIndex(i);
320     bool is_active_user = (profile_path == active_profile_path);
321
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));
339
340     // The row of user pods should display the active user first.
341     if (is_active_user)
342       users_list.Insert(0, profile_value);
343     else
344       users_list.Append(profile_value);
345   }
346
347   web_ui()->CallJavascriptFunction("login.AccountPickerScreen.loadUsers",
348     users_list, base::FundamentalValue(false), base::FundamentalValue(true));
349 }