Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / frame / browser_non_client_frame_view_ash.cc
index e61ebe3..c81f1f8 100644 (file)
@@ -4,27 +4,34 @@
 
 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h"
 
-#include "ash/ash_switches.h"
-#include "ash/wm/caption_buttons/frame_caption_button_container_view.h"
-#include "ash/wm/frame_border_hit_test_controller.h"
-#include "ash/wm/header_painter.h"
+#include <algorithm>
+
+#include "ash/frame/caption_buttons/frame_caption_button.h"
+#include "ash/frame/caption_buttons/frame_caption_button_container_view.h"
+#include "ash/frame/default_header_painter.h"
+#include "ash/frame/frame_border_hit_test_controller.h"
+#include "ash/frame/header_painter_util.h"
+#include "ash/shell.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/views/avatar_label.h"
-#include "chrome/browser/ui/views/avatar_menu_button.h"
+#include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/views/frame/browser_frame.h"
+#include "chrome/browser/ui/views/frame/browser_header_painter_ash.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
+#include "chrome/browser/ui/views/profiles/avatar_menu_button.h"
 #include "chrome/browser/ui/views/tab_icon_view.h"
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
+#include "components/signin/core/common/profile_management_switches.h"
 #include "content/public/browser/web_contents.h"
 #include "grit/ash_resources.h"
 #include "grit/theme_resources.h"
+#include "ui/accessibility/ax_view_state.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
-#include "ui/base/accessibility/accessible_view_state.h"
 #include "ui/base/hit_test.h"
-#include "ui/base/l10n/l10n_util.h"
 #include "ui/base/layout.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/theme_provider.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 
+#if defined(ENABLE_MANAGED_USERS)
+#include "chrome/browser/ui/views/profiles/supervised_user_avatar_label.h"
+#endif
+
 namespace {
 
 // The avatar ends 2 px above the bottom of the tabstrip (which, given the
@@ -46,6 +57,8 @@ const int kAvatarBottomSpacing = 2;
 // There are 2 px on each side of the avatar (between the frame border and
 // it on the left, and between it and the tabstrip on the right).
 const int kAvatarSideSpacing = 2;
+// Space between the new avatar button and the minimize button.
+const int kNewAvatarButtonOffset = 5;
 // Space between left edge of window and tabstrip.
 const int kTabstripLeftSpacing = 0;
 // Space between right edge of tabstrip and maximize button.
@@ -63,6 +76,18 @@ const int kTabstripTopSpacingShort = 0;
 // to hit easily.
 const int kTabShadowHeight = 4;
 
+// Combines View::ConvertPointToTarget() and View::HitTest() for a given
+// |point|. Converts |point| from |src| to |dst| and hit tests it against |dst|.
+bool ConvertedHitTest(views::View* src,
+                      views::View* dst,
+                      const gfx::Point& point) {
+  DCHECK(src);
+  DCHECK(dst);
+  gfx::Point converted_point(point);
+  views::View::ConvertPointToTarget(src, dst, &converted_point);
+  return dst->HitTestPoint(converted_point);
+}
+
 }  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -73,21 +98,27 @@ const char BrowserNonClientFrameViewAsh::kViewClassName[] =
     "BrowserNonClientFrameViewAsh";
 
 BrowserNonClientFrameViewAsh::BrowserNonClientFrameViewAsh(
-    BrowserFrame* frame, BrowserView* browser_view)
+    BrowserFrame* frame,
+    BrowserView* browser_view)
     : BrowserNonClientFrameView(frame, browser_view),
       caption_button_container_(NULL),
+      web_app_back_button_(NULL),
       window_icon_(NULL),
