browser_non_client_frame_view_ash.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright (c) 2012 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_non_client_frame_view_ash.h"
6
7#include "ash/ash_switches.h"
8#include "ash/wm/caption_buttons/frame_caption_button_container_view.h"
9#include "ash/wm/frame_border_hit_test_controller.h"
10#include "ash/wm/header_painter.h"
11#include "base/command_line.h"
12#include "chrome/browser/themes/theme_properties.h"
13#include "chrome/browser/ui/browser.h"
14#include "chrome/browser/ui/views/avatar_label.h"
15#include "chrome/browser/ui/views/avatar_menu_button.h"
16#include "chrome/browser/ui/views/frame/browser_frame.h"
17#include "chrome/browser/ui/views/frame/browser_view.h"
18#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
19#include "chrome/browser/ui/views/tab_icon_view.h"
20#include "chrome/browser/ui/views/tabs/tab_strip.h"
21#include "chrome/common/chrome_switches.h"
22#include "content/public/browser/web_contents.h"
23#include "grit/ash_resources.h"
24#include "grit/theme_resources.h"
25#include "ui/aura/client/aura_constants.h"
26#include "ui/aura/window.h"
27#include "ui/base/accessibility/accessible_view_state.h"
28#include "ui/base/hit_test.h"
29#include "ui/base/l10n/l10n_util.h"
30#include "ui/base/layout.h"
31#include "ui/base/resource/resource_bundle.h"
32#include "ui/base/theme_provider.h"
33#include "ui/compositor/layer_animator.h"
34#include "ui/gfx/canvas.h"
35#include "ui/gfx/image/image_skia.h"
36#include "ui/gfx/rect_conversions.h"
37#include "ui/views/controls/label.h"
38#include "ui/views/layout/layout_constants.h"
39#include "ui/views/widget/widget.h"
40#include "ui/views/widget/widget_delegate.h"
41
42namespace {
43
44// The avatar ends 2 px above the bottom of the tabstrip (which, given the
45// way the tabstrip draws its bottom edge, will appear like a 1 px gap to the
46// user).
47const int kAvatarBottomSpacing = 2;
48// There are 2 px on each side of the avatar (between the frame border and
49// it on the left, and between it and the tabstrip on the right).
50const int kAvatarSideSpacing = 2;
51// Space between left edge of window and tabstrip.
52const int kTabstripLeftSpacing = 0;
53// Space between right edge of tabstrip and maximize button.
54const int kTabstripRightSpacing = 10;
55// Height of the shadow of the content area, at the top of the toolbar.
56const int kContentShadowHeight = 1;
57// Space between top of window and top of tabstrip for tall headers, such as
58// for restored windows, apps, etc.
59const int kTabstripTopSpacingTall = 7;
60// Space between top of window and top of tabstrip for short headers, such as
61// for maximized windows, pop-ups, etc.
62const int kTabstripTopSpacingShort = 0;
63// Height of the shadow in the tab image, used to ensure clicks in the shadow
64// area still drag restored windows.  This keeps the clickable area large enough
65// to hit easily.
66const int kTabShadowHeight = 4;
67
68}  // namespace
69
70///////////////////////////////////////////////////////////////////////////////
71// BrowserNonClientFrameViewAsh, public:
72
73// static
74const char BrowserNonClientFrameViewAsh::kViewClassName[] =
75    "BrowserNonClientFrameViewAsh";
76
77BrowserNonClientFrameViewAsh::BrowserNonClientFrameViewAsh(
78    BrowserFrame* frame, BrowserView* browser_view)
79    : BrowserNonClientFrameView(frame, browser_view),
80      caption_button_container_(NULL),
81      window_icon_(NULL),
82      header_painter_(new ash::HeaderPainter),
83      frame_border_hit_test_controller_(
84          new ash::FrameBorderHitTestController(frame)) {
85}
86
87BrowserNonClientFrameViewAsh::~BrowserNonClientFrameViewAsh() {
88}
89
90void BrowserNonClientFrameViewAsh::Init() {
91  caption_button_container_ = new ash::FrameCaptionButtonContainerView(frame(),
92      ash::FrameCaptionButtonContainerView::MINIMIZE_ALLOWED);
93  AddChildView(caption_button_container_);
94
95  // Initializing the TabIconView is expensive, so only do it if we need to.
96  if (browser_view()->ShouldShowWindowIcon()) {
97    window_icon_ = new TabIconView(this, NULL);
98    window_icon_->set_is_light(true);
99    AddChildView(window_icon_);
100    window_icon_->Update();
101  }
102
103  // Create incognito icon if necessary.
104  UpdateAvatarInfo();
105
106  // HeaderPainter handles layout.
107  header_painter_->Init(frame(), this, window_icon_, caption_button_container_);
108}
109
110///////////////////////////////////////////////////////////////////////////////
111// BrowserNonClientFrameView overrides:
112
113gfx::Rect BrowserNonClientFrameViewAsh::GetBoundsForTabStrip(
114    views::View* tabstrip) const {
115  if (!tabstrip)
116    return gfx::Rect();
117
118  // When the tab strip is painted in the immersive fullscreen light bar style,
119  // the caption buttons and the avatar button are not visible. However, their
120  // bounds are still used to compute the tab strip bounds so that the tabs have
121  // the same horizontal position when the tab strip is painted in the immersive
122  // light bar style as when the top-of-window views are revealed.
123  int left_inset = GetTabStripLeftInset();
124  int right_inset = GetTabStripRightInset();
125  return gfx::Rect(left_inset,
126                   GetTopInset(),
127                   std::max(0, width() - left_inset - right_inset),
128                   tabstrip->GetPreferredSize().height());
129}
130
131int BrowserNonClientFrameViewAsh::GetTopInset() const {
132  if (!ShouldPaint() || UseImmersiveLightbarHeaderStyle())
133    return 0;
134
135  if (browser_view()->IsTabStripVisible()) {
136    if (frame()->IsMaximized() || frame()->IsFullscreen())
137      return kTabstripTopSpacingShort;
138    else
139      return kTabstripTopSpacingTall;
140  }
141
142  int caption_buttons_bottom = caption_button_container_->bounds().bottom();
143
144  // The toolbar partially overlaps the caption buttons.
145  if (browser_view()->IsToolbarVisible())
146    return caption_buttons_bottom - kContentShadowHeight;
147
148  int separator_thickness = UsePackagedAppHeaderStyle() ?
149      header_painter_->HeaderContentSeparatorSize() : kClientEdgeThickness;
150  return caption_buttons_bottom + separator_thickness;
151}
152
153int BrowserNonClientFrameViewAsh::GetThemeBackgroundXInset() const {
154  return header_painter_->GetThemeBackgroundXInset();
155}
156
157void BrowserNonClientFrameViewAsh::UpdateThrobber(bool running) {
158  if (window_icon_)
159    window_icon_->Update();
160}
161
162///////////////////////////////////////////////////////////////////////////////
163// views::NonClientFrameView overrides:
164
165gfx::Rect BrowserNonClientFrameViewAsh::GetBoundsForClientView() const {
166  // The ClientView must be flush with the top edge of the widget so that the
167  // web contents can take up the entire screen in immersive fullscreen (with
168  // or without the top-of-window views revealed). When in immersive fullscreen
169  // and the top-of-window views are revealed, the TopContainerView paints the
170  // window header by redirecting paints from its background to
171  // BrowserNonClientFrameViewAsh.
172  return ash::HeaderPainter::GetBoundsForClientView(0, bounds());
173}
174
175gfx::Rect BrowserNonClientFrameViewAsh::GetWindowBoundsForClientBounds(
176    const gfx::Rect& client_bounds) const {
177  return ash::HeaderPainter::GetWindowBoundsForClientBounds(0, client_bounds);
178}
179
180int BrowserNonClientFrameViewAsh::NonClientHitTest(const gfx::Point& point) {
181  int hit_test = ash::FrameBorderHitTestController::NonClientHitTest(this,
182      header_painter_.get(), point);
183
184  // See if the point is actually within the avatar menu button or within
185  // the avatar label.
186  if (hit_test == HTCAPTION && ((avatar_button() &&
187       avatar_button()->GetMirroredBounds().Contains(point)) ||
188      (avatar_label() && avatar_label()->GetMirroredBounds().Contains(point))))
189      return HTCLIENT;
190
191  // When the window is restored we want a large click target above the tabs
192  // to drag the window, so redirect clicks in the tab's shadow to caption.
193  if (hit_test == HTCLIENT &&
194      !(frame()->IsMaximized() || frame()->IsFullscreen())) {
195    // Convert point to client coordinates.
196    gfx::Point client_point(point);
197    View::ConvertPointToTarget(this, frame()->client_view(), &client_point);
198    // Report hits in shadow at top of tabstrip as caption.
199    gfx::Rect tabstrip_bounds(browser_view()->tabstrip()->bounds());
200    if (client_point.y() < tabstrip_bounds.y() + kTabShadowHeight)
201      hit_test = HTCAPTION;
202  }
203  return hit_test;
204}
205
206void BrowserNonClientFrameViewAsh::GetWindowMask(const gfx::Size& size,
207                                                 gfx::Path* window_mask) {
208  // Aura does not use window masks.
209}
210
211void BrowserNonClientFrameViewAsh::ResetWindowControls() {
212  // Hide the caption buttons in immersive fullscreen when the tab light bar
213  // is visible because it's confusing when the user hovers or clicks in the
214  // top-right of the screen and hits one.
215  bool button_visibility = !UseImmersiveLightbarHeaderStyle();
216  caption_button_container_->SetVisible(button_visibility);
217
218  caption_button_container_->ResetWindowControls();
219}
220
221void BrowserNonClientFrameViewAsh::UpdateWindowIcon() {
222  if (window_icon_)
223    window_icon_->SchedulePaint();
224}
225
226void BrowserNonClientFrameViewAsh::UpdateWindowTitle() {
227  if (!frame()->IsFullscreen())
228    header_painter_->SchedulePaintForTitle(BrowserFrame::GetTitleFontList());
229}
230
231///////////////////////////////////////////////////////////////////////////////
232// views::View overrides:
233
234void BrowserNonClientFrameViewAsh::OnPaint(gfx::Canvas* canvas) {
235  if (!ShouldPaint())
236    return;
237
238  if (UseImmersiveLightbarHeaderStyle()) {
239    PaintImmersiveLightbarStyleHeader(canvas);
240    return;
241  }
242
243  // The primary header image changes based on window activation state and
244  // theme, so we look it up for each paint.
245  int theme_frame_image_id = GetThemeFrameImageId();
246  int theme_frame_overlay_image_id = GetThemeFrameOverlayImageId();
247
248  ui::ThemeProvider* theme_provider = GetThemeProvider();
249  if (!theme_provider->HasCustomImage(theme_frame_image_id) &&
250      (theme_frame_overlay_image_id == 0 ||
251       !theme_provider->HasCustomImage(theme_frame_overlay_image_id))) {
252    if (frame()->IsMaximized() || frame()->IsFullscreen())
253      theme_frame_image_id = IDR_AURA_WINDOW_HEADER_BASE_MINIMAL;
254  }
255  header_painter_->PaintHeader(
256      canvas,
257      theme_frame_image_id,
258      theme_frame_overlay_image_id);
259  if (browser_view()->ShouldShowWindowTitle())
260    header_painter_->PaintTitleBar(canvas, BrowserFrame::GetTitleFontList());
261  if (browser_view()->IsToolbarVisible())
262    PaintToolbarBackground(canvas);
263  else
264    PaintContentEdge(canvas);
265}
266
267void BrowserNonClientFrameViewAsh::Layout() {
268  // The header must be laid out before computing |header_height| because the
269  // computation of |header_height| for app and popup windows depends on the
270  // position of the window controls.
271  header_painter_->LayoutHeader(UsePackagedAppHeaderStyle() ||
272                                frame()->IsMaximized() ||
273                                frame()->IsFullscreen());
274
275  int header_height = 0;
276  if (browser_view()->IsTabStripVisible()) {
277    header_height = GetTopInset() +
278        browser_view()->tabstrip()->GetPreferredSize().height();
279  } else if (browser_view()->IsToolbarVisible()) {
280    // Set the header's height so that it overlaps with the toolbar because the
281    // top few pixels of the toolbar are not opaque.
282    header_height = GetTopInset() + kFrameShadowThickness * 2;
283  } else {
284    header_height = GetTopInset();
285  }
286  header_painter_->set_header_height(header_height);
287  if (avatar_button())
288    LayoutAvatar();
289  BrowserNonClientFrameView::Layout();
290}
291
292const char* BrowserNonClientFrameViewAsh::GetClassName() const {
293  return kViewClassName;
294}
295
296bool BrowserNonClientFrameViewAsh::HitTestRect(const gfx::Rect& rect) const {
297  if (!views::View::HitTestRect(rect)) {
298    // |rect| is outside BrowserNonClientFrameViewAsh's bounds.
299    return false;
300  }
301
302  TabStrip* tabstrip = browser_view()->tabstrip();
303  if (tabstrip && browser_view()->IsTabStripVisible()) {
304    // Claim |rect| only if it is above the bottom of the tabstrip in a non-tab
305    // portion.
306    gfx::RectF rect_in_tabstrip_coords_f(rect);
307    View::ConvertRectToTarget(this, tabstrip, &rect_in_tabstrip_coords_f);
308    gfx::Rect rect_in_tabstrip_coords = gfx::ToEnclosingRect(
309        rect_in_tabstrip_coords_f);
310
311     if (rect_in_tabstrip_coords.y() > tabstrip->height())
312       return false;
313
314    return !tabstrip->HitTestRect(rect_in_tabstrip_coords) ||
315        tabstrip->IsRectInWindowCaption(rect_in_tabstrip_coords);
316  }
317
318  // Claim |rect| if it is above the top of the topmost view in the client area.
319  return rect.y() < GetTopInset();
320}
321
322void BrowserNonClientFrameViewAsh::GetAccessibleState(
323    ui::AccessibleViewState* state) {
324  state->role = ui::AccessibilityTypes::ROLE_TITLEBAR;
325}
326
327gfx::Size BrowserNonClientFrameViewAsh::GetMinimumSize() {
328  gfx::Size min_client_view_size(frame()->client_view()->GetMinimumSize());
329  int min_width = std::max(header_painter_->GetMinimumHeaderWidth(),
330                           min_client_view_size.width());
331  if (browser_view()->IsTabStripVisible()) {
332    // Ensure that the minimum width is enough to hold a minimum width tab strip
333    // at its usual insets.
334    int min_tabstrip_width =
335        browser_view()->tabstrip()->GetMinimumSize().width();
336    min_width = std::max(min_width,
337        min_tabstrip_width + GetTabStripLeftInset() + GetTabStripRightInset());
338  }
339  return gfx::Size(min_width, min_client_view_size.height());
340}
341
342void BrowserNonClientFrameViewAsh::OnThemeChanged() {
343  BrowserNonClientFrameView::OnThemeChanged();
344  header_painter_->OnThemeChanged();
345}
346
347///////////////////////////////////////////////////////////////////////////////
348// chrome::TabIconViewModel overrides:
349
350bool BrowserNonClientFrameViewAsh::ShouldTabIconViewAnimate() const {
351  // This function is queried during the creation of the window as the
352  // TabIconView we host is initialized, so we need to NULL check the selected
353  // WebContents because in this condition there is not yet a selected tab.
354  content::WebContents* current_tab = browser_view()->GetActiveWebContents();
355  return current_tab ? current_tab->IsLoading() : false;
356}
357
358gfx::ImageSkia BrowserNonClientFrameViewAsh::GetFaviconForTabIconView() {
359  views::WidgetDelegate* delegate = frame()->widget_delegate();
360  if (!delegate)
361    return gfx::ImageSkia();
362  return delegate->GetWindowIcon();
363}
364
365///////////////////////////////////////////////////////////////////////////////
366// BrowserNonClientFrameViewAsh, private:
367
368int BrowserNonClientFrameViewAsh::GetTabStripLeftInset() const {
369  return avatar_button() ? kAvatarSideSpacing +
370      browser_view()->GetOTRAvatarIcon().width() + kAvatarSideSpacing :
371      kTabstripLeftSpacing;
372}
373
374int BrowserNonClientFrameViewAsh::GetTabStripRightInset() const {
375  return header_painter_->GetRightInset() + kTabstripRightSpacing;
376}
377
378bool BrowserNonClientFrameViewAsh::UseImmersiveLightbarHeaderStyle() const {
379  ImmersiveModeController* immersive_controller =
380      browser_view()->immersive_mode_controller();
381  return immersive_controller->IsEnabled() &&
382      !immersive_controller->IsRevealed() &&
383      browser_view()->IsTabStripVisible();
384}
385
386bool BrowserNonClientFrameViewAsh::UsePackagedAppHeaderStyle() const {
387  // Non streamlined hosted apps do not have a toolbar or tabstrip. Their header
388  // should look the same as the header for packaged apps. Streamlined hosted
389  // apps have a toolbar so should use the browser header style.
390  return browser_view()->browser()->is_app() &&
391      !CommandLine::ForCurrentProcess()->HasSwitch(
392          switches::kEnableStreamlinedHostedApps);
393}
394
395void BrowserNonClientFrameViewAsh::LayoutAvatar() {
396  DCHECK(avatar_button());
397  DCHECK(browser_view()->IsTabStripVisible());
398  gfx::ImageSkia incognito_icon = browser_view()->GetOTRAvatarIcon();
399
400  int avatar_bottom = GetTopInset() +
401      browser_view()->GetTabStripHeight() - kAvatarBottomSpacing;
402  int avatar_restored_y = avatar_bottom - incognito_icon.height();
403  int avatar_y = (frame()->IsMaximized() || frame()->IsFullscreen()) ?
404      GetTopInset() + kContentShadowHeight : avatar_restored_y;
405
406  // Hide the incognito icon in immersive fullscreen when the tab light bar is
407  // visible because the header is too short for the icognito icon to be
408  // recognizable.
409  bool avatar_visible = !UseImmersiveLightbarHeaderStyle();
410  int avatar_height = avatar_visible ? avatar_bottom - avatar_y : 0;
411
412  gfx::Rect avatar_bounds(kAvatarSideSpacing,
413                          avatar_y,
414                          incognito_icon.width(),
415                          avatar_height);
416  avatar_button()->SetBoundsRect(avatar_bounds);
417  avatar_button()->SetVisible(avatar_visible);
418}
419
420bool BrowserNonClientFrameViewAsh::ShouldPaint() const {
421  if (!frame()->IsFullscreen())
422    return true;
423
424  // We need to paint when in immersive fullscreen and either:
425  // - The top-of-window views are revealed.
426  // - The lightbar style tabstrip is visible.
427  ImmersiveModeController* immersive_mode_controller =
428      browser_view()->immersive_mode_controller();
429  return immersive_mode_controller->IsEnabled() &&
430      (immersive_mode_controller->IsRevealed() ||
431       UseImmersiveLightbarHeaderStyle());
432}
433
434void BrowserNonClientFrameViewAsh::PaintImmersiveLightbarStyleHeader(
435    gfx::Canvas* canvas) {
436  // The light bar header is not themed because theming it does not look good.
437  gfx::ImageSkia* frame_image = GetThemeProvider()->GetImageSkiaNamed(
438      IDR_AURA_WINDOW_HEADER_BASE_MINIMAL);
439  canvas->TileImageInt(*frame_image, 0, 0, width(), frame_image->height());
440}
441
442void BrowserNonClientFrameViewAsh::PaintToolbarBackground(gfx::Canvas* canvas) {
443  gfx::Rect toolbar_bounds(browser_view()->GetToolbarBounds());
444  if (toolbar_bounds.IsEmpty())
445    return;
446  gfx::Point toolbar_origin(toolbar_bounds.origin());
447  View::ConvertPointToTarget(browser_view(), this, &toolbar_origin);
448  toolbar_bounds.set_origin(toolbar_origin);
449
450  int x = toolbar_bounds.x();
451  int w = toolbar_bounds.width();
452  int y = toolbar_bounds.y();
453  int h = toolbar_bounds.height();
454
455  // Gross hack: We split the toolbar images into two pieces, since sometimes
456  // (popup mode) the toolbar isn't tall enough to show the whole image.  The
457  // split happens between the top shadow section and the bottom gradient
458  // section so that we never break the gradient.
459  // NOTE(pkotwicz): If the computation for |bottom_y| is changed, Layout() must
460  // be changed as well.
461  int split_point = kFrameShadowThickness * 2;
462  int bottom_y = y + split_point;
463  ui::ThemeProvider* tp = GetThemeProvider();
464  int bottom_edge_height = h - split_point;
465
466  canvas->FillRect(gfx::Rect(x, bottom_y, w, bottom_edge_height),
467                   tp->GetColor(ThemeProperties::COLOR_TOOLBAR));
468
469  // Paint the main toolbar image.  Since this image is also used to draw the
470  // tab background, we must use the tab strip offset to compute the image
471  // source y position.  If you have to debug this code use an image editor
472  // to paint a diagonal line through the toolbar image and ensure it lines up
473  // across the tab and toolbar.
474  gfx::ImageSkia* theme_toolbar = tp->GetImageSkiaNamed(IDR_THEME_TOOLBAR);
475  canvas->TileImageInt(
476      *theme_toolbar,
477      x + GetThemeBackgroundXInset(),
478      bottom_y - GetTopInset(),
479      x, bottom_y,
480      w, theme_toolbar->height());
481
482  // The content area line has a shadow that extends a couple of pixels above
483  // the toolbar bounds.
484  const int kContentShadowHeight = 2;
485  gfx::ImageSkia* toolbar_top = tp->GetImageSkiaNamed(IDR_TOOLBAR_SHADE_TOP);
486  canvas->TileImageInt(*toolbar_top,
487                       0, 0,
488                       x, y - kContentShadowHeight,
489                       w, split_point + kContentShadowHeight + 1);
490
491  // Draw the "lightening" shade line around the edges of the toolbar.
492  gfx::ImageSkia* toolbar_left = tp->GetImageSkiaNamed(IDR_TOOLBAR_SHADE_LEFT);
493  canvas->TileImageInt(*toolbar_left,
494                       0, 0,
495                       x + kClientEdgeThickness,
496                       y + kClientEdgeThickness + kContentShadowHeight,
497                       toolbar_left->width(), theme_toolbar->height());
498  gfx::ImageSkia* toolbar_right =
499      tp->GetImageSkiaNamed(IDR_TOOLBAR_SHADE_RIGHT);
500  canvas->TileImageInt(*toolbar_right,
501                       0, 0,
502                       w - toolbar_right->width() - 2 * kClientEdgeThickness,
503                       y + kClientEdgeThickness + kContentShadowHeight,
504                       toolbar_right->width(), theme_toolbar->height());
505
506  // Draw the content/toolbar separator.
507  canvas->FillRect(
508      gfx::Rect(x + kClientEdgeThickness,
509                toolbar_bounds.bottom() - kClientEdgeThickness,
510                w - (2 * kClientEdgeThickness),
511                kClientEdgeThickness),
512      ThemeProperties::GetDefaultColor(
513          ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
514}
515
516void BrowserNonClientFrameViewAsh::PaintContentEdge(gfx::Canvas* canvas) {
517  if (UsePackagedAppHeaderStyle()) {
518    header_painter_->PaintHeaderContentSeparator(canvas);
519  } else {
520    canvas->FillRect(gfx::Rect(0, caption_button_container_->bounds().bottom(),
521                               width(), kClientEdgeThickness),
522        ThemeProperties::GetDefaultColor(
523            ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
524  }
525}
526
527int BrowserNonClientFrameViewAsh::GetThemeFrameImageId() const {
528  bool is_incognito = !browser_view()->IsRegularOrGuestSession();
529  if (browser_view()->IsBrowserTypeNormal()) {
530    // Use the standard resource ids to allow users to theme the frames.
531    if (ShouldPaintAsActive()) {
532      return is_incognito ?
533          IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME;
534    }
535    return is_incognito ?
536        IDR_THEME_FRAME_INCOGNITO_INACTIVE : IDR_THEME_FRAME_INACTIVE;
537  }
538  // Never theme app and popup windows.
539  if (ShouldPaintAsActive()) {
540    return is_incognito ?
541        IDR_AURA_WINDOW_HEADER_BASE_INCOGNITO_ACTIVE :
542        IDR_AURA_WINDOW_HEADER_BASE_ACTIVE;
543  }
544  return is_incognito ?
545      IDR_AURA_WINDOW_HEADER_BASE_INCOGNITO_INACTIVE :
546      IDR_AURA_WINDOW_HEADER_BASE_INACTIVE;
547}
548
549int BrowserNonClientFrameViewAsh::GetThemeFrameOverlayImageId() const {
550  ui::ThemeProvider* tp = GetThemeProvider();
551  if (tp->HasCustomImage(IDR_THEME_FRAME_OVERLAY) &&
552      browser_view()->IsBrowserTypeNormal() &&
553      !browser_view()->IsOffTheRecord()) {
554    return ShouldPaintAsActive() ?
555        IDR_THEME_FRAME_OVERLAY : IDR_THEME_FRAME_OVERLAY_INACTIVE;
556  }
557  return 0;
558}
559