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

Side by Side Diff: chrome/browser/ui/views/passwords/credentials_item_view.cc

Issue 854173003: Credential Management API: the account chooser dialog supports custom avatars. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: resize avatar manually so it looks cool! Created 5 years, 11 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/passwords/credentials_item_view.h" 5 #include "chrome/browser/ui/views/passwords/credentials_item_view.h"
6 6
7 #include "chrome/browser/browser_process.h" 7 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
8 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
9 #include "chrome/browser/profiles/profile_info_cache.h"
10 #include "chrome/browser/profiles/profile_manager.h"
11 #include "grit/theme_resources.h" 8 #include "grit/theme_resources.h"
9 #include "net/base/load_flags.h"
12 #include "ui/base/resource/resource_bundle.h" 10 #include "ui/base/resource/resource_bundle.h"
13 #include "ui/gfx/canvas.h" 11 #include "ui/gfx/canvas.h"
14 #include "ui/gfx/image/image.h" 12 #include "ui/gfx/image/image.h"
13 #include "ui/gfx/image/image_skia_operations.h"
15 #include "ui/gfx/path.h" 14 #include "ui/gfx/path.h"
16 #include "ui/views/border.h" 15 #include "ui/views/border.h"
17 #include "ui/views/controls/image_view.h" 16 #include "ui/views/controls/image_view.h"
18 #include "ui/views/controls/label.h" 17 #include "ui/views/controls/label.h"
19 18
20 namespace { 19 namespace {
21 const int kIconSize = 50; 20 const int kIconSize = 50;
22 // The default spacing between the icon and text. 21 // The default spacing between the icon and text.
23 const int kSpacing = 5; 22 const int kSpacing = 5;
24 23
25 gfx::Size GetTextLabelsSize(const views::Label* full_name_label, 24 gfx::Size GetTextLabelsSize(const views::Label* full_name_label,
26 const views::Label* username_label) { 25 const views::Label* username_label) {
27 gfx::Size full_name = full_name_label->GetPreferredSize(); 26 gfx::Size full_name = full_name_label->GetPreferredSize();
28 gfx::Size username = username_label ? username_label->GetPreferredSize() : 27 gfx::Size username = username_label ? username_label->GetPreferredSize() :
29 gfx::Size(); 28 gfx::Size();
30 return gfx::Size(std::max(full_name.width(), username.width()), 29 return gfx::Size(std::max(full_name.width(), username.width()),
31 full_name.height() + username.height()); 30 full_name.height() + username.height());
32 } 31 }
33 32
33 // Crops and scales |image| to kIconSize
34 gfx::ImageSkia ScaleImage(gfx::Image image) {
35 gfx::ImageSkia skia_image = image.AsImageSkia();
Mike West 2015/01/21 16:51:52 Can we shortcut this by checking whether the image
vasilii 2015/01/21 19:41:23 I've rewritten the code so we use more gfx::ImageS
36 gfx::Size size = image.Size();
37 if (size.height() != size.width()) {
38 gfx::Rect target(size);
39 int side = std::min(size.height(), size.width());
40 target.ClampToCenteredSize(gfx::Size(side, side));
41 skia_image = gfx::ImageSkiaOperations::ExtractSubset(skia_image, target);
42 }
43 return gfx::ImageSkiaOperations::CreateResizedImage(
44 skia_image,
45 skia::ImageOperations::RESIZE_BEST,
46 gfx::Size(kIconSize, kIconSize));
47 }
48
34 class CircularImageView : public views::ImageView { 49 class CircularImageView : public views::ImageView {
35 public: 50 public:
36 CircularImageView() = default; 51 CircularImageView() = default;
37 52
38 private: 53 private:
39 // views::ImageView: 54 // views::ImageView:
40 void OnPaint(gfx::Canvas* canvas) override; 55 void OnPaint(gfx::Canvas* canvas) override;
41 56
42 DISALLOW_COPY_AND_ASSIGN(CircularImageView); 57 DISALLOW_COPY_AND_ASSIGN(CircularImageView);
43 }; 58 };
44 59
45 void CircularImageView::OnPaint(gfx::Canvas* canvas) { 60 void CircularImageView::OnPaint(gfx::Canvas* canvas) {
46 // Display the avatar picture as a circle. 61 // Display the avatar picture as a circle.
47 gfx::Rect bounds(GetImageBounds()); 62 gfx::Rect bounds(GetImageBounds());
48 gfx::Path circular_mask; 63 gfx::Path circular_mask;
49 circular_mask.addCircle( 64 circular_mask.addCircle(
50 SkIntToScalar(bounds.x() + bounds.right()) / 2, 65 SkIntToScalar(bounds.x() + bounds.right()) / 2,
51 SkIntToScalar(bounds.y() + bounds.bottom()) / 2, 66 SkIntToScalar(bounds.y() + bounds.bottom()) / 2,
52 SkIntToScalar(std::min(bounds.height(), bounds.width())) / 2); 67 SkIntToScalar(std::min(bounds.height(), bounds.width())) / 2);
53 canvas->ClipPath(circular_mask, true); 68 canvas->ClipPath(circular_mask, true);
54 ImageView::OnPaint(canvas); 69 ImageView::OnPaint(canvas);
55 } 70 }
56 71
57 } // namespace 72 } // namespace
58 73
59 CredentialsItemView::CredentialsItemView(views::ButtonListener* button_listener, 74 // Helper class to download the avatar. It deletes itself once the request is
60 const autofill::PasswordForm& form) 75 // done.
76 class CredentialsItemView::AvatarFetcher
77 : public chrome::BitmapFetcherDelegate {
78 public:
79 AvatarFetcher(const GURL& url,
80 const base::WeakPtr<CredentialsItemView>& delegate);
81
82 void Start(net::URLRequestContextGetter* request_context);
83
84 private:
85 ~AvatarFetcher() override;
86
87 // chrome::BitmapFetcherDelegate:
88 void OnFetchComplete(const GURL url, const SkBitmap* bitmap) override;
89
90 chrome::BitmapFetcher fetcher_;
91 base::WeakPtr<CredentialsItemView> delegate_;
92
93 DISALLOW_COPY_AND_ASSIGN(AvatarFetcher);
94 };
95
96 CredentialsItemView::AvatarFetcher::AvatarFetcher(
97 const GURL& url,
98 const base::WeakPtr<CredentialsItemView>& delegate)
99 : fetcher_(url, this),
100 delegate_(delegate) {
101 }
102
103 CredentialsItemView::AvatarFetcher::~AvatarFetcher() = default;
104
105 void CredentialsItemView::AvatarFetcher::Start(
106 net::URLRequestContextGetter* request_context) {
107 fetcher_.Start(request_context, std::string(),
108 net::URLRequest::NEVER_CLEAR_REFERRER,
109 net::LOAD_DO_NOT_SEND_COOKIES |
110 net::LOAD_DO_NOT_SAVE_COOKIES |
111 net::LOAD_MAYBE_USER_GESTURE);
112 }
113
114 void CredentialsItemView::AvatarFetcher::OnFetchComplete(
115 const GURL /*url*/, const SkBitmap* bitmap) {
116 if (bitmap && delegate_)
117 delegate_->UpdateAvatar(gfx::Image::CreateFrom1xBitmap(*bitmap));
118
119 delete this;
120 }
121
122 CredentialsItemView::CredentialsItemView(
123 views::ButtonListener* button_listener,
124 const autofill::PasswordForm& form,
125 net::URLRequestContextGetter* request_context)
61 : LabelButton(button_listener, base::string16()), 126 : LabelButton(button_listener, base::string16()),
62 form_(form) { 127 form_(form),
128 weak_ptr_factory_(this) {
63 set_notify_enter_exit_on_child(true); 129 set_notify_enter_exit_on_child(true);
64 // Create an image-view for the avatar. Make sure it ignores events so that 130 // Create an image-view for the avatar. Make sure it ignores events so that
65 // the parent can receive the events instead. 131 // the parent can receive the events instead.
66 image_view_ = new CircularImageView; 132 image_view_ = new CircularImageView;
67 image_view_->set_interactive(false); 133 image_view_->set_interactive(false);
68 134 gfx::Image image =
69 // TODO(vasilii): temporary code below shows the built-in profile icon instead 135 ResourceBundle::GetSharedInstance().GetImageNamed(IDR_PROFILE_AVATAR_26);
70 // of avatar. 136 image_view_->SetImageSize(gfx::Size(kIconSize, kIconSize));
71 const ProfileInfoCache& cache = 137 image_view_->SetImage(image.ToImageSkia());
72 g_browser_process->profile_manager()->GetProfileInfoCache(); 138 if (form_.avatar_url.is_valid()) {
73 const gfx::Image& image = cache.GetAvatarIconOfProfileAtIndex(0); 139 // Fetch the actual avatar.
74 image_view_->SetImage(profiles::GetSizedAvatarIcon( 140 AvatarFetcher* fetcher = new AvatarFetcher(form_.avatar_url,
75 image, true, kIconSize, kIconSize).ToImageSkia()); 141 weak_ptr_factory_.GetWeakPtr());
142 fetcher->Start(request_context);
143 }
76 AddChildView(image_view_); 144 AddChildView(image_view_);
77 145
78 // Add a label to show the full name. 146 // Add a label to show the full name.
79 // TODO(vasilii): temporarily the label shows username. 147 // TODO(vasilii): temporarily the label shows username.
80 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); 148 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
81 full_name_label_ = new views::Label( 149 full_name_label_ = new views::Label(
82 form_.username_value, rb->GetFontList(ui::ResourceBundle::BoldFont)); 150 form_.username_value, rb->GetFontList(ui::ResourceBundle::BoldFont));
83 full_name_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 151 full_name_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
84 AddChildView(full_name_label_); 152 AddChildView(full_name_label_);
85 153
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 int y_offset = (child_area.height() - 196 int y_offset = (child_area.height() -
129 (full_name_size.height() + username_size.height())) / 2; 197 (full_name_size.height() + username_size.height())) / 2;
130 gfx::Point label_origin(image_origin.x() + image_size.width() + kSpacing, 198 gfx::Point label_origin(image_origin.x() + image_size.width() + kSpacing,
131 child_area.origin().y() + y_offset); 199 child_area.origin().y() + y_offset);
132 full_name_label_->SetBoundsRect(gfx::Rect(label_origin, full_name_size)); 200 full_name_label_->SetBoundsRect(gfx::Rect(label_origin, full_name_size));
133 if (username_label_) { 201 if (username_label_) {
134 label_origin.Offset(0, full_name_size.height()); 202 label_origin.Offset(0, full_name_size.height());
135 username_label_->SetBoundsRect(gfx::Rect(label_origin, username_size)); 203 username_label_->SetBoundsRect(gfx::Rect(label_origin, username_size));
136 } 204 }
137 } 205 }
206
207 void CredentialsItemView::UpdateAvatar(const gfx::Image& image) {
208 image_view_->SetImage(ScaleImage(image));
209 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698