summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorpam@chromium.org <pam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-04 16:38:34 +0000
committerpam@chromium.org <pam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-04 16:38:34 +0000
commit4e2b6f362a9dc6b872976d798769ac8032b305ec (patch)
tree706014161eca3bd985fa571280719c2b7a14acb8 /chrome/browser
parent2deae8c446a92329bc961e003f1594c453455196 (diff)
downloadchromium_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')
-rw-r--r--chrome/browser/chromeos/login/login_utils.cc5
-rw-r--r--chrome/browser/managed_mode/managed_user_registration_service.cc21
-rw-r--r--chrome/browser/managed_mode/managed_user_registration_service.h11
-rw-r--r--chrome/browser/managed_mode/managed_user_service.cc11
-rw-r--r--chrome/browser/managed_mode/managed_user_service.h7
-rw-r--r--chrome/browser/profiles/profile.h8
-rw-r--r--chrome/browser/profiles/profile_impl.h2
-rw-r--r--chrome/browser/profiles/profile_manager.cc4
-rw-r--r--chrome/browser/profiles/profile_manager_browsertest.cc3
-rw-r--r--chrome/browser/profiles/profile_metrics.h1
-rw-r--r--chrome/browser/resources/options/browser_options.js10
-rw-r--r--chrome/browser/resources/options/manage_profile_overlay.html11
-rw-r--r--chrome/browser/resources/options/manage_profile_overlay.js31
-rw-r--r--chrome/browser/ui/app_list/profile_loader.cc6
-rw-r--r--chrome/browser/ui/cocoa/browser_window_controller_browsertest.mm3
-rw-r--r--chrome/browser/ui/sync/one_click_signin_sync_starter.cc95
-rw-r--r--chrome/browser/ui/webui/options/browser_options_handler.cc145
-rw-r--r--chrome/browser/ui/webui/options/browser_options_handler.h24
-rw-r--r--chrome/browser/ui/webui/options/manage_profile_handler.cc35
-rw-r--r--chrome/browser/ui/webui/options/manage_profile_handler.h4
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.