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

Side by Side Diff: chrome/browser/ui/views/profiles/new_avatar_button.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: Moved a comment around 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/views/profiles/new_avatar_button.h" 5 #include "chrome/browser/ui/views/profiles/new_avatar_button.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/win/windows_version.h" 9 #include "base/win/windows_version.h"
10 #include "build/build_config.h" 10 #include "build/build_config.h"
11 #include "chrome/browser/browser_process.h" 11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/profiles/profile_attributes_entry.h" 12 #include "chrome/browser/profiles/profile_attributes_entry.h"
13 #include "chrome/browser/profiles/profile_manager.h" 13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "chrome/browser/profiles/profiles_state.h" 14 #include "chrome/browser/profiles/profiles_state.h"
15 #include "chrome/browser/sync/profile_sync_service_factory.h"
15 #include "chrome/browser/ui/views/profiles/avatar_button_delegate.h" 16 #include "chrome/browser/ui/views/profiles/avatar_button_delegate.h"
16 #include "chrome/browser/ui/views/profiles/profile_chooser_view.h" 17 #include "chrome/browser/ui/views/profiles/profile_chooser_view.h"
18 #include "components/browser_sync/browser/profile_sync_service.h"
17 #include "components/signin/core/common/profile_management_switches.h" 19 #include "components/signin/core/common/profile_management_switches.h"
18 #include "grit/theme_resources.h" 20 #include "grit/theme_resources.h"
19 #include "ui/base/resource/resource_bundle.h" 21 #include "ui/base/resource/resource_bundle.h"
20 #include "ui/gfx/canvas.h" 22 #include "ui/gfx/canvas.h"
21 #include "ui/gfx/color_palette.h" 23 #include "ui/gfx/color_palette.h"
22 #include "ui/gfx/geometry/vector2d.h" 24 #include "ui/gfx/geometry/vector2d.h"
23 #include "ui/gfx/paint_vector_icon.h" 25 #include "ui/gfx/paint_vector_icon.h"
24 #include "ui/gfx/vector_icons_public.h" 26 #include "ui/gfx/vector_icons_public.h"
25 #include "ui/views/border.h" 27 #include "ui/views/border.h"
26 #include "ui/views/controls/button/label_button_border.h" 28 #include "ui/views/controls/button/label_button_border.h"
(...skipping 17 matching lines...) Expand all
44 const int kTopInset = 2; 46 const int kTopInset = 2;
45 const int kBottomInset = 4; 47 const int kBottomInset = 4;
46 border->set_insets(gfx::Insets(kTopInset, kLeftRightInset, 48 border->set_insets(gfx::Insets(kTopInset, kLeftRightInset,
47 kBottomInset, kLeftRightInset)); 49 kBottomInset, kLeftRightInset));
48 50
49 return std::move(border); 51 return std::move(border);
50 } 52 }
51 53
52 } // namespace 54 } // namespace
53 55
56 SyncErrorController* GetSyncErrorControllerIfNeeded(Profile* profile) {
57 if (!switches::IsMaterialDesignUserMenu())
58 return nullptr;
59 ProfileSyncService* sync_service =
60 ProfileSyncServiceFactory::GetForProfile(profile);
61 return sync_service ? sync_service->sync_error_controller() : nullptr;
62 }
63
64 NewAvatarButton::SigninErrorObserver::SigninErrorObserver(
65 NewAvatarButton* parent_button,
66 Profile* profile)
67 : parent_button_(parent_button), profile_(profile) {
68 // Subscribe to authentication error changes so that the avatar button can
69 // update itself. Note that guest mode profiles won't have a token service.
70 SigninErrorController* signin_error_controller =
71 profiles::GetSigninErrorController(profile_);
72 if (signin_error_controller)
73 signin_error_controller->AddObserver(this);
74 }
75
76 NewAvatarButton::SigninErrorObserver::~SigninErrorObserver() {
77 SigninErrorController* signin_error_controller =
78 profiles::GetSigninErrorController(profile_);
79 if (signin_error_controller)
80 signin_error_controller->RemoveObserver(this);
81 }
82
83 void NewAvatarButton::SigninErrorObserver::OnErrorChanged() {
84 parent_button_->OnErrorChanged();
85 }
86
87 NewAvatarButton::SyncErrorObserver::SyncErrorObserver(
88 NewAvatarButton* parent_button,
89 Profile* profile)
90 : parent_button_(parent_button), profile_(profile) {
91 SyncErrorController* sync_error_controller =
92 GetSyncErrorControllerIfNeeded(profile_);
93 if (sync_error_controller)
94 sync_error_controller->AddObserver(this);
95 }
96
97 NewAvatarButton::SyncErrorObserver::~SyncErrorObserver() {
98 SyncErrorController* sync_error_controller =
99 GetSyncErrorControllerIfNeeded(profile_);
100 if (sync_error_controller)
101 sync_error_controller->RemoveObserver(this);
102 }
103
104 void NewAvatarButton::SyncErrorObserver::OnErrorChanged() {
105 parent_button_->OnErrorChanged();
106 }
107
54 NewAvatarButton::NewAvatarButton(AvatarButtonDelegate* delegate, 108 NewAvatarButton::NewAvatarButton(AvatarButtonDelegate* delegate,
55 AvatarButtonStyle button_style, 109 AvatarButtonStyle button_style,
56 Profile* profile) 110 Profile* profile)
57 : LabelButton(delegate, base::string16()), 111 : LabelButton(delegate, base::string16()),
112 signin_error_observer_(new SigninErrorObserver(this, profile)),
113 sync_error_observer_(switches::IsMaterialDesignUserMenu()
114 ? new SyncErrorObserver(this, profile)
115 : nullptr),
58 delegate_(delegate), 116 delegate_(delegate),
59 profile_(profile), 117 profile_(profile),
60 has_auth_error_(false), 118 has_error_(false),
61 suppress_mouse_released_action_(false) { 119 suppress_mouse_released_action_(false) {
62 set_triggerable_event_flags( 120 set_triggerable_event_flags(
63 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON); 121 ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON);
64 set_animate_on_state_change(false); 122 set_animate_on_state_change(false);
65 SetEnabledTextColors(SK_ColorWHITE); 123 SetEnabledTextColors(SK_ColorWHITE);
66 SetTextSubpixelRenderingEnabled(false); 124 SetTextSubpixelRenderingEnabled(false);
67 SetHorizontalAlignment(gfx::ALIGN_CENTER); 125 SetHorizontalAlignment(gfx::ALIGN_CENTER);
68 126
69 // The largest text height that fits in the button. If the font list height 127 // The largest text height that fits in the button. If the font list height
70 // is larger than this, it will be shrunk to match it. 128 // is larger than this, it will be shrunk to match it.
(...skipping 26 matching lines...) Expand all
97 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_PRESSED); 155 const int kPushedImageSet[] = IMAGE_GRID(IDR_AVATAR_NATIVE_BUTTON_PRESSED);
98 156
99 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet)); 157 SetBorder(CreateBorder(kNormalImageSet, kHotImageSet, kPushedImageSet));
100 generic_avatar_ = 158 generic_avatar_ =
101 *rb->GetImageNamed(IDR_AVATAR_NATIVE_BUTTON_AVATAR).ToImageSkia(); 159 *rb->GetImageNamed(IDR_AVATAR_NATIVE_BUTTON_AVATAR).ToImageSkia();
102 } 160 }
103 161
104 g_browser_process->profile_manager()-> 162 g_browser_process->profile_manager()->
105 GetProfileAttributesStorage().AddObserver(this); 163 GetProfileAttributesStorage().AddObserver(this);
106 164
107 // Subscribe to authentication error changes so that the avatar button can 165 SigninErrorController* signin_error_controller =
108 // update itself. Note that guest mode profiles won't have a token service. 166 profiles::GetSigninErrorController(profile_);
109 SigninErrorController* error = profiles::GetSigninErrorController(profile_); 167 SyncErrorController* sync_error_controller =
110 if (error) { 168 GetSyncErrorControllerIfNeeded(profile_);
111 error->AddObserver(this); 169 if (signin_error_controller || sync_error_controller) {
112 OnErrorChanged(); // This calls Update(). 170 OnErrorChanged(); // This calls Update()
msw 2016/07/14 17:47:52 nit: Just always call OnErrorChanged here and remo
Jane 2016/07/14 17:59:44 Done.
113 } else { 171 } else {
114 Update(); 172 Update();
115 } 173 }
116 SchedulePaint(); 174 SchedulePaint();
117 } 175 }
118 176
119 NewAvatarButton::~NewAvatarButton() { 177 NewAvatarButton::~NewAvatarButton() {
120 g_browser_process->profile_manager()-> 178 g_browser_process->profile_manager()->
121 GetProfileAttributesStorage().RemoveObserver(this); 179 GetProfileAttributesStorage().RemoveObserver(this);
122 SigninErrorController* error =
123 profiles::GetSigninErrorController(profile_);
124 if (error)
125 error->RemoveObserver(this);
126 } 180 }
127 181
128 bool NewAvatarButton::OnMousePressed(const ui::MouseEvent& event) { 182 bool NewAvatarButton::OnMousePressed(const ui::MouseEvent& event) {
129 // Prevent the bubble from being re-shown if it's already showing. 183 // Prevent the bubble from being re-shown if it's already showing.
130 suppress_mouse_released_action_ = ProfileChooserView::IsShowing(); 184 suppress_mouse_released_action_ = ProfileChooserView::IsShowing();
131 return LabelButton::OnMousePressed(event); 185 return LabelButton::OnMousePressed(event);
132 } 186 }
133 187
134 void NewAvatarButton::OnMouseReleased(const ui::MouseEvent& event) { 188 void NewAvatarButton::OnMouseReleased(const ui::MouseEvent& event) {
135 if (suppress_mouse_released_action_) 189 if (suppress_mouse_released_action_)
136 suppress_mouse_released_action_ = false; 190 suppress_mouse_released_action_ = false;
137 else 191 else
138 LabelButton::OnMouseReleased(event); 192 LabelButton::OnMouseReleased(event);
139 } 193 }
140 194
141 void NewAvatarButton::OnGestureEvent(ui::GestureEvent* event) { 195 void NewAvatarButton::OnGestureEvent(ui::GestureEvent* event) {
142 // TODO(wjmaclean): The check for ET_GESTURE_LONG_PRESS is done here since 196 // TODO(wjmaclean): The check for ET_GESTURE_LONG_PRESS is done here since
143 // no other UI button based on CustomButton appears to handle mouse 197 // no other UI button based on CustomButton appears to handle mouse
144 // right-click. If other cases are identified, it may make sense to move this 198 // right-click. If other cases are identified, it may make sense to move this
145 // check to CustomButton. 199 // check to CustomButton.
146 if (event->type() == ui::ET_GESTURE_LONG_PRESS) 200 if (event->type() == ui::ET_GESTURE_LONG_PRESS)
147 NotifyClick(*event); 201 NotifyClick(*event);
148 else 202 else
149 LabelButton::OnGestureEvent(event); 203 LabelButton::OnGestureEvent(event);
150 } 204 }
151 205
206 void NewAvatarButton::OnErrorChanged() {
207 // If there is a signin error, show a warning icon.
208 const SigninErrorController* signin_error_controller =
209 profiles::GetSigninErrorController(profile_);
210 has_error_ = signin_error_controller && signin_error_controller->HasError();
211
212 // Also show a warning icon for sync errors for the material design user menu.
213 ProfileSyncService* sync_service =
214 ProfileSyncServiceFactory::GetForProfile(profile_);
215 if (switches::IsMaterialDesignUserMenu() && sync_service) {
216 SyncErrorController* sync_error_controller =
217 sync_service->sync_error_controller();
218 ProfileSyncService::Status status;
219 sync_service->QueryDetailedSyncStatus(&status);
220 has_error_ |=
221 (sync_service->HasUnrecoverableError() ||
222 status.sync_protocol_error.action == syncer::UPGRADE_CLIENT ||
223 (sync_error_controller && sync_error_controller->HasError()));
224 }
225
226 Update();
227 }
228
152 void NewAvatarButton::OnProfileAdded(const base::FilePath& profile_path) { 229 void NewAvatarButton::OnProfileAdded(const base::FilePath& profile_path) {
153 Update(); 230 Update();
154 } 231 }
155 232
156 void NewAvatarButton::OnProfileWasRemoved( 233 void NewAvatarButton::OnProfileWasRemoved(
157 const base::FilePath& profile_path, 234 const base::FilePath& profile_path,
158 const base::string16& profile_name) { 235 const base::string16& profile_name) {
159 // If deleting the active profile, don't bother updating the avatar 236 // If deleting the active profile, don't bother updating the avatar
160 // button, as the browser window is being closed anyway. 237 // button, as the browser window is being closed anyway.
161 if (profile_->GetPath() != profile_path) 238 if (profile_->GetPath() != profile_path)
162 Update(); 239 Update();
163 } 240 }
164 241
165 void NewAvatarButton::OnProfileNameChanged( 242 void NewAvatarButton::OnProfileNameChanged(
166 const base::FilePath& profile_path, 243 const base::FilePath& profile_path,
167 const base::string16& old_profile_name) { 244 const base::string16& old_profile_name) {
168 if (profile_->GetPath() == profile_path) 245 if (profile_->GetPath() == profile_path)
169 Update(); 246 Update();
170 } 247 }
171 248
172 void NewAvatarButton::OnProfileSupervisedUserIdChanged( 249 void NewAvatarButton::OnProfileSupervisedUserIdChanged(
173 const base::FilePath& profile_path) { 250 const base::FilePath& profile_path) {
174 if (profile_->GetPath() == profile_path) 251 if (profile_->GetPath() == profile_path)
175 Update(); 252 Update();
176 } 253 }
177 254
178 void NewAvatarButton::OnErrorChanged() {
179 // If there is an error, show an warning icon.
180 const SigninErrorController* error =
181 profiles::GetSigninErrorController(profile_);
182 has_auth_error_ = error && error->HasError();
183
184 Update();
185 }
186
187 void NewAvatarButton::Update() { 255 void NewAvatarButton::Update() {
188 ProfileAttributesStorage& storage = 256 ProfileAttributesStorage& storage =
189 g_browser_process->profile_manager()->GetProfileAttributesStorage(); 257 g_browser_process->profile_manager()->GetProfileAttributesStorage();
190 258
191 // If we have a single local profile, then use the generic avatar 259 // If we have a single local profile, then use the generic avatar
192 // button instead of the profile name. Never use the generic button if 260 // button instead of the profile name. Never use the generic button if
193 // the active profile is Guest. 261 // the active profile is Guest.
194 const bool use_generic_button = 262 const bool use_generic_button =
195 !profile_->IsGuestSession() && 263 !profile_->IsGuestSession() &&
196 storage.GetNumberOfProfiles() == 1 && 264 storage.GetNumberOfProfiles() == 1 &&
197 !storage.GetAllProfilesAttributes().front()->IsAuthenticated(); 265 !storage.GetAllProfilesAttributes().front()->IsAuthenticated();
198 266
199 SetText(use_generic_button 267 SetText(use_generic_button
200 ? base::string16() 268 ? base::string16()
201 : profiles::GetAvatarButtonTextForProfile(profile_)); 269 : profiles::GetAvatarButtonTextForProfile(profile_));
202 270
203 // If the button has no text, clear the text shadows to make sure the 271 // If the button has no text, clear the text shadows to make sure the
204 // image is centered correctly. 272 // image is centered correctly.
205 SetTextShadows( 273 SetTextShadows(
206 use_generic_button 274 use_generic_button
207 ? gfx::ShadowValues() 275 ? gfx::ShadowValues()
208 : gfx::ShadowValues( 276 : gfx::ShadowValues(
209 10, gfx::ShadowValue(gfx::Vector2d(), 1.0f, SK_ColorDKGRAY))); 277 10, gfx::ShadowValue(gfx::Vector2d(), 1.0f, SK_ColorDKGRAY)));
210 278
211 // We want the button to resize if the new text is shorter. 279 // We want the button to resize if the new text is shorter.
212 SetMinSize(gfx::Size()); 280 SetMinSize(gfx::Size());
213 281
214 if (use_generic_button) { 282 if (use_generic_button) {
215 SetImage(views::Button::STATE_NORMAL, generic_avatar_); 283 SetImage(views::Button::STATE_NORMAL, generic_avatar_);
216 } else if (has_auth_error_) { 284 } else if (has_error_) {
217 if (switches::IsMaterialDesignUserMenu()) { 285 if (switches::IsMaterialDesignUserMenu()) {
218 SetImage(views::Button::STATE_NORMAL, 286 SetImage(views::Button::STATE_NORMAL,
219 gfx::CreateVectorIcon(gfx::VectorIconId::SYNC_PROBLEM, 13, 287 gfx::CreateVectorIcon(gfx::VectorIconId::SYNC_PROBLEM, 13,
220 gfx::kGoogleRed700)); 288 gfx::kGoogleRed700));
221 } else { 289 } else {
222 SetImage(views::Button::STATE_NORMAL, 290 SetImage(views::Button::STATE_NORMAL,
223 gfx::CreateVectorIcon(gfx::VectorIconId::WARNING, 13, 291 gfx::CreateVectorIcon(gfx::VectorIconId::WARNING, 13,
224 gfx::kGoogleYellow700)); 292 gfx::kGoogleYellow700));
225 } 293 }
226 } else { 294 } else {
227 SetImage(views::Button::STATE_NORMAL, gfx::ImageSkia()); 295 SetImage(views::Button::STATE_NORMAL, gfx::ImageSkia());
228 } 296 }
229 297
230 // If we are not using the generic button, then reset the spacing between 298 // If we are not using the generic button, then reset the spacing between
231 // the text and the possible authentication error icon. 299 // the text and the possible authentication error icon.
232 const int kDefaultImageTextSpacing = 5; 300 const int kDefaultImageTextSpacing = 5;
233 SetImageLabelSpacing(use_generic_button ? 0 : kDefaultImageTextSpacing); 301 SetImageLabelSpacing(use_generic_button ? 0 : kDefaultImageTextSpacing);
234 302
235 PreferredSizeChanged(); 303 PreferredSizeChanged();
236 delegate_->ButtonPreferredSizeChanged(); 304 delegate_->ButtonPreferredSizeChanged();
237 } 305 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698