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

Side by Side Diff: chrome/browser/ui/views/toolbar/site_chip_view.cc

Issue 92073003: [SiteChip] Draw site chip icon and site title. Drag support. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: l10n str for ev ssl, 2 16x16 icons, etc. Created 7 years 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/toolbar/site_chip_view.h" 5 #include "chrome/browser/ui/views/toolbar/site_chip_view.h"
6 6
7 #include "base/files/file_path.h"
7 #include "base/prefs/pref_service.h" 8 #include "base/prefs/pref_service.h"
8 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/extensions/extension_icon_image.h"
13 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/extensions/extension_system.h"
15 #include "chrome/browser/favicon/favicon_tab_helper.h"
10 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/search/search.h" 17 #include "chrome/browser/search/search.h"
12 #include "chrome/browser/themes/theme_properties.h" 18 #include "chrome/browser/themes/theme_properties.h"
13 #include "chrome/browser/ui/browser.h" 19 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/omnibox/omnibox_view.h" 20 #include "chrome/browser/ui/omnibox/omnibox_view.h"
15 #include "chrome/browser/ui/toolbar/toolbar_model.h" 21 #include "chrome/browser/ui/toolbar/toolbar_model.h"
16 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" 22 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
17 #include "chrome/browser/ui/views/toolbar/toolbar_view.h" 23 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
24 #include "chrome/common/extensions/extension_constants.h"
25 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
18 #include "chrome/common/pref_names.h" 26 #include "chrome/common/pref_names.h"
19 #include "content/public/browser/web_contents.h" 27 #include "content/public/browser/web_contents.h"
28 #include "extensions/common/constants.h"
20 #include "grit/theme_resources.h" 29 #include "grit/theme_resources.h"
21 #include "net/base/net_util.h" 30 #include "net/base/net_util.h"
31 #include "ui/base/l10n/l10n_util.h"
22 #include "ui/base/resource/resource_bundle.h" 32 #include "ui/base/resource/resource_bundle.h"
23 #include "ui/base/theme_provider.h" 33 #include "ui/base/theme_provider.h"
24 #include "ui/views/background.h" 34 #include "ui/views/background.h"
35 #include "ui/views/button_drag_utils.h"
25 #include "ui/views/controls/button/label_button.h" 36 #include "ui/views/controls/button/label_button.h"
26 #include "ui/views/controls/button/label_button_border.h" 37 #include "ui/views/controls/button/label_button_border.h"
27 #include "ui/views/controls/label.h" 38 #include "ui/views/controls/label.h"
28 #include "ui/views/painter.h" 39 #include "ui/views/painter.h"
29 40
30 const int kEdgeThickness = 4; 41
31 const int kIconTextSpacing = 4; 42 // SiteChipExtensionIcon ------------------------------------------------------
32 const int kTrailingLabelMargin = 2; 43
44 class SiteChipExtensionIcon : public extensions::IconImage::Observer {
45 public:
46 SiteChipExtensionIcon(LocationIconView* icon_view,
47 Profile* profile,
48 const extensions::Extension* extension);
49 ~SiteChipExtensionIcon();
50
51 // IconImage::Observer:
52 virtual void OnExtensionIconImageChanged(
53 extensions::IconImage* image) OVERRIDE;
54
55 private:
56 LocationIconView* icon_view_;
57 scoped_ptr<extensions::IconImage> icon_image_;
58
59 DISALLOW_COPY_AND_ASSIGN(SiteChipExtensionIcon);
60 };
61
62 SiteChipExtensionIcon::SiteChipExtensionIcon(
63 LocationIconView* icon_view,
64 Profile* profile,
65 const extensions::Extension* extension)
66 : icon_view_(icon_view),
67 icon_image_(new extensions::IconImage(
68 profile,
69 extension,
70 extensions::IconsInfo::GetIcons(extension),
71 extension_misc::EXTENSION_ICON_BITTY,
72 extensions::IconsInfo::GetDefaultAppIcon(),
73 this)) {
74 // Forces load of the image.
75 icon_image_->image_skia().GetRepresentation(1.0f);
76
77 if (!icon_image_->image_skia().image_reps().empty())
78 OnExtensionIconImageChanged(icon_image_.get());
79 }
80
81 SiteChipExtensionIcon::~SiteChipExtensionIcon() {
82 }
83
84 void SiteChipExtensionIcon::OnExtensionIconImageChanged(
85 extensions::IconImage* image) {
86 if (icon_view_)
87 icon_view_->SetImage(&icon_image_->image_skia());
88 }
89
90
91 // SiteChipView ---------------------------------------------------------------
92
93 namespace {
94
95 const int kEdgeThickness = 5;
96 const int k16x16IconExtraSpacing = 3;
97 const int k16x16IconLeadingSpacing = 3;
98 const int k16x16IconTrailingSpacing = 3;
99 const int kIconTextSpacing = 3;
100 const int kTrailingLabelMargin = 0;
101
102 } // namespace
103
104 string16 SiteChipView::SiteLabelFromURL(const GURL& url) {
105 // The NTP.
106 if (!url.is_valid())
107 return string16(UTF8ToUTF16("Chrome"));
108
109 // TODO(gbillock): for kChromeUIScheme and kAboutScheme, return the title of
110 // the page.
111 // See url_constants.cc for hosts. ?? Or just show "Chrome"?
112 if (url.SchemeIs(chrome::kChromeUIScheme) ||
113 url.SchemeIs(chrome::kAboutScheme)) {
114 return string16(UTF8ToUTF16("Chrome"));
115 }
116
117 // For file: urls, return the BaseName of the file.
118 if (url.SchemeIsFile()) {
119 base::FilePath path = base::FilePath::FromUTF8Unsafe(url.path());
120 // TODO(gbillock): Need nuance here.
121 return string16(base::UTF8ToUTF16(path.BaseName().value()));
122 }
123
124 // TODO(gbillock): Handle filesystem urls the same way?
125 // Also: should handle interstitials differently?
126
127 // TODO(gbillock): think about view-source?
128
129 Profile* profile = toolbar_view_->browser()->profile();
130
131 // For chrome-extension urls, return the extension name.
132 if (url.SchemeIs(extensions::kExtensionScheme)) {
133 ExtensionService* service =
134 extensions::ExtensionSystem::Get(profile)->extension_service();
135 const extensions::Extension* extension =
136 service->extensions()->GetExtensionOrAppByURL(url);
137 return extension ?
138 base::UTF8ToUTF16(extension->name()) : UTF8ToUTF16(url.host());
139 }
140
141 if (url.SchemeIsHTTPOrHTTPS()) {
142 // See ToolbarModelImpl::GetText(). Does not pay attention to any user
143 // edits, and uses GetURL/net::FormatUrl -- We don't really care about
144 // length or the autocomplete parser.
145 std::string languages;
146 if (profile)
147 languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages);
148
149 base::string16 formatted = net::FormatUrl(url.GetOrigin(), languages,
150 net::kFormatUrlOmitAll, net::UnescapeRule::NORMAL, NULL, NULL, NULL);
151 // Remove scheme, "www.", and trailing "/".
152 if (StartsWith(formatted, ASCIIToUTF16("http://"), false))
153 formatted = formatted.substr(7);
154 if (StartsWith(formatted, ASCIIToUTF16("https://"), false))
155 formatted = formatted.substr(8);
156 if (StartsWith(formatted, ASCIIToUTF16("www."), false))
157 formatted = formatted.substr(4);
158 if (EndsWith(formatted, ASCIIToUTF16("/"), false))
159 formatted = formatted.substr(0, formatted.size()-1);
160 return formatted;
161 }
162
163 // For FTP, prepend "ftp:" to hostname.
164 if (url.SchemeIs(content::kFtpScheme)) {
165 return string16(UTF8ToUTF16(std::string("ftp:") + url.host()));
166 }
167
168 // If all else fails, return hostname.
169 return string16(UTF8ToUTF16(url.host()));
170 }
33 171
34 SiteChipView::SiteChipView(ToolbarView* toolbar_view) 172 SiteChipView::SiteChipView(ToolbarView* toolbar_view)
35 : ToolbarButton(this, NULL), 173 : ToolbarButton(this, NULL),
36 toolbar_view_(toolbar_view) { 174 toolbar_view_(toolbar_view),
175 painter_(NULL),
176 showing_16x16_icon_(false) {
177 set_drag_controller(this);
37 } 178 }
38 179
39 SiteChipView::~SiteChipView() { 180 SiteChipView::~SiteChipView() {
40 } 181 }
41 182
42 void SiteChipView::Init() { 183 void SiteChipView::Init() {
43 ToolbarButton::Init(); 184 ToolbarButton::Init();
44 185
45 // TODO(gbillock): Would be nice to just use stock LabelButton stuff here. 186 // TODO(gbillock): Would be nice to just use stock LabelButton stuff here.
46 location_icon_view_ = new LocationIconView(toolbar_view_->location_bar()); 187 location_icon_view_ = new LocationIconView(toolbar_view_->location_bar());
47 host_label_ = new views::Label(); 188 host_label_ = new views::Label();
48 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 189 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
49 host_label_->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont)); 190 host_label_->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont));
50 191
51 AddChildView(location_icon_view_); 192 AddChildView(location_icon_view_);
52 AddChildView(host_label_); 193 AddChildView(host_label_);
53 194
54 // temporary background painter
55 const int kBackgroundImages[] = IMAGE_GRID(IDR_SITE_CHIP_EV);
56 background_painter_.reset(
57 views::Painter::CreateImageGridPainter(kBackgroundImages));
58
59 // temporary icon filler
60 location_icon_view_->SetImage(GetThemeProvider()->GetImageSkiaNamed( 195 location_icon_view_->SetImage(GetThemeProvider()->GetImageSkiaNamed(
61 IDR_OMNIBOX_HTTPS_VALID)); 196 IDR_LOCATION_BAR_HTTP));
62 location_icon_view_->ShowTooltip(true); 197 location_icon_view_->ShowTooltip(true);
63 198
64 // temporary filler text. 199 const int kEVBackgroundImages[] = IMAGE_GRID(IDR_SITE_CHIP_EV);
65 host_label_->SetText(ASCIIToUTF16("site.chip")); 200 ev_background_painter_.reset(
201 views::Painter::CreateImageGridPainter(kEVBackgroundImages));
202 const int kBrokenSSLBackgroundImages[] = IMAGE_GRID(IDR_SITE_CHIP_BROKENSSL);
203 broken_ssl_background_painter_.reset(
204 views::Painter::CreateImageGridPainter(kBrokenSSLBackgroundImages));
66 } 205 }
67 206
68 bool SiteChipView::ShouldShow() { 207 bool SiteChipView::ShouldShow() {
69 return chrome::ShouldDisplayOriginChip(); 208 return chrome::ShouldDisplayOriginChip();
70 } 209 }
71 210
72 void SiteChipView::Update(content::WebContents* tab) { 211 void SiteChipView::Update(content::WebContents* web_contents) {
212 if (!web_contents)
213 return;
214
215 // Note: security level can change async as the connection is made.
216 GURL url = toolbar_view_->GetToolbarModel()->GetURL();
217 const ToolbarModel::SecurityLevel security_level =
218 toolbar_view_->GetToolbarModel()->GetSecurityLevel(true);
219 if ((url == url_displayed_) && (security_level == security_level_))
220 return;
221
222 url_displayed_ = url;
223
224 string16 host = SiteLabelFromURL(url);
225
226 // TODO(gbillock): Deal with RTL here better? Use a separate
227 // label for cert name?
228 if ((security_level != security_level_) &&
229 (security_level == ToolbarModel::EV_SECURE)) {
230 host = l10n_util::GetStringUTF16(IDS_SITE_CHIP_EV_SSL_LABEL,
231 toolbar_view_->GetToolbarModel()->GetEVCertName(), host);
232 }
233
234 host_ = host;
235 host_label_->SetText(host_);
236 host_label_->SetTooltipText(host_);
237 SkColor toolbar_background =
238 GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR);
239 host_label_->SetEnabledColor(
240 color_utils::GetReadableColor(SK_ColorBLACK, toolbar_background));
241
242 security_level_ = security_level;
243 int icon = toolbar_view_->GetToolbarModel()->GetIconForSecurityLevel(
244 security_level_);
245 showing_16x16_icon_ = false;
246
247 if (!url.is_valid() ||
248 url.SchemeIs(chrome::kChromeUIScheme)) {
249 icon = IDR_PRODUCT_LOGO_16;
250 showing_16x16_icon_ = true;
251 }
252
253 if (url.SchemeIs(extensions::kExtensionScheme)) {
254 icon = IDR_EXTENSIONS_FAVICON;
255 showing_16x16_icon_ = true;
256
257 ExtensionService* service =
258 extensions::ExtensionSystem::Get(
259 toolbar_view_->browser()->profile())->extension_service();
260 const extensions::Extension* extension =
261 service->extensions()->GetExtensionOrAppByURL(url);
262 extension_icon_.reset(
263 new SiteChipExtensionIcon(location_icon_view_,
264 toolbar_view_->browser()->profile(),
265 extension));
266 } else {
267 extension_icon_.reset();
268 }
269
270 location_icon_view_->SetImage(GetThemeProvider()->GetImageSkiaNamed(icon));
271 location_icon_view_->ShowTooltip(true);
272
273 // TODO(gbillock): Add malware accounting.
274 if (security_level_ == ToolbarModel::SECURITY_ERROR)
275 painter_ = broken_ssl_background_painter_.get();
276 else if (security_level_ == ToolbarModel::EV_SECURE)
277 painter_ = ev_background_painter_.get();
278 else
279 painter_ = NULL;
280
73 Layout(); 281 Layout();
74 SchedulePaint(); 282 SchedulePaint();
283 // TODO(gbillock): Need to schedule paint on parent to erase any background?
284 }
285
286 void SiteChipView::OnChanged() {
287 Update(toolbar_view_->GetWebContents());
288 toolbar_view_->Layout();
289 toolbar_view_->SchedulePaint();
290 // TODO(gbillock): Also need to potentially repaint infobars to make sure the
291 // arrows are pointing to the right spot. Only needed for some edge cases.
75 } 292 }
76 293
77 gfx::Size SiteChipView::GetPreferredSize() { 294 gfx::Size SiteChipView::GetPreferredSize() {
78 gfx::Size label_size = host_label_->GetPreferredSize(); 295 gfx::Size label_size = host_label_->GetPreferredSize();
79 gfx::Size icon_size = location_icon_view_->GetPreferredSize(); 296 gfx::Size icon_size = location_icon_view_->GetPreferredSize();
297 int icon_spacing = showing_16x16_icon_ ?
298 (2 * (k16x16IconLeadingSpacing + k16x16IconTrailingSpacing)) : 0;
Peter Kasting 2013/12/10 19:44:31 The "2 *" here is wrong.
Greg Billock 2013/12/10 20:36:23 Done.
80 return gfx::Size(icon_size.width() + label_size.width() + 299 return gfx::Size(icon_size.width() + label_size.width() +
81 kIconTextSpacing + kTrailingLabelMargin + 300 kIconTextSpacing + kTrailingLabelMargin +
82 2 * kEdgeThickness, 301 2 * kEdgeThickness +
302 icon_spacing,
83 icon_size.height()); 303 icon_size.height());
Peter Kasting 2013/12/10 19:44:31 Nit: How about wrapping/indenting like: return
Greg Billock 2013/12/10 20:36:23 I like it.
84 } 304 }
85 305
86 void SiteChipView::Layout() { 306 void SiteChipView::Layout() {
307 // TODO(gbillock): Eventually we almost certainly want to use
308 // LocationBarLayout for leading and trailing decorations.
309
87 location_icon_view_->SetBounds( 310 location_icon_view_->SetBounds(
88 kEdgeThickness, 311 kEdgeThickness + (showing_16x16_icon_ ? k16x16IconLeadingSpacing : 0),
89 LocationBarView::kNormalEdgeThickness, 312 LocationBarView::kNormalEdgeThickness,
90 location_icon_view_->GetPreferredSize().width(), 313 location_icon_view_->GetPreferredSize().width(),
91 height() - 2 * LocationBarView::kNormalEdgeThickness); 314 height() - 2 * LocationBarView::kNormalEdgeThickness);
92 315
93 int host_label_x = location_icon_view_->x() + location_icon_view_->width() + 316 int host_label_x = location_icon_view_->x() + location_icon_view_->width() +
94 kIconTextSpacing; 317 kIconTextSpacing;
318 host_label_x += showing_16x16_icon_ ?
319 (k16x16IconLeadingSpacing + k16x16IconTrailingSpacing) : 0;
95 int host_label_width = 320 int host_label_width =
96 width() - host_label_x - kEdgeThickness - kTrailingLabelMargin; 321 width() - host_label_x - kEdgeThickness - kTrailingLabelMargin;
97 host_label_->SetBounds(host_label_x, 322 host_label_->SetBounds(host_label_x,
98 LocationBarView::kNormalEdgeThickness, 323 LocationBarView::kNormalEdgeThickness,
99 host_label_width, 324 host_label_width,
100 height() - 2 * LocationBarView::kNormalEdgeThickness); 325 height() - 2 * LocationBarView::kNormalEdgeThickness);
101 } 326 }
102 327
103 void SiteChipView::OnPaint(gfx::Canvas* canvas) { 328 void SiteChipView::OnPaint(gfx::Canvas* canvas) {
104 gfx::Rect rect(GetLocalBounds()); 329 gfx::Rect rect(GetLocalBounds());
105 rect.Inset(LocationBarView::kNormalEdgeThickness, 330 if (painter_)
106 LocationBarView::kNormalEdgeThickness); 331 views::Painter::PaintPainterAt(canvas, painter_, rect);
107 if (background_painter_.get())
108 views::Painter::PaintPainterAt(canvas, background_painter_.get(), rect);
109 332
110 ToolbarButton::OnPaint(canvas); 333 ToolbarButton::OnPaint(canvas);
111 } 334 }
112 335
113 // TODO(gbillock): Make the LocationBarView or OmniboxView the listener for 336 // TODO(gbillock): Make the LocationBarView or OmniboxView the listener for
114 // this button. 337 // this button.
115 void SiteChipView::ButtonPressed(views::Button* sender, 338 void SiteChipView::ButtonPressed(views::Button* sender,
116 const ui::Event& event) { 339 const ui::Event& event) {
117 toolbar_view_->location_bar()->GetOmniboxView()->SetFocus(); 340 toolbar_view_->location_bar()->GetOmniboxView()->SetFocus();
118 toolbar_view_->location_bar()->GetOmniboxView()->SelectAll(true); 341 toolbar_view_->location_bar()->GetOmniboxView()->SelectAll(true);
119 toolbar_view_->location_bar()->GetOmniboxView()->model()-> 342 toolbar_view_->location_bar()->GetOmniboxView()->model()->
120 SetCaretVisibility(true); 343 SetCaretVisibility(true);
121 } 344 }
345
346 void SiteChipView::WriteDragDataForView(View* sender,
347 const gfx::Point& press_pt,
348 OSExchangeData* data) {
349 // TODO(gbillock): Consolidate this with the identical logic in
350 // LocationBarView.
351 content::WebContents* web_contents = toolbar_view_->GetWebContents();
352 FaviconTabHelper* favicon_tab_helper =
353 FaviconTabHelper::FromWebContents(web_contents);
354 gfx::ImageSkia favicon = favicon_tab_helper->GetFavicon().AsImageSkia();
355 button_drag_utils::SetURLAndDragImage(web_contents->GetURL(),
356 web_contents->GetTitle(),
357 favicon,
358 data,
359 sender->GetWidget());
360 }
361
362 int SiteChipView::GetDragOperationsForView(View* sender,
363 const gfx::Point& p) {
364 return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK;
365 }
366
367 bool SiteChipView::CanStartDragForView(View* sender,
368 const gfx::Point& press_pt,
369 const gfx::Point& p) {
370 return true;
371 }
372
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698