Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1206)

Unified Diff: chrome/browser/ui/views/profiles/profile_chooser_view.cc

Issue 2151513002: Revamped signin/sync error surfacing on desktop user menu (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/profiles/profile_chooser_view.cc
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index cbae94c49150976daea87beb1a9ca1efbfd16644..670d5d98ba37045b7c83c5b02a26cf153b344354 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -21,6 +21,7 @@
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/signin/signin_promo.h"
#include "chrome/browser/signin/signin_ui_util.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_dialogs.h"
@@ -36,12 +37,14 @@
#include "chrome/common/url_constants.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
+#include "components/browser_sync/browser/profile_sync_service.h"
#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_error_controller.h"
#include "components/signin/core/browser/signin_header_helper.h"
#include "components/signin/core/browser/signin_manager.h"
#include "components/signin/core/common/profile_management_switches.h"
+#include "components/sync_driver/sync_error_controller.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/user_metrics.h"
#include "grit/theme_resources.h"
@@ -788,6 +791,11 @@ void ProfileChooserView::ResetView() {
tutorial_see_whats_new_button_ = nullptr;
tutorial_not_you_link_ = nullptr;
tutorial_learn_more_link_ = nullptr;
+ sync_error_signin_button_ = nullptr;
msw 2016/07/13 22:31:38 nit: order to match the decl of all these members.
Jane 2016/07/14 00:18:58 Done.
+ sync_error_passphrase_button_ = nullptr;
+ sync_error_upgrade_button_ = nullptr;
+ sync_error_signin_again_button_ = nullptr;
+ sync_error_signout_button_ = nullptr;
}
void ProfileChooserView::Init() {
@@ -872,7 +880,11 @@ void ProfileChooserView::ShowView(profiles::BubbleViewMode view_to_display,
DCHECK(switches::IsEnableAccountConsistency());
const AvatarMenu::Item& active_item = avatar_menu->GetItemAt(
avatar_menu->GetActiveProfileIndex());
- DCHECK(active_item.signed_in);
+ if (!active_item.signed_in)
msw 2016/07/13 22:31:38 Add curlies here or move the comment above the if
Jane 2016/07/14 00:18:58 Done.
+ // This is the case when the user selects the sign out option in the user
+ // menu upon encountering unrecoverable error. Then following the action,
msw 2016/07/13 22:31:37 nit: "errors"
Jane 2016/07/14 00:18:57 Done.
+ // profile chooser view would be shown instead of account management view.
msw 2016/07/13 22:31:38 nit: "Afterwards, the profile chooser view is show
Jane 2016/07/14 00:18:58 Done.
+ view_to_display = profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER;
}
if (browser_->profile()->IsSupervised() &&
@@ -1000,8 +1012,22 @@ void ProfileChooserView::ButtonPressed(views::Button* sender,
PostActionPerformed(ProfileMetrics::PROFILE_DESKTOP_MENU_LOCK);
} else if (sender == close_all_windows_button_) {
profiles::CloseProfileWindows(browser_->profile());
- } else if (sender == auth_error_email_button_) {
+ } else if (sender == auth_error_email_button_ ||
+ sender == sync_error_signin_button_) {
ShowViewFromMode(profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH);
+ } else if (sender == sync_error_passphrase_button_) {
+ chrome::ShowSettingsSubPage(browser_, chrome::kSyncSetupSubPage);
+ } else if (sender == sync_error_upgrade_button_) {
+ chrome::OpenUpdateChromeDialog(browser_);
+ } else if (sender == sync_error_signin_again_button_) {
+ if (ProfileSyncServiceFactory::GetForProfile(browser_->profile()))
+ ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS);
+ SigninManagerFactory::GetForProfile(browser_->profile())
+ ->SignOut(signin_metrics::USER_CLICKED_SIGNOUT_SETTINGS,
+ signin_metrics::SignoutDelete::IGNORE_METRIC);
+ ShowViewFromMode(profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN);
+ } else if (sender == sync_error_signout_button_) {
+ chrome::ShowSettingsSubPage(browser_, chrome::kSignOutSubPage);
} else if (sender == tutorial_sync_settings_ok_button_) {
LoginUIServiceFactory::GetForProfile(browser_->profile())->
SyncConfirmationUIClosed(LoginUIService::SYNC_WITH_DEFAULT_SETTINGS);
@@ -1175,6 +1201,7 @@ void ProfileChooserView::PopulateCompleteProfileChooserView(
// Separate items into active and alternatives.
Indexes other_profiles;
views::View* tutorial_view = NULL;
+ views::View* sync_error_view = NULL;
views::View* current_profile_view = NULL;
views::View* current_profile_accounts = NULL;
views::View* option_buttons_view = NULL;
@@ -1189,10 +1216,14 @@ void ProfileChooserView::PopulateCompleteProfileChooserView(
? CreateMaterialDesignCurrentProfileView(item, false)
: CreateCurrentProfileView(item, false);
if (IsProfileChooser(view_mode_)) {
- tutorial_view = CreateTutorialViewIfNeeded(item);
+ if (!switches::IsMaterialDesignUserMenu())
msw 2016/07/13 22:31:38 Do we really not want tutorial_view in MD? Call th
Jane 2016/07/14 00:18:58 Yep, this is an explicit decision and is briefly m
msw 2016/07/14 02:23:33 Acknowledged.
+ tutorial_view = CreateTutorialViewIfNeeded(item);
} else {
current_profile_accounts = CreateCurrentProfileAccountsView(item);
}
+ if (switches::IsMaterialDesignUserMenu()) {
msw 2016/07/13 22:31:38 nit: curlies not needed
Jane 2016/07/14 00:18:57 Done.
+ sync_error_view = CreateSyncErrorViewIfNeeded();
+ }
} else {
other_profiles.push_back(i);
}
@@ -1206,6 +1237,13 @@ void ProfileChooserView::PopulateCompleteProfileChooserView(
tutorial_mode_ = profiles::TUTORIAL_MODE_NONE;
}
+ if (sync_error_view) {
+ layout->StartRow(1, 0);
+ layout->AddView(sync_error_view);
+ layout->StartRow(0, 0);
+ layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
+ }
+
if (!current_profile_view) {
// Guest windows don't have an active profile.
current_profile_view = CreateGuestProfileView();
@@ -1434,6 +1472,137 @@ views::View* ProfileChooserView::CreateTutorialView(
return view;
}
+views::View* ProfileChooserView::CreateSyncErrorViewIfNeeded() {
+ ProfileSyncService* service =
+ ProfileSyncServiceFactory::GetForProfile(browser_->profile());
+
+ // The order or priority is going to be: 1. Unrecoverable errors.
+ // 2. Auth errors. 3. Protocol errors. 4. Passphrase errors.
+ if (service && service->HasUnrecoverableError()) {
+ // Unrecoverable error is sometimes accompanied by actionable error.
msw 2016/07/13 22:31:38 nit: "An unrecoverable" and "an actionable"
Jane 2016/07/14 00:18:58 Done.
+ // If actionable error is not set to be UPGRADE_CLIENT, then show generic
msw 2016/07/13 22:31:38 nit: "an actionable" and "show a generic"
Jane 2016/07/14 00:18:58 Done.
+ // unrecoverable error message.
+ ProfileSyncService::Status status;
+ service->QueryDetailedSyncStatus(&status);
+ if (status.sync_protocol_error.action != syncer::UPGRADE_CLIENT) {
+ // Display different error messages and buttons depending on whether it
msw 2016/07/13 22:31:38 nit: "Display different messages and buttons for m
Jane 2016/07/14 00:18:58 Done.
+ // is a managed account.
+ if (SigninManagerFactory::GetForProfile(browser_->profile())
+ ->IsSignoutProhibited()) {
+ return CreateSyncErrorView(
+ l10n_util::GetStringUTF16(
+ IDS_SYNC_ERROR_USER_MENU_SIGNOUT_MESSAGE),
msw 2016/07/13 22:31:38 Did you flip the intended values here? You're usin
Jane 2016/07/14 00:18:58 The values are not flipped. AFAIU, IsSignoutProhib
msw 2016/07/14 02:23:33 This seems highly counter-intuitive, and deserves
Jane 2016/07/14 15:34:37 So Roger said this is the right function to use. I
+ l10n_util::GetStringUTF16(
+ IDS_SYNC_ERROR_USER_MENU_SIGNOUT_BUTTON),
+ &sync_error_signout_button_);
+ } else {
msw 2016/07/13 22:31:38 nit: no else after return.
Jane 2016/07/14 00:18:57 Done.
+ return CreateSyncErrorView(
+ l10n_util::GetStringUTF16(
+ IDS_SYNC_ERROR_USER_MENU_SIGNIN_AGAIN_MESSAGE),
+ l10n_util::GetStringUTF16(
+ IDS_SYNC_ERROR_USER_MENU_SIGNIN_AGAIN_BUTTON),
+ &sync_error_signin_again_button_);
+ }
+ }
+ }
+
+ // Check for an auth error.
+ if (HasAuthError(browser_->profile())) {
+ return CreateSyncErrorView(
+ l10n_util::GetStringUTF16(IDS_SYNC_ERROR_USER_MENU_LOGIN_MESSAGE),
+ l10n_util::GetStringUTF16(IDS_SYNC_ERROR_USER_MENU_LOGIN_BUTTON),
+ &sync_error_signin_button_);
+ }
+
+ // Check for sync errors if the sync service is enabled.
+ if (service) {
+ // Check for an actionable error UPGRADE_CLIENT.
msw 2016/07/13 22:31:38 nit: "actionable UPGRADE_CLIENT error"?
Jane 2016/07/14 00:18:58 Done.
+ ProfileSyncService::Status status;
+ service->QueryDetailedSyncStatus(&status);
+ if (status.sync_protocol_error.action == syncer::UPGRADE_CLIENT) {
+ return CreateSyncErrorView(
+ l10n_util::GetStringUTF16(IDS_SYNC_ERROR_USER_MENU_UPGRADE_MESSAGE),
+ l10n_util::GetStringUTF16(IDS_SYNC_ERROR_USER_MENU_UPGRADE_BUTTON),
+ &sync_error_upgrade_button_);
+ }
+
+ // Check for a sync passphrase error.
+ SyncErrorController* sync_error_controller =
+ service->sync_error_controller();
+ if (sync_error_controller && sync_error_controller->HasError()) {
+ return CreateSyncErrorView(
+ l10n_util::GetStringUTF16(
+ IDS_SYNC_ERROR_USER_MENU_PASSPHRASE_MESSAGE),
+ l10n_util::GetStringUTF16(IDS_SYNC_ERROR_USER_MENU_PASSPHRASE_BUTTON),
+ &sync_error_passphrase_button_);
+ }
+ }
+
+ // There is no error.
+ return nullptr;
+}
+
+views::View* ProfileChooserView::CreateSyncErrorView(
+ const base::string16& content_text,
msw 2016/07/13 22:31:38 nit: take a resource ID here instead of the string
Jane 2016/07/14 00:18:58 Good suggestion! Changed it.
+ const base::string16& button_text,
+ views::LabelButton** button) {
msw 2016/07/13 22:31:38 nit: button_out... it'd be nice if we used |views:
Jane 2016/07/14 00:18:58 Done.
+ // Sets an overall horizontal layout.
+ views::View* view = new views::View();
+ views::BoxLayout* layout = new views::BoxLayout(
+ views::BoxLayout::kHorizontal, kMaterialMenuEdgeMargin,
+ kMaterialMenuEdgeMargin, views::kUnrelatedControlHorizontalSpacing);
+ layout->set_cross_axis_alignment(
+ views::BoxLayout::CROSS_AXIS_ALIGNMENT_START);
+ view->SetLayoutManager(layout);
+
+ // Adds the sync problem icon.
+ views::ImageView* sync_problem_icon = new views::ImageView();
+ sync_problem_icon->SetImage(gfx::CreateVectorIcon(
+ gfx::VectorIconId::SYNC_PROBLEM, 20, gfx::kGoogleRed700));
+ view->AddChildView(sync_problem_icon);
+
+ // Adds a vertical view to organize the error title, message, and button.
msw 2016/07/13 22:31:38 nit: GridLayout *might* be simpler than nesting Bo
Jane 2016/07/14 00:18:58 Oh, right, maybe, but I thought this was pretty st
+ views::View* vertical_view = new views::View();
+ views::BoxLayout* vertical_layout =
+ new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
+ views::kRelatedControlSmallVerticalSpacing);
+ vertical_layout->set_cross_axis_alignment(
+ views::BoxLayout::CROSS_AXIS_ALIGNMENT_START);
+ vertical_view->SetLayoutManager(vertical_layout);
+
+ // Adds the title.
+ views::Label* title_label = new views::Label(
+ l10n_util::GetStringUTF16(IDS_SYNC_ERROR_USER_MENU_TITLE));
+ title_label->SetFontList(gfx::FontList().DeriveWithSizeDelta(1));
msw 2016/07/13 22:31:38 I doubt that a 1px Font size difference matters he
Jane 2016/07/14 00:18:57 Done.
+ title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ title_label->SetEnabledColor(gfx::kGoogleRed700);
+ vertical_view->AddChildView(title_label);
+
+ // Adds body content.
+ if (!content_text.empty()) {
msw 2016/07/13 22:31:38 This text should never be empty; DCHECK instead or
Jane 2016/07/14 00:18:58 Done.
+ views::Label* content_label = new views::Label(content_text);
+ content_label->SetMultiLine(true);
+ content_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ vertical_view->AddChildView(content_label);
+ }
+
+ // Adds a padding row between error title/content and the button.
+ SizedContainer* padding = new SizedContainer(
+ gfx::Size(GetFixedMenuWidth() - 2 * kMaterialMenuEdgeMargin,
msw 2016/07/13 22:31:38 nit: I bet a 0 width would be okay here...
Jane 2016/07/14 00:18:58 Done.
+ views::kRelatedControlVerticalSpacing));
+ vertical_view->AddChildView(padding);
+
+ // Adds action_button.
msw 2016/07/13 22:31:38 nit: "an action button"; there is no |action_butto
Jane 2016/07/14 00:18:57 Done.
+ *button = views::MdTextButton::CreateSecondaryUiBlueButton(this, button_text);
+ vertical_view->AddChildView(*button);
+
+ view->AddChildView(vertical_view);
+ view->SetBorder(views::Border::CreateEmptyBorder(
+ 0, 0, views::kRelatedControlSmallVerticalSpacing, 0));
+
+ return view;
+}
+
views::View* ProfileChooserView::CreateCurrentProfileView(
const AvatarMenu::Item& avatar_item,
bool is_guest) {

Powered by Google App Engine
This is Rietveld 408576698