diff options
author | pam@chromium.org <pam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-04 16:38:34 +0000 |
---|---|---|
committer | pam@chromium.org <pam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-04 16:38:34 +0000 |
commit | 4e2b6f362a9dc6b872976d798769ac8032b305ec (patch) | |
tree | 706014161eca3bd985fa571280719c2b7a14acb8 /chrome/browser | |
parent | 2deae8c446a92329bc961e003f1594c453455196 (diff) | |
download | chromium_src-4e2b6f362a9dc6b872976d798769ac8032b305ec.zip chromium_src-4e2b6f362a9dc6b872976d798769ac8032b305ec.tar.gz chromium_src-4e2b6f362a9dc6b872976d798769ac8032b305ec.tar.bz2 |
Pass errors generated during limited-user registration up to the UI for display.
Introduces a new Profile::CREATE_STATUS_REMOTE_FAIL type, and renames
CREATE_STATUS_FAIL to CREATE_STATUS_LOCAL_FAIL. Adds callbacks and reorganizes
profile creation to allow registration errors to propagate back up to the UI
layer, and displays them in the profile creation dialog. Adds a spinner to the
creation dialog. Adds UMA metrics.
BUG=234991
TEST=manual
Review URL: https://chromiumcodereview.appspot.com/15774008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203976 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
20 files changed, 274 insertions, 163 deletions
diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc index cc24c34..32511ba 100644 --- a/chrome/browser/chromeos/login/login_utils.cc +++ b/chrome/browser/chromeos/login/login_utils.cc @@ -447,8 +447,9 @@ void LoginUtilsImpl::OnProfileCreated( case Profile::CREATE_STATUS_CREATED: InitProfilePreferences(user_profile); break; - case Profile::CREATE_STATUS_FAIL: - default: + case Profile::CREATE_STATUS_LOCAL_FAIL: + case Profile::CREATE_STATUS_REMOTE_FAIL: + case Profile::MAX_CREATE_STATUS: NOTREACHED(); break; } diff --git a/chrome/browser/managed_mode/managed_user_registration_service.cc b/chrome/browser/managed_mode/managed_user_registration_service.cc index 093d2d1f..6fbffda 100644 --- a/chrome/browser/managed_mode/managed_user_registration_service.cc +++ b/chrome/browser/managed_mode/managed_user_registration_service.cc @@ -113,12 +113,6 @@ void ManagedUserRegistrationService::Register( weak_ptr_factory_.GetWeakPtr(), name)); } -ProfileManager::CreateCallback -ManagedUserRegistrationService::GetRegistrationAndInitCallback() { - return base::Bind(&ManagedUserRegistrationService::OnProfileCreated, - weak_ptr_factory_.GetWeakPtr()); -} - void ManagedUserRegistrationService::Shutdown() { CancelPendingRegistration(); } @@ -331,18 +325,3 @@ void ManagedUserRegistrationService::DispatchCallback( pending_managed_user_id_.clear(); pending_managed_user_acknowledged_ = false; } - -void ManagedUserRegistrationService::OnProfileCreated( - Profile* profile, - Profile::CreateStatus status) { - // We're being called back twice: once after the profile has been created on - // disk, and once after all the profile services (including the - // ManagedUserService) have been initialized. Ignore the first one. - if (status != Profile::CREATE_STATUS_INITIALIZED) - return; - - ManagedUserService* managed_user_service = - ManagedUserServiceFactory::GetForProfile(profile); - DCHECK(managed_user_service->ProfileIsManaged()); - managed_user_service->RegisterAndInitSync(this); -} diff --git a/chrome/browser/managed_mode/managed_user_registration_service.h b/chrome/browser/managed_mode/managed_user_registration_service.h index d6f9221..5827afe1 100644 --- a/chrome/browser/managed_mode/managed_user_registration_service.h +++ b/chrome/browser/managed_mode/managed_user_registration_service.h @@ -55,15 +55,6 @@ class ManagedUserRegistrationService : public BrowserContextKeyedService, // registration. void Register(const string16& name, const RegistrationCallback& callback); - // Convenience method that registers a new managed user with the server and - // initializes it locally. The callback allows it to be run after a new - // profile has been created: - // ProfileManager::CreateMultiProfileAsync( - // name, icon, - // managed_user_registration_service->GetRegistrationAndInitCallback(), - // managed_user); - ProfileManager::CreateCallback GetRegistrationAndInitCallback(); - // ProfileKeyedService implementation: virtual void Shutdown() OVERRIDE; @@ -103,8 +94,6 @@ class ManagedUserRegistrationService : public BrowserContextKeyedService, // given |error|. void DispatchCallback(const GoogleServiceAuthError& error); - void OnProfileCreated(Profile* profile, Profile::CreateStatus status); - base::WeakPtrFactory<ManagedUserRegistrationService> weak_ptr_factory_; PrefService* prefs_; PrefChangeRegistrar pref_change_registrar_; diff --git a/chrome/browser/managed_mode/managed_user_service.cc b/chrome/browser/managed_mode/managed_user_service.cc index 668c206..a335461 100644 --- a/chrome/browser/managed_mode/managed_user_service.cc +++ b/chrome/browser/managed_mode/managed_user_service.cc @@ -520,24 +520,29 @@ void ManagedUserService::Init() { } void ManagedUserService::RegisterAndInitSync( - ManagedUserRegistrationService* registration_service) { - string16 name = UTF8ToUTF16(profile_->GetProfileName()); + ManagedUserRegistrationService* registration_service, + const ProfileManager::CreateCallback& callback) { + string16 name = UTF8ToUTF16( + profile_->GetPrefs()->GetString(prefs::kProfileName)); registration_service->Register( name, base::Bind(&ManagedUserService::OnManagedUserRegistered, - weak_ptr_factory_.GetWeakPtr())); + weak_ptr_factory_.GetWeakPtr(), callback)); } void ManagedUserService::OnManagedUserRegistered( + const ProfileManager::CreateCallback& callback, const GoogleServiceAuthError& auth_error, const std::string& token) { if (auth_error.state() != GoogleServiceAuthError::NONE) { LOG(ERROR) << "Managed user OAuth error: " << auth_error.ToString(); DCHECK_EQ(std::string(), token); + callback.Run(profile_, Profile::CREATE_STATUS_REMOTE_FAIL); return; } InitSync(token); + callback.Run(profile_, Profile::CREATE_STATUS_INITIALIZED); } void ManagedUserService::UpdateManualHosts() { diff --git a/chrome/browser/managed_mode/managed_user_service.h b/chrome/browser/managed_mode/managed_user_service.h index 103b2e1..8f4f1a3 100644 --- a/chrome/browser/managed_mode/managed_user_service.h +++ b/chrome/browser/managed_mode/managed_user_service.h @@ -13,6 +13,7 @@ #include "base/string16.h" #include "chrome/browser/extensions/management_policy.h" #include "chrome/browser/managed_mode/managed_mode_url_filter.h" +#include "chrome/browser/profiles/profile_manager.h" #include "components/browser_context_keyed_service/browser_context_keyed_service.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -121,7 +122,8 @@ class ManagedUserService : public BrowserContextKeyedService, // Note that |registration_service| should belong to the custodian's profile, // not this one. void RegisterAndInitSync( - ManagedUserRegistrationService* registration_service); + ManagedUserRegistrationService* registration_service, + const ProfileManager::CreateCallback& callback); // Returns a pseudo-email address for systems that expect well-formed email // addresses (like Sync), even though we're not signed in. @@ -176,7 +178,8 @@ class ManagedUserService : public BrowserContextKeyedService, DISALLOW_COPY_AND_ASSIGN(URLFilterContext); }; - void OnManagedUserRegistered(const GoogleServiceAuthError& auth_error, + void OnManagedUserRegistered(const ProfileManager::CreateCallback& callback, + const GoogleServiceAuthError& auth_error, const std::string& token); // Internal implementation for ExtensionManagementPolicy::Delegate methods. diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h index 5ba08c5..41b7c3d 100644 --- a/chrome/browser/profiles/profile.h +++ b/chrome/browser/profiles/profile.h @@ -95,12 +95,16 @@ class Profile : public content::BrowserContext { }; enum CreateStatus { - // Profile services were not created. - CREATE_STATUS_FAIL, + // Profile services were not created due to a local error (e.g., disk full). + CREATE_STATUS_LOCAL_FAIL, + // Profile services were not created due to a remote error (e.g., network + // down during limited-user registration). + CREATE_STATUS_REMOTE_FAIL, // Profile created but before initializing extensions and promo resources. CREATE_STATUS_CREATED, // Profile is created, extensions and promo resources are initialized. CREATE_STATUS_INITIALIZED, + MAX_CREATE_STATUS // For histogram display. }; enum CreateMode { diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h index 6f4f415..4ac54a5 100644 --- a/chrome/browser/profiles/profile_impl.h +++ b/chrome/browser/profiles/profile_impl.h @@ -87,6 +87,8 @@ class ProfileImpl : public Profile { // Profile implementation: virtual scoped_refptr<base::SequencedTaskRunner> GetIOTaskRunner() OVERRIDE; + // Note that this implementation returns the Google-services username, if any, + // not the Chrome user's display name. virtual std::string GetProfileName() OVERRIDE; virtual bool IsOffTheRecord() const OVERRIDE; virtual Profile* GetOffTheRecordProfile() OVERRIDE; diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index 19f2279..4f5b1e8 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc @@ -501,7 +501,7 @@ void ProfileManager::CreateProfileAsync( if (std::find(ProfilesToDelete().begin(), ProfilesToDelete().end(), profile_path) != ProfilesToDelete().end()) { if (!callback.is_null()) - callback.Run(NULL, Profile::CREATE_STATUS_FAIL); + callback.Run(NULL, Profile::CREATE_STATUS_LOCAL_FAIL); return; } @@ -885,7 +885,7 @@ void ProfileManager::OnProfileCreated(Profile* profile, // Invoke INITIALIZED or FAIL for all profiles. RunCallbacks(callbacks, profile, profile ? Profile::CREATE_STATUS_INITIALIZED : - Profile::CREATE_STATUS_FAIL); + Profile::CREATE_STATUS_LOCAL_FAIL); } base::FilePath ProfileManager::GenerateNextProfileDirectoryPath() { diff --git a/chrome/browser/profiles/profile_manager_browsertest.cc b/chrome/browser/profiles/profile_manager_browsertest.cc index b0a3715..45bbb00 100644 --- a/chrome/browser/profiles/profile_manager_browsertest.cc +++ b/chrome/browser/profiles/profile_manager_browsertest.cc @@ -27,7 +27,8 @@ void OnUnblockOnProfileCreation(Profile* profile, } void ProfileCreationComplete(Profile* profile, Profile::CreateStatus status) { - ASSERT_NE(status, Profile::CREATE_STATUS_FAIL); + ASSERT_NE(status, Profile::CREATE_STATUS_LOCAL_FAIL); + ASSERT_NE(status, Profile::CREATE_STATUS_REMOTE_FAIL); // No browser should have been created for this profile yet. EXPECT_EQ(chrome::GetTotalBrowserCountForProfile(profile), 0U); EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); diff --git a/chrome/browser/profiles/profile_metrics.h b/chrome/browser/profiles/profile_metrics.h index 1e8071f..0c2c244 100644 --- a/chrome/browser/profiles/profile_metrics.h +++ b/chrome/browser/profiles/profile_metrics.h @@ -23,6 +23,7 @@ class ProfileMetrics { enum ProfileAdd { ADD_NEW_USER_ICON = 0, // User adds new user from icon menu ADD_NEW_USER_MENU, // User adds new user from menu bar + ADD_NEW_USER_DIALOG, // User adds new user from create-profile dialog NUM_PROFILE_ADD_METRICS }; diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js index 2a846e3..c88e624 100644 --- a/chrome/browser/resources/options/browser_options.js +++ b/chrome/browser/resources/options/browser_options.js @@ -1070,6 +1070,15 @@ cr.define('options', function() { }, /** + * Reports a remote error (e.g., a network error during limited-user + * registration) to the "create" overlay during profile creation. + * @private + */ + showCreateProfileRemoteError_: function() { + CreateProfileOverlay.onRemoteError(); + }, + + /** * Reports successful profile creation to the "create" overlay. * @param {Object} profileInfo An object of the form: * profileInfo = { @@ -1464,6 +1473,7 @@ cr.define('options', function() { 'setupProxySettingsSection', 'showBluetoothSettings', 'showCreateProfileLocalError', + 'showCreateProfileRemoteError', 'showCreateProfileSuccess', 'showMouseControls', 'showTouchpadControls', diff --git a/chrome/browser/resources/options/manage_profile_overlay.html b/chrome/browser/resources/options/manage_profile_overlay.html index 94833a2..e7822b2 100644 --- a/chrome/browser/resources/options/manage_profile_overlay.html +++ b/chrome/browser/resources/options/manage_profile_overlay.html @@ -88,10 +88,13 @@ </label> </div> </div> - <div class="action-area button-strip"> - <button id="create-profile-cancel" i18n-content="cancel"></button> - <button id="create-profile-ok" i18n-content="createProfileConfirm"> - </button> + <div class="action-area"> + <div id="create-profile-throbber" class="throbber"></div> + <div class="button-strip"> + <button id="create-profile-cancel" i18n-content="cancel"></button> + <button id="create-profile-ok" i18n-content="createProfileConfirm"> + </button> + </div> </div> </div> </div> diff --git a/chrome/browser/resources/options/manage_profile_overlay.js b/chrome/browser/resources/options/manage_profile_overlay.js index 738f5f3..47948ee 100644 --- a/chrome/browser/resources/options/manage_profile_overlay.js +++ b/chrome/browser/resources/options/manage_profile_overlay.js @@ -51,8 +51,8 @@ cr.define('options', function() { // Override the create-profile-ok handler, to avoid closing the overlay // until we finish creating the profile. $('create-profile-ok').onclick = function(event) { + CreateProfileOverlay.updateCreateInProgress(true); ManageProfileOverlay.getInstance().hideErrorBubble_('create'); - $('create-profile-ok').disabled = true; self.submitCreateProfile_(); }; @@ -433,6 +433,7 @@ cr.define('options', function() { $('create-profile-instructions').textContent = loadTimeData.getStringF('createProfileInstructions'); this.hideErrorBubble_(); + this.updateCreateInProgress_(false); var shortcutsEnabled = loadTimeData.getBoolean('profileShortcutsEnabled'); $('create-shortcut-container').hidden = !shortcutsEnabled; @@ -456,17 +457,39 @@ cr.define('options', function() { }, /** + * Updates the UI when a profile create step begins or ends. + * @param {boolean} inProgress True if the UI should be updated to show that + * profile creation is now in progress. + * @private + */ + updateCreateInProgress_: function(inProgress) { + $('create-profile-ok').disabled = inProgress; + $('create-profile-throbber').hidden = !inProgress; + }, + + /** * Shows an error message describing a local error (most likely a disk * error) when creating a new profile. Called by BrowserOptions via the * BrowserOptionsHandler. * @private */ onLocalError_: function() { - $('create-profile-ok').disabled = false; + this.updateCreateInProgress_(false); this.showErrorBubble_('createProfileLocalError'); }, /** + * Shows an error message describing a remote error (most likely a network + * error) when creating a new profile. Called by BrowserOptions via the + * BrowserOptionsHandler. + * @private + */ + onRemoteError_: function() { + this.updateCreateInProgress_(false); + this.showErrorBubble_('createProfileRemoteError'); + }, + + /** * For new limited users, shows a confirmation page after successfully * creating a new profile; otherwise, the handler will open a new window. * @param {Object} profileInfo An object of the form: @@ -478,8 +501,8 @@ cr.define('options', function() { * @private */ onSuccess_: function(profileInfo) { + this.updateCreateInProgress_(false); OptionsPage.closeOverlay(); - $('create-profile-ok').disabled = false; if (profileInfo.isManaged) { ManagedUserCreateConfirmOverlay.setProfileInfo(profileInfo); OptionsPage.navigateToPage('managedUserCreateConfirm'); @@ -506,7 +529,9 @@ cr.define('options', function() { // Forward public APIs to private implementations. [ 'onLocalError', + 'onRemoteError', 'onSuccess', + 'updateCreateInProgress', 'updateSignedInStatus', ].forEach(function(name) { CreateProfileOverlay[name] = function() { diff --git a/chrome/browser/ui/app_list/profile_loader.cc b/chrome/browser/ui/app_list/profile_loader.cc index b7c5af3..e3413f5 100644 --- a/chrome/browser/ui/app_list/profile_loader.cc +++ b/chrome/browser/ui/app_list/profile_loader.cc @@ -59,9 +59,13 @@ void ProfileLoader::OnProfileLoaded(int profile_load_sequence_id, callback.Run(profile); DecrementPendingProfileLoads(); break; - case Profile::CREATE_STATUS_FAIL: + case Profile::CREATE_STATUS_LOCAL_FAIL: + case Profile::CREATE_STATUS_REMOTE_FAIL: DecrementPendingProfileLoads(); break; + case Profile::MAX_CREATE_STATUS: + NOTREACHED(); + break; } } diff --git a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm index 0cacf34..563f502 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm @@ -49,7 +49,8 @@ void CreateProfileCallback(const base::Closure& quit_closure, Profile* profile, Profile::CreateStatus status) { EXPECT_TRUE(profile); - EXPECT_NE(Profile::CREATE_STATUS_FAIL, status); + EXPECT_NE(Profile::CREATE_STATUS_LOCAL_FAIL, status); + EXPECT_NE(Profile::CREATE_STATUS_REMOTE_FAIL, status); // This will be called multiple times. Wait until the profile is initialized // fully to quit the loop. if (status == Profile::CREATE_STATUS_INITIALIZED) diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc index df57a20..b83c521 100644 --- a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc +++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc @@ -214,49 +214,60 @@ void OneClickSigninSyncStarter::CompleteInitForNewProfile( Profile* new_profile, Profile::CreateStatus status) { DCHECK_NE(profile_, new_profile); - if (status == Profile::CREATE_STATUS_FAIL) { - // TODO(atwilson): On error, unregister the client to release the DMToken - // and surface a better error for the user. - NOTREACHED() << "Error creating new profile"; - CancelSigninAndDelete(); - return; - } - // Wait until the profile is initialized before we transfer credentials. - if (status == Profile::CREATE_STATUS_INITIALIZED) { - SigninManager* old_signin_manager = - SigninManagerFactory::GetForProfile(profile_); - SigninManager* new_signin_manager = - SigninManagerFactory::GetForProfile(new_profile); - DCHECK(!old_signin_manager->GetUsernameForAuthInProgress().empty()); - DCHECK(old_signin_manager->GetAuthenticatedUsername().empty()); - DCHECK(new_signin_manager->GetAuthenticatedUsername().empty()); - DCHECK(policy_client_); - - // Copy credentials from the old profile to the just-created profile, - // and switch over to tracking that profile. - new_signin_manager->CopyCredentialsFrom(*old_signin_manager); - FinishProfileSyncServiceSetup(); - Initialize(new_profile, NULL); - DCHECK_EQ(profile_, new_profile); - - // We've transferred our credentials to the new profile - notify that - // the signin for the original profile was cancelled (must do this after - // we have called Initialize() with the new profile, as otherwise this - // object will get freed when the signin on the old profile is cancelled. - old_signin_manager->SignOut(); - - // Load policy for the just-created profile - once policy has finished - // loading the signin process will complete. - LoadPolicyWithCachedClient(); - - // Open the profile's first window, after all initialization. - ProfileManager::FindOrCreateNewWindowForProfile( - new_profile, - chrome::startup::IS_PROCESS_STARTUP, - chrome::startup::IS_FIRST_RUN, - desktop_type, - false); + // TODO(atwilson): On error, unregister the client to release the DMToken + // and surface a better error for the user. + switch (status) { + case Profile::CREATE_STATUS_LOCAL_FAIL: { + NOTREACHED() << "Error creating new profile"; + CancelSigninAndDelete(); + return; + } + case Profile::CREATE_STATUS_CREATED: { + break; + } + case Profile::CREATE_STATUS_INITIALIZED: { + // Wait until the profile is initialized before we transfer credentials. + SigninManager* old_signin_manager = + SigninManagerFactory::GetForProfile(profile_); + SigninManager* new_signin_manager = + SigninManagerFactory::GetForProfile(new_profile); + DCHECK(!old_signin_manager->GetUsernameForAuthInProgress().empty()); + DCHECK(old_signin_manager->GetAuthenticatedUsername().empty()); + DCHECK(new_signin_manager->GetAuthenticatedUsername().empty()); + DCHECK(policy_client_); + + // Copy credentials from the old profile to the just-created profile, + // and switch over to tracking that profile. + new_signin_manager->CopyCredentialsFrom(*old_signin_manager); + FinishProfileSyncServiceSetup(); + Initialize(new_profile, NULL); + DCHECK_EQ(profile_, new_profile); + + // We've transferred our credentials to the new profile - notify that + // the signin for the original profile was cancelled (must do this after + // we have called Initialize() with the new profile, as otherwise this + // object will get freed when the signin on the old profile is cancelled. + old_signin_manager->SignOut(); + + // Load policy for the just-created profile - once policy has finished + // loading the signin process will complete. + LoadPolicyWithCachedClient(); + + // Open the profile's first window, after all initialization. + ProfileManager::FindOrCreateNewWindowForProfile( + new_profile, + chrome::startup::IS_PROCESS_STARTUP, + chrome::startup::IS_FIRST_RUN, + desktop_type, + false); + } + case Profile::CREATE_STATUS_REMOTE_FAIL: + case Profile::MAX_CREATE_STATUS: { + NOTREACHED() << "Invalid profile creation status"; + CancelSigninAndDelete(); + return; + } } } #endif diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc index 322ec96..88ee101 100644 --- a/chrome/browser/ui/webui/options/browser_options_handler.cc +++ b/chrome/browser/ui/webui/options/browser_options_handler.cc @@ -12,6 +12,7 @@ #include "base/bind_helpers.h" #include "base/command_line.h" #include "base/memory/singleton.h" +#include "base/metrics/histogram.h" #include "base/path_service.h" #include "base/prefs/pref_service.h" #include "base/stl_util.h" @@ -32,8 +33,10 @@ #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h" #include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h" #include "chrome/browser/printing/cloud_print/cloud_print_url.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_info_cache.h" #include "chrome/browser/profiles/profile_info_util.h" +#include "chrome/browser/profiles/profile_metrics.h" #include "chrome/browser/profiles/profile_shortcut_manager.h" #include "chrome/browser/search/search.h" #include "chrome/browser/search_engines/template_url.h" @@ -146,6 +149,31 @@ void CreateDesktopShortcutForProfile(Profile* profile, shortcut_manager->CreateProfileShortcut(profile->GetPath()); } +void RunProfileCreationCallbacks( + const std::vector<ProfileManager::CreateCallback>& callbacks, + Profile* profile, + Profile::CreateStatus status) { + std::vector<ProfileManager::CreateCallback>::const_iterator it; + for (it = callbacks.begin(); it != callbacks.end(); ++it) { + it->Run(profile, status); + } +} + +void OpenNewWindowForProfile( + chrome::HostDesktopType desktop_type, + Profile* profile, + Profile::CreateStatus status) { + if (status != Profile::CREATE_STATUS_INITIALIZED) + return; + + ProfileManager::FindOrCreateNewWindowForProfile( + profile, + chrome::startup::IS_PROCESS_STARTUP, + chrome::startup::IS_FIRST_RUN, + desktop_type, + false); +} + } // namespace BrowserOptionsHandler::BrowserOptionsHandler() @@ -485,9 +513,8 @@ void BrowserOptionsHandler::GetLocalizedValues(DictionaryValue* values) { values->Set("profilesInfo", GetProfilesInfoList().release()); #if defined(ENABLE_MANAGED_USERS) - ManagedUserService* service = - ManagedUserServiceFactory::GetForProfile(Profile::FromWebUI(web_ui())); - values->SetBoolean("profileIsManaged", service->ProfileIsManaged()); + values->SetBoolean("profileIsManaged", + ManagedUserService::ProfileIsManaged(Profile::FromWebUI(web_ui()))); #endif #if !defined(OS_CHROMEOS) @@ -539,6 +566,10 @@ void BrowserOptionsHandler::RegisterMessages() { base::Bind(&BrowserOptionsHandler::CreateProfile, base::Unretained(this))); web_ui()->RegisterMessageCallback( + "deleteProfile", + base::Bind(&BrowserOptionsHandler::DeleteProfile, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( "themesReset", base::Bind(&BrowserOptionsHandler::ThemesReset, base::Unretained(this))); @@ -1064,9 +1095,7 @@ void BrowserOptionsHandler::CreateProfile(const ListValue* args) { // This handler could have been called in managed mode, for example because // the user fiddled with the web inspector. Silently return in this case. Profile* profile = Profile::FromWebUI(web_ui()); - ManagedUserService* service = - ManagedUserServiceFactory::GetForProfile(profile); - if (service->ProfileIsManaged()) + if (ManagedUserService::ProfileIsManaged(profile)) return; #endif @@ -1081,7 +1110,6 @@ void BrowserOptionsHandler::CreateProfile(const ListValue* args) { string16 name; string16 icon; - std::vector<ProfileManager::CreateCallback> callbacks; bool create_shortcut = false; bool managed_user = false; if (args->GetString(0, &name) && args->GetString(1, &icon)) { @@ -1091,41 +1119,71 @@ void BrowserOptionsHandler::CreateProfile(const ListValue* args) { } } + std::vector<ProfileManager::CreateCallback> callbacks; if (create_shortcut) callbacks.push_back(base::Bind(&CreateDesktopShortcutForProfile)); + ProfileManager::CreateCallback show_user_feedback = + base::Bind(&BrowserOptionsHandler::ShowProfileCreationFeedback, + weak_ptr_factory_.GetWeakPtr(), desktop_type, managed_user); + if (managed_user && ManagedUserService::AreManagedUsersEnabled()) { #if defined(ENABLE_MANAGED_USERS) - ManagedUserRegistrationService* registration_service = - ManagedUserRegistrationServiceFactory::GetForProfile(profile); - callbacks.push_back(registration_service->GetRegistrationAndInitCallback()); + callbacks.push_back( + base::Bind(&BrowserOptionsHandler::RegisterNewManagedUser, + weak_ptr_factory_.GetWeakPtr(), show_user_feedback)); #else NOTREACHED(); #endif + } else { + callbacks.push_back(show_user_feedback); } + ProfileMetrics::LogProfileAddNewUser(ProfileMetrics::ADD_NEW_USER_DIALOG); + ProfileManager::CreateMultiProfileAsync( - name, icon, base::Bind(&BrowserOptionsHandler::OnProfileCreated, - weak_ptr_factory_.GetWeakPtr(), - desktop_type, managed_user, callbacks), + name, icon, base::Bind(&RunProfileCreationCallbacks, callbacks), managed_user); } -void BrowserOptionsHandler::OnProfileCreated( +void BrowserOptionsHandler::RegisterNewManagedUser( + const ProfileManager::CreateCallback& callback, + Profile* profile, + Profile::CreateStatus status) { + if (status != Profile::CREATE_STATUS_INITIALIZED) + return; + + ManagedUserService* managed_user_service = + ManagedUserServiceFactory::GetForProfile(profile); + DCHECK(managed_user_service->ProfileIsManaged()); + ManagedUserRegistrationService* registration_service = + ManagedUserRegistrationServiceFactory::GetForProfile(profile); + + managed_user_service->RegisterAndInitSync(registration_service, callback); +} + +void BrowserOptionsHandler::ShowProfileCreationFeedback( chrome::HostDesktopType desktop_type, bool is_managed, - const std::vector<ProfileManager::CreateCallback>& callbacks, Profile* profile, Profile::CreateStatus status) { - std::vector<ProfileManager::CreateCallback>::const_iterator it; - for (it = callbacks.begin(); it != callbacks.end(); ++it) { - it->Run(profile, status); + if (status != Profile::CREATE_STATUS_CREATED) { + UMA_HISTOGRAM_ENUMERATION("Profile.CreateResult", + status, + Profile::MAX_CREATE_STATUS); } switch (status) { - case Profile::CREATE_STATUS_FAIL: { + case Profile::CREATE_STATUS_LOCAL_FAIL: { web_ui()->CallJavascriptFunction( "BrowserOptions.showCreateProfileLocalError"); + DeleteProfileAtPath(profile->GetPath()); + break; + } + case Profile::CREATE_STATUS_REMOTE_FAIL: { + web_ui()->CallJavascriptFunction( + "BrowserOptions.showCreateProfileRemoteError"); + DeleteProfileAtPath(profile->GetPath()); break; } case Profile::CREATE_STATUS_CREATED: { @@ -1147,18 +1205,55 @@ void BrowserOptionsHandler::OnProfileCreated( if (!is_managed) { // Opening the new window must be the last action, after all callbacks // have been run, to give them a chance to initialize the profile. - ProfileManager::FindOrCreateNewWindowForProfile( - profile, - chrome::startup::IS_PROCESS_STARTUP, - chrome::startup::IS_FIRST_RUN, - desktop_type, - false); + OpenNewWindowForProfile(desktop_type, + profile, + Profile::CREATE_STATUS_INITIALIZED); } break; } + case Profile::MAX_CREATE_STATUS: { + NOTREACHED(); + break; + } } } +void BrowserOptionsHandler::DeleteProfile(const ListValue* args) { + DCHECK(args); + const Value* file_path_value; + if (!args->Get(0, &file_path_value)) + return; + + base::FilePath file_path; + if (!base::GetValueAsFilePath(*file_path_value, &file_path)) + return; + DeleteProfileAtPath(file_path); +} + +void BrowserOptionsHandler::DeleteProfileAtPath(base::FilePath file_path) { +#if defined(ENABLE_MANAGED_USERS) + // This handler could have been called in managed mode, for example because + // the user fiddled with the web inspector. Silently return in this case. + if (ManagedUserService::ProfileIsManaged(Profile::FromWebUI(web_ui()))) + return; +#endif + + if (!ProfileManager::IsMultipleProfilesEnabled()) + return; + + ProfileMetrics::LogProfileDeleteUser(ProfileMetrics::PROFILE_DELETED); + + Browser* browser = + chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()); + chrome::HostDesktopType desktop_type = chrome::HOST_DESKTOP_TYPE_NATIVE; + if (browser) + desktop_type = browser->host_desktop_type(); + + g_browser_process->profile_manager()->ScheduleProfileForDeletion( + file_path, + base::Bind(&OpenNewWindowForProfile, desktop_type)); +} + void BrowserOptionsHandler::ObserveThemeChanged() { Profile* profile = Profile::FromWebUI(web_ui()); #if defined(TOOLKIT_GTK) diff --git a/chrome/browser/ui/webui/options/browser_options_handler.h b/chrome/browser/ui/webui/options/browser_options_handler.h index 6343658..4f748fc 100644 --- a/chrome/browser/ui/webui/options/browser_options_handler.h +++ b/chrome/browser/ui/webui/options/browser_options_handler.h @@ -144,7 +144,7 @@ class BrowserOptionsHandler // Sends an array of Profile objects to javascript. void SendProfilesInfo(); - // Asynchronously opens a new browser window to create a new profile. + // Asynchronously creates and initializes a new profile. // The arguments are as follows: // 0: name (string) // 1: icon (string) @@ -153,15 +153,29 @@ class BrowserOptionsHandler // 3: a flag stating whether the user should be managed (optional, boolean) void CreateProfile(const base::ListValue* args); - // Handles final tasks when a new profile has been created, running any queued - // callbacks and updating the UI. - void OnProfileCreated( + // After a new managed-user profile has been created, registers the user with + // the management server. This is a class method to ensure that the + // registration service (on the custodian's profile, along with this WebUI + // class) still exists after the new managed profile has been created + // asynchronously. + void RegisterNewManagedUser(const ProfileManager::CreateCallback& callback, + Profile* profile, + Profile::CreateStatus status); + + // Updates the UI as the final task after a new profile has been created. + void ShowProfileCreationFeedback( chrome::HostDesktopType desktop_type, bool is_managed, - const std::vector<ProfileManager::CreateCallback>& callbacks, Profile* profile, Profile::CreateStatus status); + // Deletes the given profile. Expects one argument: + // 0: profile file path (string) + void DeleteProfile(const base::ListValue* args); + + // Deletes the profile at the given |file_path|. + void DeleteProfileAtPath(base::FilePath file_path); + void ObserveThemeChanged(); void ThemesReset(const base::ListValue* args); #if defined(TOOLKIT_GTK) diff --git a/chrome/browser/ui/webui/options/manage_profile_handler.cc b/chrome/browser/ui/webui/options/manage_profile_handler.cc index 42867cc..7395ac8 100644 --- a/chrome/browser/ui/webui/options/manage_profile_handler.cc +++ b/chrome/browser/ui/webui/options/manage_profile_handler.cc @@ -103,6 +103,7 @@ void ManageProfileHandler::GetLocalizedValues( { "createProfileInstructions", IDS_PROFILES_CREATE_INSTRUCTIONS }, { "createProfileConfirm", IDS_PROFILES_CREATE_CONFIRM }, { "createProfileLocalError", IDS_PROFILES_CREATE_LOCAL_ERROR }, + { "createProfileRemoteError", IDS_PROFILES_CREATE_REMOTE_ERROR }, { "createProfileShortcut", IDS_PROFILES_CREATE_SHORTCUT }, { "removeProfileShortcut", IDS_PROFILES_REMOVE_SHORTCUT }, }; @@ -132,9 +133,6 @@ void ManageProfileHandler::RegisterMessages() { web_ui()->RegisterMessageCallback("setProfileNameAndIcon", base::Bind(&ManageProfileHandler::SetProfileNameAndIcon, base::Unretained(this))); - web_ui()->RegisterMessageCallback("deleteProfile", - base::Bind(&ManageProfileHandler::DeleteProfile, - base::Unretained(this))); web_ui()->RegisterMessageCallback("requestDefaultProfileIcons", base::Bind(&ManageProfileHandler::RequestDefaultProfileIcons, base::Unretained(this))); @@ -315,37 +313,6 @@ void ManageProfileHandler::SetProfileNameAndIcon(const ListValue* args) { ProfileMetrics::LogProfileUpdate(profile_file_path); } -void ManageProfileHandler::DeleteProfile(const ListValue* args) { - DCHECK(args); -#if defined(ENABLE_MANAGED_USERS) - // This handler could have been called in managed mode, for example because - // the user fiddled with the web inspector. Silently return in this case. - ManagedUserService* service = - ManagedUserServiceFactory::GetForProfile(Profile::FromWebUI(web_ui())); - if (service->ProfileIsManaged()) - return; -#endif - - if (!ProfileManager::IsMultipleProfilesEnabled()) - return; - - ProfileMetrics::LogProfileDeleteUser(ProfileMetrics::PROFILE_DELETED); - - base::FilePath profile_file_path; - if (!GetProfilePathFromArgs(args, &profile_file_path)) - return; - - Browser* browser = - chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()); - chrome::HostDesktopType desktop_type = chrome::HOST_DESKTOP_TYPE_NATIVE; - if (browser) - desktop_type = browser->host_desktop_type(); - - g_browser_process->profile_manager()->ScheduleProfileForDeletion( - profile_file_path, - base::Bind(&OnNewDefaultProfileCreated, desktop_type)); -} - #if defined(ENABLE_SETTINGS_APP) void ManageProfileHandler::SwitchAppListProfile(const ListValue* args) { DCHECK(args); diff --git a/chrome/browser/ui/webui/options/manage_profile_handler.h b/chrome/browser/ui/webui/options/manage_profile_handler.h index 8fd252e..6872cf5 100644 --- a/chrome/browser/ui/webui/options/manage_profile_handler.h +++ b/chrome/browser/ui/webui/options/manage_profile_handler.h @@ -70,10 +70,6 @@ class ManageProfileHandler : public OptionsPageUIHandler { // ] void SetProfileNameAndIcon(const base::ListValue* args); - // Callback for the "deleteProfile" message. Deletes the given profile. - // |args| is of the form: [ {string} profileFilePath ] - void DeleteProfile(const base::ListValue* args); - #if defined(ENABLE_SETTINGS_APP) // Callback for the "switchAppListProfile" message. Asks the // app_list_controller to change the profile registered for the AppList. |