Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / options / create_profile_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/options/create_profile_handler.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/files/file_path.h"
10 #include "base/metrics/histogram.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/value_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/managed_mode/managed_user_registration_utility.h"
16 #include "chrome/browser/managed_mode/managed_user_service.h"
17 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
18 #include "chrome/browser/managed_mode/managed_user_sync_service.h"
19 #include "chrome/browser/managed_mode/managed_user_sync_service_factory.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/browser/profiles/profile_metrics.h"
22 #include "chrome/browser/profiles/profiles_state.h"
23 #include "chrome/browser/sync/profile_sync_service.h"
24 #include "chrome/browser/sync/profile_sync_service_factory.h"
25 #include "chrome/browser/ui/webui/options/options_handlers_helper.h"
26 #include "chrome/common/pref_names.h"
27 #include "grit/generated_resources.h"
28 #include "ui/base/l10n/l10n_util.h"
29
30 namespace options {
31
32 CreateProfileHandler::CreateProfileHandler()
33     : profile_creation_type_(NO_CREATION_IN_PROGRESS),
34       weak_ptr_factory_(this) {
35 }
36
37 CreateProfileHandler::~CreateProfileHandler() {
38   CancelProfileRegistration(false);
39 }
40
41 void CreateProfileHandler::GetLocalizedValues(
42     base::DictionaryValue* localized_strings) {
43 }
44
45 void CreateProfileHandler::RegisterMessages() {
46   web_ui()->RegisterMessageCallback(
47       "cancelCreateProfile",
48       base::Bind(&CreateProfileHandler::HandleCancelProfileCreation,
49                  base::Unretained(this)));
50   web_ui()->RegisterMessageCallback(
51       "createProfile",
52       base::Bind(&CreateProfileHandler::CreateProfile,
53                  base::Unretained(this)));
54 }
55
56 void CreateProfileHandler::CreateProfile(const base::ListValue* args) {
57   // This handler could have been called in managed mode, for example because
58   // the user fiddled with the web inspector. Silently return in this case.
59   Profile* current_profile = Profile::FromWebUI(web_ui());
60   if (current_profile->IsManaged())
61     return;
62
63   if (!profiles::IsMultipleProfilesEnabled())
64     return;
65
66   // We can have only one in progress profile creation
67   // at any given moment, if new ones are initiated just
68   // ignore them until we are done with the old one.
69   if (profile_creation_type_ != NO_CREATION_IN_PROGRESS)
70     return;
71
72   profile_creation_type_ = NON_SUPERVISED_PROFILE_CREATION;
73
74   DCHECK(profile_path_being_created_.empty());
75   profile_creation_start_time_ = base::TimeTicks::Now();
76
77   base::string16 name;
78   base::string16 icon;
79   std::string managed_user_id;
80   bool create_shortcut = false;
81   bool managed_user = false;
82   if (args->GetString(0, &name) && args->GetString(1, &icon)) {
83     if (args->GetBoolean(2, &create_shortcut)) {
84       bool success = args->GetBoolean(3, &managed_user);
85       DCHECK(success);
86       success = args->GetString(4, &managed_user_id);
87       DCHECK(success);
88     }
89   }
90
91   if (managed_user) {
92     if (!IsValidExistingManagedUserId(managed_user_id))
93       return;
94
95     profile_creation_type_ = SUPERVISED_PROFILE_IMPORT;
96     if (managed_user_id.empty()) {
97       profile_creation_type_ = SUPERVISED_PROFILE_CREATION;
98       managed_user_id =
99           ManagedUserRegistrationUtility::GenerateNewManagedUserId();
100
101       // If sync is not yet fully initialized, the creation may take extra time,
102       // so show a message. Import doesn't wait for an acknowledgement, so it
103       // won't have the same potential delay.
104       ProfileSyncService* sync_service =
105           ProfileSyncServiceFactory::GetInstance()->GetForProfile(
106               current_profile);
107       ProfileSyncService::SyncStatusSummary status =
108           sync_service->QuerySyncStatusSummary();
109       if (status == ProfileSyncService::DATATYPES_NOT_INITIALIZED) {
110         ShowProfileCreationWarning(l10n_util::GetStringUTF16(
111             IDS_PROFILES_CREATE_MANAGED_JUST_SIGNED_IN));
112       }
113     }
114   }
115
116   ProfileMetrics::LogProfileAddNewUser(ProfileMetrics::ADD_NEW_USER_DIALOG);
117
118   profile_path_being_created_ = ProfileManager::CreateMultiProfileAsync(
119       name, icon,
120       base::Bind(&CreateProfileHandler::OnProfileCreated,
121                  weak_ptr_factory_.GetWeakPtr(),
122                  create_shortcut,
123                  helper::GetDesktopType(web_ui()),
124                  managed_user_id),
125       managed_user_id);
126 }
127
128 void CreateProfileHandler::OnProfileCreated(
129     bool create_shortcut,
130     chrome::HostDesktopType desktop_type,
131     const std::string& managed_user_id,
132     Profile* profile,
133     Profile::CreateStatus status) {
134   if (status != Profile::CREATE_STATUS_CREATED)
135     RecordProfileCreationMetrics(status);
136
137   switch (status) {
138     case Profile::CREATE_STATUS_LOCAL_FAIL: {
139       ShowProfileCreationError(profile,
140                                GetProfileCreationErrorMessage(LOCAL_ERROR));
141       break;
142     }
143     case Profile::CREATE_STATUS_CREATED: {
144       // Do nothing for an intermediate status.
145       break;
146     }
147     case Profile::CREATE_STATUS_INITIALIZED: {
148       HandleProfileCreationSuccess(create_shortcut, desktop_type,
149                                    managed_user_id, profile);
150       break;
151     }
152     // User-initiated cancellation is handled in CancelProfileRegistration and
153     // does not call this callback.
154     case Profile::CREATE_STATUS_CANCELED:
155     // Managed user registration errors are handled in
156     // OnManagedUserRegistered().
157     case Profile::CREATE_STATUS_REMOTE_FAIL:
158     case Profile::MAX_CREATE_STATUS: {
159       NOTREACHED();
160       break;
161     }
162   }
163 }
164
165 void CreateProfileHandler::HandleProfileCreationSuccess(
166     bool create_shortcut,
167     chrome::HostDesktopType desktop_type,
168     const std::string& managed_user_id,
169     Profile* profile) {
170   switch (profile_creation_type_) {
171     case NON_SUPERVISED_PROFILE_CREATION: {
172       DCHECK(managed_user_id.empty());
173       CreateShortcutAndShowSuccess(create_shortcut, desktop_type, profile);
174       break;
175     }
176     case SUPERVISED_PROFILE_CREATION:
177     case SUPERVISED_PROFILE_IMPORT:
178       RegisterManagedUser(create_shortcut, desktop_type,
179                           managed_user_id, profile);
180       break;
181     case NO_CREATION_IN_PROGRESS:
182       NOTREACHED();
183       break;
184   }
185 }
186
187 void CreateProfileHandler::RegisterManagedUser(
188     bool create_shortcut,
189     chrome::HostDesktopType desktop_type,
190     const std::string& managed_user_id,
191     Profile* new_profile) {
192   DCHECK_EQ(profile_path_being_created_.value(),
193             new_profile->GetPath().value());
194
195   ManagedUserService* managed_user_service =
196       ManagedUserServiceFactory::GetForProfile(new_profile);
197
198   // Register the managed user using the profile of the custodian.
199   managed_user_registration_utility_ =
200       ManagedUserRegistrationUtility::Create(Profile::FromWebUI(web_ui()));
201   managed_user_service->RegisterAndInitSync(
202       managed_user_registration_utility_.get(),
203       Profile::FromWebUI(web_ui()),
204       managed_user_id,
205       base::Bind(&CreateProfileHandler::OnManagedUserRegistered,
206                  weak_ptr_factory_.GetWeakPtr(),
207                  create_shortcut,
208                  desktop_type,
209                  new_profile));
210 }
211
212 void CreateProfileHandler::OnManagedUserRegistered(
213     bool create_shortcut,
214     chrome::HostDesktopType desktop_type,
215     Profile* profile,
216     const GoogleServiceAuthError& error) {
217   GoogleServiceAuthError::State state = error.state();
218   RecordSupervisedProfileCreationMetrics(state);
219   if (state == GoogleServiceAuthError::NONE) {
220     CreateShortcutAndShowSuccess(create_shortcut, desktop_type, profile);
221     return;
222   }
223
224   base::string16 error_msg;
225   if (state == GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS ||
226       state == GoogleServiceAuthError::USER_NOT_SIGNED_UP ||
227       state == GoogleServiceAuthError::ACCOUNT_DELETED ||
228       state == GoogleServiceAuthError::ACCOUNT_DISABLED) {
229     error_msg = GetProfileCreationErrorMessage(SIGNIN_ERROR);
230   } else {
231     error_msg = GetProfileCreationErrorMessage(REMOTE_ERROR);
232   }
233   ShowProfileCreationError(profile, error_msg);
234 }
235
236 void CreateProfileHandler::CreateShortcutAndShowSuccess(
237     bool create_shortcut,
238     chrome::HostDesktopType desktop_type,
239     Profile* profile) {
240   if (create_shortcut) {
241     ProfileShortcutManager* shortcut_manager =
242         g_browser_process->profile_manager()->profile_shortcut_manager();
243
244     if (shortcut_manager)
245       shortcut_manager->CreateProfileShortcut(profile->GetPath());
246   }
247
248   DCHECK_EQ(profile_path_being_created_.value(), profile->GetPath().value());
249   profile_path_being_created_.clear();
250   DCHECK_NE(NO_CREATION_IN_PROGRESS, profile_creation_type_);
251   base::DictionaryValue dict;
252   dict.SetString("name",
253                  profile->GetPrefs()->GetString(prefs::kProfileName));
254   dict.Set("filePath", base::CreateFilePathValue(profile->GetPath()));
255   bool is_managed =
256       profile_creation_type_ == SUPERVISED_PROFILE_CREATION ||
257       profile_creation_type_ == SUPERVISED_PROFILE_IMPORT;
258   dict.SetBoolean("isManaged", is_managed);
259   web_ui()->CallJavascriptFunction(
260       GetJavascriptMethodName(PROFILE_CREATION_SUCCESS), dict);
261
262   // If the new profile is a supervised user, instead of opening a new window
263   // right away, a confirmation overlay will be shown by JS from the creation
264   // dialog. If we are importing an existing supervised profile or creating a
265   // new non-supervised user profile we don't show any confirmation, so open
266   // the new window now.
267   if (profile_creation_type_ != SUPERVISED_PROFILE_CREATION) {
268     // Opening the new window must be the last action, after all callbacks
269     // have been run, to give them a chance to initialize the profile.
270     helper::OpenNewWindowForProfile(desktop_type,
271                                     profile,
272                                     Profile::CREATE_STATUS_INITIALIZED);
273   }
274   profile_creation_type_ = NO_CREATION_IN_PROGRESS;
275 }
276
277 void CreateProfileHandler::ShowProfileCreationError(
278     Profile* profile,
279     const base::string16& error) {
280   DCHECK_NE(NO_CREATION_IN_PROGRESS, profile_creation_type_);
281   profile_creation_type_ = NO_CREATION_IN_PROGRESS;
282   profile_path_being_created_.clear();
283   web_ui()->CallJavascriptFunction(
284       GetJavascriptMethodName(PROFILE_CREATION_ERROR),
285       base::StringValue(error));
286   helper::DeleteProfileAtPath(profile->GetPath(), web_ui());
287 }
288
289 void CreateProfileHandler::ShowProfileCreationWarning(
290     const base::string16& warning) {
291   DCHECK_EQ(SUPERVISED_PROFILE_CREATION, profile_creation_type_);
292   web_ui()->CallJavascriptFunction("BrowserOptions.showCreateProfileWarning",
293                                    base::StringValue(warning));
294 }
295
296 void CreateProfileHandler::HandleCancelProfileCreation(
297     const base::ListValue* args) {
298   CancelProfileRegistration(true);
299 }
300
301 void CreateProfileHandler::CancelProfileRegistration(bool user_initiated) {
302   if (profile_path_being_created_.empty())
303     return;
304
305   ProfileManager* manager = g_browser_process->profile_manager();
306   Profile* new_profile = manager->GetProfileByPath(profile_path_being_created_);
307   if (!new_profile)
308     return;
309
310   // Non-managed user creation cannot be canceled. (Creating a non-managed
311   // profile shouldn't take significant time, and it can easily be deleted
312   // afterward.)
313   if (!new_profile->IsManaged())
314     return;
315
316   if (user_initiated) {
317     UMA_HISTOGRAM_MEDIUM_TIMES(
318         "Profile.CreateTimeCanceledNoTimeout",
319         base::TimeTicks::Now() - profile_creation_start_time_);
320     RecordProfileCreationMetrics(Profile::CREATE_STATUS_CANCELED);
321   }
322
323   DCHECK(managed_user_registration_utility_.get());
324   managed_user_registration_utility_.reset();
325
326   DCHECK_NE(NO_CREATION_IN_PROGRESS, profile_creation_type_);
327   profile_creation_type_ = NO_CREATION_IN_PROGRESS;
328
329   // Cancelling registration means the callback passed into
330   // RegisterAndInitSync() won't be called, so the cleanup must be done here.
331   profile_path_being_created_.clear();
332   helper::DeleteProfileAtPath(new_profile->GetPath(), web_ui());
333 }
334
335 void CreateProfileHandler::RecordProfileCreationMetrics(
336     Profile::CreateStatus status) {
337   UMA_HISTOGRAM_ENUMERATION("Profile.CreateResult",
338                             status,
339                             Profile::MAX_CREATE_STATUS);
340   UMA_HISTOGRAM_MEDIUM_TIMES(
341       "Profile.CreateTimeNoTimeout",
342       base::TimeTicks::Now() - profile_creation_start_time_);
343 }
344
345 void CreateProfileHandler::RecordSupervisedProfileCreationMetrics(
346     GoogleServiceAuthError::State error_state) {
347   if (profile_creation_type_ == SUPERVISED_PROFILE_CREATION) {
348     UMA_HISTOGRAM_ENUMERATION("Profile.SupervisedProfileCreateError",
349                               error_state,
350                               GoogleServiceAuthError::NUM_STATES);
351     UMA_HISTOGRAM_MEDIUM_TIMES(
352         "Profile.SupervisedProfileTotalCreateTime",
353         base::TimeTicks::Now() - profile_creation_start_time_);
354   } else {
355     DCHECK_EQ(SUPERVISED_PROFILE_IMPORT, profile_creation_type_);
356     UMA_HISTOGRAM_ENUMERATION("Profile.SupervisedProfileImportError",
357                               error_state,
358                               GoogleServiceAuthError::NUM_STATES);
359     UMA_HISTOGRAM_MEDIUM_TIMES(
360         "Profile.SupervisedProfileTotalImportTime",
361         base::TimeTicks::Now() - profile_creation_start_time_);
362   }
363 }
364
365 base::string16 CreateProfileHandler::GetProfileCreationErrorMessage(
366     ProfileCreationErrorType error) const {
367   int message_id = -1;
368   switch (error) {
369     case SIGNIN_ERROR:
370       message_id =
371           profile_creation_type_ == SUPERVISED_PROFILE_IMPORT ?
372               IDS_MANAGED_USER_IMPORT_SIGN_IN_ERROR :
373               IDS_PROFILES_CREATE_SIGN_IN_ERROR;
374       break;
375     case REMOTE_ERROR:
376       message_id =
377           profile_creation_type_ == SUPERVISED_PROFILE_IMPORT ?
378               IDS_MANAGED_USER_IMPORT_REMOTE_ERROR :
379               IDS_PROFILES_CREATE_REMOTE_ERROR;
380       break;
381     case LOCAL_ERROR:
382       message_id =
383           profile_creation_type_ == SUPERVISED_PROFILE_IMPORT ?
384               IDS_MANAGED_USER_IMPORT_LOCAL_ERROR :
385               IDS_PROFILES_CREATE_LOCAL_ERROR;
386       break;
387   }
388
389   return l10n_util::GetStringUTF16(message_id);
390 }
391
392 std::string CreateProfileHandler::GetJavascriptMethodName(
393     ProfileCreationStatus status) const {
394   switch (status) {
395     case PROFILE_CREATION_SUCCESS:
396       return profile_creation_type_ == SUPERVISED_PROFILE_IMPORT ?
397           "BrowserOptions.showManagedUserImportSuccess" :
398           "BrowserOptions.showCreateProfileSuccess";
399     case PROFILE_CREATION_ERROR:
400       return profile_creation_type_ == SUPERVISED_PROFILE_IMPORT ?
401           "BrowserOptions.showManagedUserImportError" :
402           "BrowserOptions.showCreateProfileError";
403   }
404
405   NOTREACHED();
406   return std::string();
407 }
408
409 bool CreateProfileHandler::IsValidExistingManagedUserId(
410     const std::string& existing_managed_user_id) const {
411   if (existing_managed_user_id.empty())
412     return true;
413
414   Profile* profile = Profile::FromWebUI(web_ui());
415   const base::DictionaryValue* dict =
416       ManagedUserSyncServiceFactory::GetForProfile(profile)->GetManagedUsers();
417   if (!dict->HasKey(existing_managed_user_id))
418     return false;
419
420   // Check if this managed user already exists on this machine.
421   const ProfileInfoCache& cache =
422       g_browser_process->profile_manager()->GetProfileInfoCache();
423   for (size_t i = 0; i < cache.GetNumberOfProfiles(); ++i) {
424     if (existing_managed_user_id == cache.GetManagedUserIdOfProfileAtIndex(i))
425       return false;
426   }
427   return true;
428 }
429
430 }  // namespace options