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