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

Side by Side Diff: chrome/browser/ui/views/frame/browser_header_painter_ash.cc

Issue 189463013: [Refactor] Move code for painting the window header for browser windows out of ash (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/views/frame/browser_header_painter_ash.h"
6
7 #include "ash/frame/caption_buttons/frame_caption_button_container_view.h"
8 #include "ash/frame/header_painter_util.h"
9 #include "base/logging.h" // DCHECK
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/views/frame/browser_frame.h"
12 #include "chrome/browser/ui/views/frame/browser_view.h"
13 #include "grit/ash_resources.h"
14 #include "grit/theme_resources.h"
15 #include "third_party/skia/include/core/SkCanvas.h"
16 #include "third_party/skia/include/core/SkColor.h"
17 #include "third_party/skia/include/core/SkPaint.h"
18 #include "third_party/skia/include/core/SkPath.h"
19 #include "ui/base/resource/resource_bundle.h"
20 #include "ui/base/theme_provider.h"
21 #include "ui/gfx/animation/slide_animation.h"
22 #include "ui/gfx/canvas.h"
23 #include "ui/gfx/image/image_skia.h"
24 #include "ui/gfx/rect.h"
25 #include "ui/gfx/skia_util.h"
26 #include "ui/views/view.h"
27 #include "ui/views/widget/widget.h"
28 #include "ui/views/widget/widget_delegate.h"
29
30 using views::Widget;
31
32 namespace {
33 // Color for the restored window title text.
34 const SkColor kRestoredWindowTitleTextColor = SkColorSetRGB(40, 40, 40);
35 // Color for the maximized window title text.
36 const SkColor kMaximizedWindowTitleTextColor = SK_ColorWHITE;
37 // Duration of crossfade animation for activating and deactivating frame.
38 const int kActivationCrossfadeDurationMs = 200;
39
40 // Tiles an image into an area, rounding the top corners. Samples |image|
41 // starting |image_inset_x| pixels from the left of the image.
42 void TileRoundRect(gfx::Canvas* canvas,
43 const gfx::ImageSkia& image,
44 const SkPaint& paint,
45 const gfx::Rect& bounds,
46 int top_left_corner_radius,
47 int top_right_corner_radius,
48 int image_inset_x) {
49 SkRect rect = gfx::RectToSkRect(bounds);
50 const SkScalar kTopLeftRadius = SkIntToScalar(top_left_corner_radius);
51 const SkScalar kTopRightRadius = SkIntToScalar(top_right_corner_radius);
52 SkScalar radii[8] = {
53 kTopLeftRadius, kTopLeftRadius, // top-left
54 kTopRightRadius, kTopRightRadius, // top-right
55 0, 0, // bottom-right
56 0, 0}; // bottom-left
57 SkPath path;
58 path.addRoundRect(rect, radii, SkPath::kCW_Direction);
59 canvas->DrawImageInPath(image, -image_inset_x, 0, path, paint);
60 }
61
62 // Tiles |frame_image| and |frame_overlay_image| into an area, rounding the top
63 // corners.
64 void PaintFrameImagesInRoundRect(gfx::Canvas* canvas,
65 const gfx::ImageSkia& frame_image,
66 const gfx::ImageSkia& frame_overlay_image,
67 const SkPaint& paint,
68 const gfx::Rect& bounds,
69 int corner_radius,
70 int image_inset_x) {
71 SkXfermode::Mode normal_mode;
72 SkXfermode::AsMode(NULL, &normal_mode);
73
74 // If |paint| is using an unusual SkXfermode::Mode (this is the case while
75 // crossfading), we must create a new canvas to overlay |frame_image| and
76 // |frame_overlay_image| using |normal_mode| and then paint the result
77 // using the unusual mode. We try to avoid this because creating a new
78 // browser-width canvas is expensive.
79 bool fast_path = (frame_overlay_image.isNull() ||
80 SkXfermode::IsMode(paint.getXfermode(), normal_mode));
81 if (fast_path) {
82 TileRoundRect(canvas, frame_image, paint, bounds, corner_radius,
83 corner_radius, image_inset_x);
84
85 if (!frame_overlay_image.isNull()) {
86 // Adjust |bounds| such that |frame_overlay_image| is not tiled.
87 gfx::Rect overlay_bounds = bounds;
88 overlay_bounds.Intersect(
89 gfx::Rect(bounds.origin(), frame_overlay_image.size()));
90 int top_left_corner_radius = corner_radius;
91 int top_right_corner_radius = corner_radius;
92 if (overlay_bounds.width() < bounds.width() - corner_radius)
93 top_right_corner_radius = 0;
94 TileRoundRect(canvas, frame_overlay_image, paint, overlay_bounds,
95 top_left_corner_radius, top_right_corner_radius, 0);
96 }
97 } else {
98 gfx::Canvas temporary_canvas(bounds.size(), canvas->image_scale(), false);
99 temporary_canvas.TileImageInt(frame_image,
100 image_inset_x, 0,
101 0, 0,
102 bounds.width(), bounds.height());
103 temporary_canvas.DrawImageInt(frame_overlay_image, 0, 0);
104 TileRoundRect(canvas, gfx::ImageSkia(temporary_canvas.ExtractImageRep()),
105 paint, bounds, corner_radius, corner_radius, 0);
106 }
107 }
108
109 } // namespace
110
111 ///////////////////////////////////////////////////////////////////////////////
112 // BrowserHeaderPainterAsh, public:
113
114 BrowserHeaderPainterAsh::BrowserHeaderPainterAsh()
115 : frame_(NULL),
116 is_tabbed_(false),
117 is_incognito_(false),
118 view_(NULL),
119 window_icon_(NULL),
120 caption_button_container_(NULL),
121 painted_height_(0),
122 initial_paint_(true),
123 mode_(MODE_INACTIVE),
124 activation_animation_(new gfx::SlideAnimation(this)) {
125 }
126
127 BrowserHeaderPainterAsh::~BrowserHeaderPainterAsh() {
128 }
129
130 void BrowserHeaderPainterAsh::Init(
131 views::Widget* frame,
132 BrowserView* browser_view,
133 views::View* header_view,
134 views::View* window_icon,
135 ash::FrameCaptionButtonContainerView* caption_button_container) {
136 DCHECK(frame);
137 DCHECK(browser_view);
138 DCHECK(header_view);
139 // window_icon may be NULL.
140 DCHECK(caption_button_container);
141 frame_ = frame;
142
143 is_tabbed_ = browser_view->browser()->is_type_tabbed();
144 is_incognito_ = !browser_view->IsRegularOrGuestSession();
145
146 view_ = header_view;
147 window_icon_ = window_icon;
148 caption_button_container_ = caption_button_container;
149 }
150
151 int BrowserHeaderPainterAsh::GetMinimumHeaderWidth() const {
152 // Ensure we have enough space for the window icon and buttons. We allow
153 // the title string to collapse to zero width.
154 return GetTitleBounds().x() +
155 caption_button_container_->GetMinimumSize().width();
156 }
157
158 void BrowserHeaderPainterAsh::PaintHeader(gfx::Canvas* canvas, Mode mode) {
159 Mode old_mode = mode_;
160 mode_ = mode;
161
162 if (mode_ != old_mode) {
163 if (!initial_paint_ &&
164 ash::HeaderPainterUtil::CanAnimateActivation(frame_)) {
165 activation_animation_->SetSlideDuration(kActivationCrossfadeDurationMs);
166 if (mode_ == MODE_ACTIVE)
167 activation_animation_->Show();
168 else
169 activation_animation_->Hide();
170 } else {
171 if (mode_ == MODE_ACTIVE)
172 activation_animation_->Reset(1);
173 else
174 activation_animation_->Reset(0);
175 }
176 initial_paint_ = false;
177 }
178
179 int corner_radius = (frame_->IsMaximized() || frame_->IsFullscreen()) ?
180 0 : ash::HeaderPainterUtil::GetTopCornerRadiusWhenRestored();
181
182 int active_alpha = activation_animation_->CurrentValueBetween(0, 255);
183 int inactive_alpha = 255 - active_alpha;
184
185 SkPaint paint;
186 if (inactive_alpha > 0) {
187 if (active_alpha > 0)
188 paint.setXfermodeMode(SkXfermode::kPlus_Mode);
189
190 gfx::ImageSkia inactive_frame_image;
191 gfx::ImageSkia inactive_frame_overlay_image;
192 GetFrameImages(MODE_INACTIVE, &inactive_frame_image,
193 &inactive_frame_overlay_image);
194
195 paint.setAlpha(inactive_alpha);
196 PaintFrameImagesInRoundRect(
197 canvas,
198 inactive_frame_image,
199 inactive_frame_overlay_image,
200 paint,
201 GetPaintedBounds(),
202 corner_radius,
203 ash::HeaderPainterUtil::GetThemeBackgroundXInset());
204 }
205
206 if (active_alpha > 0) {
207 gfx::ImageSkia active_frame_image;
208 gfx::ImageSkia active_frame_overlay_image;
209 GetFrameImages(MODE_ACTIVE, &active_frame_image,
210 &active_frame_overlay_image);
211
212 paint.setAlpha(active_alpha);
213 PaintFrameImagesInRoundRect(
214 canvas,
215 active_frame_image,
216 active_frame_overlay_image,
217 paint,
218 GetPaintedBounds(),
219 corner_radius,
220 ash::HeaderPainterUtil::GetThemeBackgroundXInset());
221 }
222
223 if (!frame_->IsMaximized() && !frame_->IsFullscreen())
224 PaintHighlightForRestoredWindow(canvas);
225 if (frame_->widget_delegate() &&
226 frame_->widget_delegate()->ShouldShowWindowTitle()) {
227 PaintTitleBar(canvas);
228 }
229 }
230
231 void BrowserHeaderPainterAsh::LayoutHeader() {
232 // Purposefully set |painted_height_| to an invalid value. We cannot use
233 // |painted_height_| because the computation of |painted_height_| may depend
234 // on having laid out the window controls.
235 painted_height_ = -1;
236
237 UpdateCaptionButtonImages();
238 caption_button_container_->Layout();
239
240 gfx::Size caption_button_container_size =
241 caption_button_container_->GetPreferredSize();
242 caption_button_container_->SetBounds(
243 view_->width() - caption_button_container_size.width(),
244 0,
245 caption_button_container_size.width(),
246 caption_button_container_size.height());
247
248 if (window_icon_) {
249 // Vertically center the window icon with respect to the caption button
250 // container.
251 int icon_size = ash::HeaderPainterUtil::GetIconSize();
252 int icon_offset_y = (caption_button_container_->height() - icon_size) / 2;
253 window_icon_->SetBounds(ash::HeaderPainterUtil::GetIconXOffset(),
254 icon_offset_y, icon_size, icon_size);
255 }
256 }
257
258 int BrowserHeaderPainterAsh::GetHeaderHeightForPainting() const {
259 return painted_height_;
260 }
261
262 void BrowserHeaderPainterAsh::SetHeaderHeightForPainting(int height) {
263 painted_height_ = height;
264 }
265
266 void BrowserHeaderPainterAsh::SchedulePaintForTitle() {
267 view_->SchedulePaintInRect(GetTitleBounds());
268 }
269
270 ///////////////////////////////////////////////////////////////////////////////
271 // gfx::AnimationDelegate overrides:
272
273 void BrowserHeaderPainterAsh::AnimationProgressed(
274 const gfx::Animation* animation) {
275 view_->SchedulePaintInRect(GetPaintedBounds());
276 }
277
278 ///////////////////////////////////////////////////////////////////////////////
279 // BrowserHeaderPainterAsh, private:
280
281 void BrowserHeaderPainterAsh::PaintHighlightForRestoredWindow(
282 gfx::Canvas* canvas) {
283 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
284 gfx::ImageSkia top_left_corner = *rb.GetImageSkiaNamed(
285 IDR_AURA_BROWSER_WINDOW_HEADER_SHADE_TOP_LEFT);
286 gfx::ImageSkia top_right_corner = *rb.GetImageSkiaNamed(
287 IDR_AURA_BROWSER_WINDOW_HEADER_SHADE_TOP_RIGHT);
288 gfx::ImageSkia top_edge = *rb.GetImageSkiaNamed(
289 IDR_AURA_BROWSER_WINDOW_HEADER_SHADE_TOP);
290 gfx::ImageSkia left_edge = *rb.GetImageSkiaNamed(
291 IDR_AURA_BROWSER_WINDOW_HEADER_SHADE_LEFT);
292 gfx::ImageSkia right_edge = *rb.GetImageSkiaNamed(
293 IDR_AURA_BROWSER_WINDOW_HEADER_SHADE_RIGHT);
294
295 int top_left_width = top_left_corner.width();
296 int top_left_height = top_left_corner.height();
297 canvas->DrawImageInt(top_left_corner, 0, 0);
298
299 int top_right_width = top_right_corner.width();
300 int top_right_height = top_right_corner.height();
301 canvas->DrawImageInt(top_right_corner,
302 view_->width() - top_right_width,
303 0);
304
305 canvas->TileImageInt(
306 top_edge,
307 top_left_width,
308 0,
309 view_->width() - top_left_width - top_right_width,
310 top_edge.height());
311
312 canvas->TileImageInt(left_edge,
313 0,
314 top_left_height,
315 left_edge.width(),
316 painted_height_ - top_left_height);
317
318 canvas->TileImageInt(right_edge,
319 view_->width() - right_edge.width(),
320 top_right_height,
321 right_edge.width(),
322 painted_height_ - top_right_height);
323 }
324
325 void BrowserHeaderPainterAsh::PaintTitleBar(gfx::Canvas* canvas) {
326 // The window icon is painted by its own views::View.
327 gfx::Rect title_bounds = GetTitleBounds();
328 title_bounds.set_x(view_->GetMirroredXForRect(title_bounds));
329 SkColor title_color = (frame_->IsMaximized() || frame_->IsFullscreen()) ?
330 kMaximizedWindowTitleTextColor : kRestoredWindowTitleTextColor;
331 canvas->DrawStringRectWithFlags(frame_->widget_delegate()->GetWindowTitle(),
332 BrowserFrame::GetTitleFontList(),
333 title_color,
334 title_bounds,
335 gfx::Canvas::NO_SUBPIXEL_RENDERING);
336 }
337
338 void BrowserHeaderPainterAsh::GetFrameImages(
339 Mode mode,
340 gfx::ImageSkia* frame_image,
341 gfx::ImageSkia* frame_overlay_image) const {
342 if (is_tabbed_) {
343 GetFrameImagesForTabbedBrowser(mode, frame_image, frame_overlay_image);
344 } else {
345 *frame_image = GetFrameImageForNonTabbedBrowser(mode);
346 *frame_overlay_image = gfx::ImageSkia();
347 }
348 }
349
350 void BrowserHeaderPainterAsh::GetFrameImagesForTabbedBrowser(
351 Mode mode,
352 gfx::ImageSkia* frame_image,
353 gfx::ImageSkia* frame_overlay_image) const {
354 int frame_image_id = 0;
355 int frame_overlay_image_id = 0;
356
357 ui::ThemeProvider* tp = frame_->GetThemeProvider();
358 if (tp->HasCustomImage(IDR_THEME_FRAME_OVERLAY) && !is_incognito_) {
359 frame_overlay_image_id = (mode == MODE_ACTIVE) ?
360 IDR_THEME_FRAME_OVERLAY : IDR_THEME_FRAME_OVERLAY_INACTIVE;
361 }
362
363 if (mode == MODE_ACTIVE) {
364 frame_image_id = is_incognito_ ?
365 IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME;
366 } else {
367 frame_image_id = is_incognito_ ?
368 IDR_THEME_FRAME_INCOGNITO_INACTIVE : IDR_THEME_FRAME_INACTIVE;
369 }
370
371 if ((frame_->IsMaximized() || frame_->IsFullscreen()) &&
372 !tp->HasCustomImage(IDR_THEME_FRAME) &&
373 !tp->HasCustomImage(frame_image_id) &&
374 frame_overlay_image_id == 0) {
375 *frame_image = *tp->GetImageSkiaNamed(
376 IDR_AURA_BROWSER_WINDOW_HEADER_BASE_MAXIMIZED);
377 } else {
378 *frame_image = *tp->GetImageSkiaNamed(frame_image_id);
379 }
380
381 *frame_overlay_image = (frame_overlay_image_id == 0) ?
382 gfx::ImageSkia() : *tp->GetImageSkiaNamed(frame_overlay_image_id);
383 }
384
385 gfx::ImageSkia BrowserHeaderPainterAsh::GetFrameImageForNonTabbedBrowser(
386 Mode mode) const {
387 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
388 if (frame_->IsMaximized() || frame_->IsFullscreen())
389 return *rb.GetImageSkiaNamed(IDR_AURA_BROWSER_WINDOW_HEADER_BASE_MAXIMIZED);
390
391 if (mode == MODE_ACTIVE) {
392 return *rb.GetImageSkiaNamed(is_incognito_ ?
393 IDR_AURA_BROWSER_WINDOW_HEADER_BASE_RESTORED_INCOGNITO_ACTIVE :
394 IDR_AURA_BROWSER_WINDOW_HEADER_BASE_RESTORED_ACTIVE);
395 }
396 return *rb.GetImageSkiaNamed(is_incognito_ ?
397 IDR_AURA_BROWSER_WINDOW_HEADER_BASE_RESTORED_INCOGNITO_INACTIVE :
398 IDR_AURA_BROWSER_WINDOW_HEADER_BASE_RESTORED_INACTIVE);
399 }
400
401 void BrowserHeaderPainterAsh::UpdateCaptionButtonImages() {
402 if (frame_->IsMaximized() || frame_->IsFullscreen()) {
403 caption_button_container_->SetButtonImages(
404 ash::CAPTION_BUTTON_ICON_MINIMIZE,
405 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_MINIMIZE,
406 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_MINIMIZE,
407 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_H,
408 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_P);
409 caption_button_container_->SetButtonImages(
410 ash::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE,
411 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_SIZE,
412 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_SIZE,
413 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_H,
414 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_P);
415 caption_button_container_->SetButtonImages(
416 ash::CAPTION_BUTTON_ICON_CLOSE,
417 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_CLOSE,
418 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_CLOSE,
419 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_H,
420 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_P);
421 caption_button_container_->SetButtonImages(
422 ash::CAPTION_BUTTON_ICON_LEFT_SNAPPED,
423 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_LEFT_SNAPPED,
424 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_LEFT_SNAPPED,
425 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_H,
426 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_P);
427 caption_button_container_->SetButtonImages(
428 ash::CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
429 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_RIGHT_SNAPPED,
430 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_MAXIMIZED_RIGHT_SNAPPED,
431 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_H,
432 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_MAXIMIZED_P);
433 } else {
434 caption_button_container_->SetButtonImages(
435 ash::CAPTION_BUTTON_ICON_MINIMIZE,
436 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_MINIMIZE,
437 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_MINIMIZE,
438 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_H,
439 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_P);
440 caption_button_container_->SetButtonImages(
441 ash::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE,
442 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_SIZE,
443 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_SIZE,
444 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_H,
445 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_P);
446 caption_button_container_->SetButtonImages(
447 ash::CAPTION_BUTTON_ICON_CLOSE,
448 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_CLOSE,
449 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_CLOSE,
450 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_H,
451 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_P);
452 caption_button_container_->SetButtonImages(
453 ash::CAPTION_BUTTON_ICON_LEFT_SNAPPED,
454 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_LEFT_SNAPPED,
455 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_LEFT_SNAPPED,
456 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_H,
457 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_P);
458 caption_button_container_->SetButtonImages(
459 ash::CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
460 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_RIGHT_SNAPPED,
461 IDR_AURA_BROWSER_WINDOW_CONTROL_ICON_RESTORED_RIGHT_SNAPPED,
462 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_H,
463 IDR_AURA_BROWSER_WINDOW_CONTROL_BACKGROUND_RESTORED_P);
464 }
465 }
466
467 gfx::Rect BrowserHeaderPainterAsh::GetPaintedBounds() const {
468 return gfx::Rect(view_->width(), painted_height_);
469 }
470
471 gfx::Rect BrowserHeaderPainterAsh::GetTitleBounds() const {
472 return ash::HeaderPainterUtil::GetTitleBounds(window_icon_,
473 caption_button_container_, BrowserFrame::GetTitleFontList());
474 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698