-      header_painter_(new ash::HeaderPainter),
       frame_border_hit_test_controller_(
           new ash::FrameBorderHitTestController(frame)) {
+  ash::Shell::GetInstance()->AddShellObserver(this);
 }
 
 BrowserNonClientFrameViewAsh::~BrowserNonClientFrameViewAsh() {
+  ash::Shell::GetInstance()->RemoveShellObserver(this);
+  // browser_view() outlives the frame, as destruction of sibling views happens
+  // in the same order as creation - see BrowserView::CreateBrowserWindow.
+  chrome::RemoveCommandObserver(browser_view()->browser(), IDC_BACK, this);
 }
 
 void BrowserNonClientFrameViewAsh::Init() {
-  caption_button_container_ = new ash::FrameCaptionButtonContainerView(frame(),
-      ash::FrameCaptionButtonContainerView::MINIMIZE_ALLOWED);
+  caption_button_container_ = new ash::FrameCaptionButtonContainerView(frame());
+  caption_button_container_->UpdateSizeButtonVisibility();
   AddChildView(caption_button_container_);
 
   // Initializing the TabIconView is expensive, so only do it if we need to.
@@ -98,15 +129,49 @@ void BrowserNonClientFrameViewAsh::Init() {
     window_icon_->Update();
   }
 
-  // Create incognito icon if necessary.
-  UpdateAvatarInfo();
+  if (browser_view()->IsRegularOrGuestSession() &&
+      switches::IsNewAvatarMenu()) {
+    UpdateNewStyleAvatarInfo(this, NewAvatarButton::NATIVE_BUTTON);
+  } else {
+    UpdateAvatarInfo();
+  }
 
-  // Frame painter handles layout.
-  header_painter_->Init(frame(), this, window_icon_, caption_button_container_);
+  // HeaderPainter handles layout.
+  if (UsePackagedAppHeaderStyle()) {
+    ash::DefaultHeaderPainter* header_painter = new ash::DefaultHeaderPainter;
+    header_painter_.reset(header_painter);
+    header_painter->Init(frame(), this, caption_button_container_);
+    if (window_icon_) {
+      header_painter->UpdateLeftHeaderView(window_icon_);
+    }
+  } else if (UseWebAppHeaderStyle()) {
+    web_app_back_button_ =
+        new ash::FrameCaptionButton(this, ash::CAPTION_BUTTON_ICON_BACK);
+    web_app_back_button_->SetImages(ash::CAPTION_BUTTON_ICON_BACK,
+                                    ash::FrameCaptionButton::ANIMATE_NO,
+                                    IDR_AURA_WINDOW_CONTROL_ICON_BACK,
+                                    IDR_AURA_WINDOW_CONTROL_ICON_BACK_I,
+                                    IDR_AURA_WINDOW_CONTROL_BACKGROUND_H,
+                                    IDR_AURA_WINDOW_CONTROL_BACKGROUND_P);
+
+    UpdateBackButtonState(true);
+    chrome::AddCommandObserver(browser_view()->browser(), IDC_BACK, this);
+    AddChildView(web_app_back_button_);
+
+    ash::DefaultHeaderPainter* header_painter = new ash::DefaultHeaderPainter;
+    header_painter_.reset(header_painter);
+    header_painter->Init(frame(), this, caption_button_container_);
+    header_painter->UpdateLeftHeaderView(web_app_back_button_);
+  } else {
+    BrowserHeaderPainterAsh* header_painter = new BrowserHeaderPainterAsh;
+    header_painter_.reset(header_painter);
+    header_painter->Init(frame(), browser_view(), this, window_icon_,
+        caption_button_container_);
+  }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// BrowserNonClientFrameView overrides:
+// BrowserNonClientFrameView:
 
 gfx::Rect BrowserNonClientFrameViewAsh::GetBoundsForTabStrip(
     views::View* tabstrip) const {
@@ -131,12 +196,15 @@ int BrowserNonClientFrameViewAsh::GetTopInset() const {
     return 0;
 
   if (browser_view()->IsTabStripVisible()) {
-    if (UseShortHeader())
+    if (frame()->IsMaximized() || frame()->IsFullscreen())
       return kTabstripTopSpacingShort;
     else
       return kTabstripTopSpacingTall;
   }
 
+  if (UsePackagedAppHeaderStyle() || UseWebAppHeaderStyle())
+    return header_painter_->GetHeaderHeightForPainting();
+
   int caption_buttons_bottom = caption_button_container_->bounds().bottom();
 
   // The toolbar partially overlaps the caption buttons.
@@ -147,7 +215,7 @@ int BrowserNonClientFrameViewAsh::GetTopInset() const {
 }
 
 int BrowserNonClientFrameViewAsh::GetThemeBackgroundXInset() const {
-  return header_painter_->GetThemeBackgroundXInset();
+  return ash::HeaderPainterUtil::GetThemeBackgroundXInset();
 }
 
 void BrowserNonClientFrameViewAsh::UpdateThrobber(bool running) {
@@ -156,7 +224,7 @@ void BrowserNonClientFrameViewAsh::UpdateThrobber(bool running) {
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// views::NonClientFrameView overrides:
+// views::NonClientFrameView:
 
 gfx::Rect BrowserNonClientFrameViewAsh::GetBoundsForClientView() const {
   // The ClientView must be flush with the top edge of the widget so that the
@@ -165,24 +233,42 @@ gfx::Rect BrowserNonClientFrameViewAsh::GetBoundsForClientView() const {
   // and the top-of-window views are revealed, the TopContainerView paints the
   // window header by redirecting paints from its background to
   // BrowserNonClientFrameViewAsh.
-  return ash::HeaderPainter::GetBoundsForClientView(0, bounds());
+  return bounds();
 }
 
 gfx::Rect BrowserNonClientFrameViewAsh::GetWindowBoundsForClientBounds(
     const gfx::Rect& client_bounds) const {
-  return ash::HeaderPainter::GetWindowBoundsForClientBounds(0, client_bounds);
+  return client_bounds;
 }
 
 int BrowserNonClientFrameViewAsh::NonClientHitTest(const gfx::Point& point) {
   int hit_test = ash::FrameBorderHitTestController::NonClientHitTest(this,
-      header_painter_.get(), point);
+      caption_button_container_, point);
+
+  // See if the point is actually within either of the avatar menu buttons.
+  if (hit_test == HTCAPTION && avatar_button() &&
+      ConvertedHitTest(this, avatar_button(), point)) {
+    return HTCLIENT;
+  }
+
+  if (hit_test == HTCAPTION && new_avatar_button() &&
+      ConvertedHitTest(this, new_avatar_button(), point)) {
+    return HTCLIENT;
+  }
 
-  // See if the point is actually within the avatar menu button or within
-  // the avatar label.
-  if (hit_test == HTCAPTION && ((avatar_button() &&
-       avatar_button()->GetMirroredBounds().Contains(point)) ||
-      (avatar_label() && avatar_label()->GetMirroredBounds().Contains(point))))
-      return HTCLIENT;
+  // See if the point is actually within the web app back button.
+  if (hit_test == HTCAPTION && web_app_back_button_ &&
+      ConvertedHitTest(this, web_app_back_button_, point)) {
+    return HTCLIENT;
+  }
+
+#if defined(ENABLE_MANAGED_USERS)
+  // ...or within the avatar label, if it's a supervised user.
+  if (hit_test == HTCAPTION && supervised_user_avatar_label() &&
+      ConvertedHitTest(this, supervised_user_avatar_label(), point)) {
+    return HTCLIENT;
+  }
+#endif
 
   // When the window is restored we want a large click target above the tabs
   // to drag the window, so redirect clicks in the tab's shadow to caption.
@@ -200,7 +286,7 @@ int BrowserNonClientFrameViewAsh::NonClientHitTest(const gfx::Point& point) {
 }
 
 void BrowserNonClientFrameViewAsh::GetWindowMask(const gfx::Size& size,
-                                                  gfx::Path* window_mask) {
+                                                 gfx::Path* window_mask) {
   // Aura does not use window masks.
 }
 
@@ -221,11 +307,14 @@ void BrowserNonClientFrameViewAsh::UpdateWindowIcon() {
 
 void BrowserNonClientFrameViewAsh::UpdateWindowTitle() {
   if (!frame()->IsFullscreen())
-    header_painter_->SchedulePaintForTitle(BrowserFrame::GetTitleFontList());
+    header_painter_->SchedulePaintForTitle();
+}
+
+void BrowserNonClientFrameViewAsh::SizeConstraintsChanged() {
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// views::View overrides:
+// views::View:
 
 void BrowserNonClientFrameViewAsh::OnPaint(gfx::Canvas* canvas) {
   if (!ShouldPaint())
@@ -236,46 +325,52 @@ void BrowserNonClientFrameViewAsh::OnPaint(gfx::Canvas* canvas) {
     return;
   }
 
-  // The primary header image changes based on window activation state and
-  // theme, so we look it up for each paint.
-  int theme_frame_image_id = GetThemeFrameImageId();
-  int theme_frame_overlay_image_id = GetThemeFrameOverlayImageId();
-
-  ui::ThemeProvider* theme_provider = GetThemeProvider();
-  if (!theme_provider->HasCustomImage(theme_frame_image_id) &&
-      (theme_frame_overlay_image_id == 0 ||
-       !theme_provider->HasCustomImage(theme_frame_overlay_image_id))) {
-    if (frame()->IsMaximized() || frame()->IsFullscreen())
-      theme_frame_image_id = IDR_AURA_WINDOW_HEADER_BASE_MINIMAL;
+  caption_button_container_->SetPaintAsActive(ShouldPaintAsActive());
+  if (web_app_back_button_) {
+    // TODO(benwells): Check that the disabled and inactive states should be
+    // drawn in the same way.
+    web_app_back_button_->set_paint_as_active(
+        ShouldPaintAsActive() &&
+        chrome::IsCommandEnabled(browser_view()->browser(), IDC_BACK));
   }
-  header_painter_->PaintHeader(
-      canvas,
-      theme_frame_image_id,
-      theme_frame_overlay_image_id);
-  if (browser_view()->ShouldShowWindowTitle())
-    header_painter_->PaintTitleBar(canvas, BrowserFrame::GetTitleFontList());
+
+  ash::HeaderPainter::Mode header_mode = ShouldPaintAsActive() ?
+      ash::HeaderPainter::MODE_ACTIVE : ash::HeaderPainter::MODE_INACTIVE;
+  header_painter_->PaintHeader(canvas, header_mode);
   if (browser_view()->IsToolbarVisible())
     PaintToolbarBackground(canvas);
-  else
+  else if (!UsePackagedAppHeaderStyle() && !UseWebAppHeaderStyle())
     PaintContentEdge(canvas);
 }
 
 void BrowserNonClientFrameViewAsh::Layout() {
-  int header_height = 0;
+  // The header must be laid out before computing |painted_height| because the
+  // computation of |painted_height| for app and popup windows depends on the
+  // position of the window controls.
+  header_painter_->LayoutHeader();
+
+  int painted_height = 0;
   if (browser_view()->IsTabStripVisible()) {
-    header_height = GetTopInset() +
+    painted_height = GetTopInset() +
         browser_view()->tabstrip()->GetPreferredSize().height();
   } else if (browser_view()->IsToolbarVisible()) {
-    // Set the header's height so that it overlaps with the toolbar because the
-    // top few pixels of the toolbar are not opaque.
-    header_height = GetTopInset() + kFrameShadowThickness * 2;
+    // Paint the header so that it overlaps with the top few pixels of the
+    // toolbar because the top few pixels of the toolbar are not opaque.
+    painted_height = GetTopInset() + kFrameShadowThickness * 2;
   } else {
-    header_height = GetTopInset();
+    painted_height = GetTopInset();
   }
-  header_painter_->set_header_height(header_height);
-  header_painter_->LayoutHeader(UseShortHeader());
-  if (avatar_button())
+  header_painter_->SetHeaderHeightForPainting(painted_height);
+
+  if (avatar_button()) {
     LayoutAvatar();
+    header_painter_->UpdateLeftViewXInset(avatar_button()->bounds().right());
+  } else {
+    if (new_avatar_button())
+      LayoutNewStyleAvatar();
+    header_painter_->UpdateLeftViewXInset(
+        ash::HeaderPainterUtil::GetDefaultLeftViewXInset());
+  }
   BrowserNonClientFrameView::Layout();
 }
 
@@ -283,38 +378,12 @@ const char* BrowserNonClientFrameViewAsh::GetClassName() const {
   return kViewClassName;
 }
 
-bool BrowserNonClientFrameViewAsh::HitTestRect(const gfx::Rect& rect) const {
-  if (!views::View::HitTestRect(rect)) {
-    // |rect| is outside BrowserNonClientFrameViewAsh's bounds.
-    return false;
-  }
-
-  TabStrip* tabstrip = browser_view()->tabstrip();
-  if (tabstrip && browser_view()->IsTabStripVisible()) {
-    // Claim |rect| only if it is above the bottom of the tabstrip in a non-tab
-    // portion.
-    gfx::RectF rect_in_tabstrip_coords_f(rect);
-    View::ConvertRectToTarget(this, tabstrip, &rect_in_tabstrip_coords_f);
-    gfx::Rect rect_in_tabstrip_coords = gfx::ToEnclosingRect(
-        rect_in_tabstrip_coords_f);
-
-     if (rect_in_tabstrip_coords.y() > tabstrip->height())
-       return false;
-
-    return !tabstrip->HitTestRect(rect_in_tabstrip_coords) ||
-        tabstrip->IsRectInWindowCaption(rect_in_tabstrip_coords);
-  }
-
-  // Claim |rect| if it is above the top of the topmost view in the client area.
-  return rect.y() < GetTopInset();
-}
-
 void BrowserNonClientFrameViewAsh::GetAccessibleState(
-    ui::AccessibleViewState* state) {
-  state->role = ui::AccessibilityTypes::ROLE_TITLEBAR;
+    ui::AXViewState* state) {
+  state->role = ui::AX_ROLE_TITLE_BAR;
 }
 
-gfx::Size BrowserNonClientFrameViewAsh::GetMinimumSize() {
+gfx::Size BrowserNonClientFrameViewAsh::GetMinimumSize() const {
   gfx::Size min_client_view_size(frame()->client_view()->GetMinimumSize());
   int min_width = std::max(header_painter_->GetMinimumHeaderWidth(),
                            min_client_view_size.width());
@@ -329,13 +398,36 @@ gfx::Size BrowserNonClientFrameViewAsh::GetMinimumSize() {
   return gfx::Size(min_width, min_client_view_size.height());
 }
 
-void BrowserNonClientFrameViewAsh::OnThemeChanged() {
-  BrowserNonClientFrameView::OnThemeChanged();
-  header_painter_->OnThemeChanged();
+void BrowserNonClientFrameViewAsh::
+  ChildPreferredSizeChanged(views::View* child) {
+  // FrameCaptionButtonContainerView animates the visibility changes in
+  // UpdateSizeButtonVisibility(false). Due to this a new size is not available
+  // until the completion of the animation. Layout in response to the preferred
+  // size changes.
+  if (child != caption_button_container_)
+    return;
+  frame()->GetRootView()->Layout();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ash::ShellObserver:
+
+void BrowserNonClientFrameViewAsh::OnMaximizeModeStarted() {
+  caption_button_container_->UpdateSizeButtonVisibility();
+  InvalidateLayout();
+  frame()->client_view()->InvalidateLayout();
+  frame()->GetRootView()->Layout();
+}
+
+void BrowserNonClientFrameViewAsh::OnMaximizeModeEnded() {
+  caption_button_container_->UpdateSizeButtonVisibility();
+  InvalidateLayout();
+  frame()->client_view()->InvalidateLayout();
+  frame()->GetRootView()->Layout();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// chrome::TabIconViewModel overrides:
+// chrome::TabIconViewModel:
 
 bool BrowserNonClientFrameViewAsh::ShouldTabIconViewAnimate() const {
   // This function is queried during the creation of the window as the
@@ -353,8 +445,60 @@ gfx::ImageSkia BrowserNonClientFrameViewAsh::GetFaviconForTabIconView() {
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// CommandObserver:
+
+void BrowserNonClientFrameViewAsh::EnabledStateChangedForCommand(int id,
+                                                                 bool enabled) {
+  DCHECK_EQ(IDC_BACK, id);
+  UpdateBackButtonState(enabled);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// views::ButtonListener:
+
+void BrowserNonClientFrameViewAsh::ButtonPressed(views::Button* sender,
+                                                 const ui::Event& event) {
+  if (sender == web_app_back_button_)
+    chrome::ExecuteCommand(browser_view()->browser(), IDC_BACK);
+  else if (sender == new_avatar_button())
+    chrome::ExecuteCommand(browser_view()->browser(), IDC_SHOW_AVATAR_MENU);
+  else
+    NOTREACHED();
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // BrowserNonClientFrameViewAsh, private:
 
+// views::NonClientFrameView:
+bool BrowserNonClientFrameViewAsh::DoesIntersectRect(
+    const views::View* target,
+    const gfx::Rect& rect) const {
+  CHECK_EQ(target, this);
+  if (!views::ViewTargeterDelegate::DoesIntersectRect(this, rect)) {
+    // |rect| is outside BrowserNonClientFrameViewAsh's bounds.
+    return false;
+  }
+
+  TabStrip* tabstrip = browser_view()->tabstrip();
+  if (tabstrip && browser_view()->IsTabStripVisible()) {
+    // Claim |rect| only if it is above the bottom of the tabstrip in a non-tab
+    // portion.
+    gfx::RectF rect_in_tabstrip_coords_f(rect);
+    View::ConvertRectToTarget(this, tabstrip, &rect_in_tabstrip_coords_f);
+    gfx::Rect rect_in_tabstrip_coords = gfx::ToEnclosingRect(
+        rect_in_tabstrip_coords_f);
+
+     if (rect_in_tabstrip_coords.y() > tabstrip->height())
+       return false;
+
+    return !tabstrip->HitTestRect(rect_in_tabstrip_coords) ||
+        tabstrip->IsRectInWindowCaption(rect_in_tabstrip_coords);
+  }
+
+  // Claim |rect| if it is above the top of the topmost view in the client area.
+  return rect.y() < GetTopInset();
+}
+
 int BrowserNonClientFrameViewAsh::GetTabStripLeftInset() const {
   return avatar_button() ? kAvatarSideSpacing +
       browser_view()->GetOTRAvatarIcon().width() + kAvatarSideSpacing :
@@ -362,15 +506,12 @@ int BrowserNonClientFrameViewAsh::GetTabStripLeftInset() const {
 }
 
 int BrowserNonClientFrameViewAsh::GetTabStripRightInset() const {
-  return header_painter_->GetRightInset() + kTabstripRightSpacing;
-}
+  int tabstrip_width = kTabstripRightSpacing +
+      caption_button_container_->GetPreferredSize().width();
 
-bool BrowserNonClientFrameViewAsh::UseShortHeader() const {
-  // Restored browser windows use the tall header. All other windows use the
-  // short header.
-  return frame()->IsMaximized() ||
-         frame()->IsFullscreen() ||
-         browser_view()->browser()->is_app();
+  return new_avatar_button() ? kNewAvatarButtonOffset +
+      new_avatar_button()->GetPreferredSize().width() + tabstrip_width :
+      tabstrip_width;
 }
 
 bool BrowserNonClientFrameViewAsh::UseImmersiveLightbarHeaderStyle() const {
@@ -381,15 +522,33 @@ bool BrowserNonClientFrameViewAsh::UseImmersiveLightbarHeaderStyle() const {
       browser_view()->IsTabStripVisible();
 }
 
+bool BrowserNonClientFrameViewAsh::UsePackagedAppHeaderStyle() const {
+  // Use the packaged app style for apps that aren't using the newer WebApp
+  // style.
+  return browser_view()->browser()->is_app() && !UseWebAppHeaderStyle();
+}
+
+bool BrowserNonClientFrameViewAsh::UseWebAppHeaderStyle() const {
+  // Use of the experimental WebApp header style is guarded with the
+  // streamlined hosted app style.
+  return browser_view()->browser()->is_app() &&
+         extensions::util::IsStreamlinedHostedAppsEnabled();
+}
+
 void BrowserNonClientFrameViewAsh::LayoutAvatar() {
   DCHECK(avatar_button());
+#if !defined(OS_CHROMEOS)
+  // ChromeOS shows avatar on V1 app.
   DCHECK(browser_view()->IsTabStripVisible());
+#endif
   gfx::ImageSkia incognito_icon = browser_view()->GetOTRAvatarIcon();
 
   int avatar_bottom = GetTopInset() +
       browser_view()->GetTabStripHeight() - kAvatarBottomSpacing;
   int avatar_restored_y = avatar_bottom - incognito_icon.height();
-  int avatar_y = (frame()->IsMaximized() || frame()->IsFullscreen()) ?
+  int avatar_y =
+      (browser_view()->IsTabStripVisible() &&
+       (frame()->IsMaximized() || frame()->IsFullscreen())) ?
       GetTopInset() + kContentShadowHeight : avatar_restored_y;
 
   // Hide the incognito icon in immersive fullscreen when the tab light bar is
@@ -406,6 +565,23 @@ void BrowserNonClientFrameViewAsh::LayoutAvatar() {
   avatar_button()->SetVisible(avatar_visible);
 }
 
+void BrowserNonClientFrameViewAsh::LayoutNewStyleAvatar() {
+  DCHECK(switches::IsNewAvatarMenu());
+  if (!new_avatar_button())
+    return;
+
+  gfx::Size button_size = new_avatar_button()->GetPreferredSize();
+  int button_x = width() -
+      caption_button_container_->GetPreferredSize().width() -
+      kNewAvatarButtonOffset - button_size.width();
+
+  new_avatar_button()->SetBounds(
+      button_x,
+      0,
+      button_size.width(),
+      caption_button_container_->GetPreferredSize().height());
+}
+
 bool BrowserNonClientFrameViewAsh::ShouldPaint() const {
   if (!frame()->IsFullscreen())
     return true;
@@ -423,9 +599,9 @@ bool BrowserNonClientFrameViewAsh::ShouldPaint() const {
 void BrowserNonClientFrameViewAsh::PaintImmersiveLightbarStyleHeader(
     gfx::Canvas* canvas) {
   // The light bar header is not themed because theming it does not look good.
-  gfx::ImageSkia* frame_image = GetThemeProvider()->GetImageSkiaNamed(
-      IDR_AURA_WINDOW_HEADER_BASE_MINIMAL);
-  canvas->TileImageInt(*frame_image, 0, 0, width(), frame_image->height());
+  canvas->FillRect(
+      gfx::Rect(width(), header_painter_->GetHeaderHeightForPainting()),
+      SK_ColorBLACK);
 }
 
 void BrowserNonClientFrameViewAsh::PaintToolbarBackground(gfx::Canvas* canvas) {
@@ -503,41 +679,14 @@ void BrowserNonClientFrameViewAsh::PaintToolbarBackground(gfx::Canvas* canvas) {
 }
 
 void BrowserNonClientFrameViewAsh::PaintContentEdge(gfx::Canvas* canvas) {
+  DCHECK(!UsePackagedAppHeaderStyle() && !UseWebAppHeaderStyle());
   canvas->FillRect(gfx::Rect(0, caption_button_container_->bounds().bottom(),
                              width(), kClientEdgeThickness),
-      ThemeProperties::GetDefaultColor(
-          ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
+                   ThemeProperties::GetDefaultColor(
+                       ThemeProperties::COLOR_TOOLBAR_SEPARATOR));
 }
 
-int BrowserNonClientFrameViewAsh::GetThemeFrameImageId() const {
-  bool is_incognito = !browser_view()->IsRegularOrGuestSession();
-  if (browser_view()->IsBrowserTypeNormal()) {
-    // Use the standard resource ids to allow users to theme the frames.
-    if (ShouldPaintAsActive()) {
-      return is_incognito ?
-          IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME;
-    }
-    return is_incognito ?
-        IDR_THEME_FRAME_INCOGNITO_INACTIVE : IDR_THEME_FRAME_INACTIVE;
-  }
-  // Never theme app and popup windows.
-  if (ShouldPaintAsActive()) {
-    return is_incognito ?
-        IDR_AURA_WINDOW_HEADER_BASE_INCOGNITO_ACTIVE :
-        IDR_AURA_WINDOW_HEADER_BASE_ACTIVE;
-  }
-  return is_incognito ?
-      IDR_AURA_WINDOW_HEADER_BASE_INCOGNITO_INACTIVE :
-      IDR_AURA_WINDOW_HEADER_BASE_INACTIVE;
-}
-
-int BrowserNonClientFrameViewAsh::GetThemeFrameOverlayImageId() const {
-  ui::ThemeProvider* tp = GetThemeProvider();
-  if (tp->HasCustomImage(IDR_THEME_FRAME_OVERLAY) &&
-      browser_view()->IsBrowserTypeNormal() &&
-      !browser_view()->IsOffTheRecord()) {
-    return ShouldPaintAsActive() ?
-        IDR_THEME_FRAME_OVERLAY : IDR_THEME_FRAME_OVERLAY_INACTIVE;
-  }
-  return 0;
+void BrowserNonClientFrameViewAsh::UpdateBackButtonState(bool enabled) {
+  web_app_back_button_->SetState(enabled ? views::Button::STATE_NORMAL
+                                         : views::Button::STATE_DISABLED);
 }