Draw classic theme frame header in CrOS without use of assets

BUG=584386

Review URL: https://codereview.chromium.org/1676443002

Cr-Commit-Position: refs/heads/master@{#374429}
diff --git a/chrome/app/theme/default_100_percent/common/ash/theme_frame_active.png b/chrome/app/theme/default_100_percent/common/ash/theme_frame_active.png
deleted file mode 100644
index cb28a18..0000000
--- a/chrome/app/theme/default_100_percent/common/ash/theme_frame_active.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/ash/theme_frame_inactive.png b/chrome/app/theme/default_100_percent/common/ash/theme_frame_inactive.png
deleted file mode 100644
index a091c39..0000000
--- a/chrome/app/theme/default_100_percent/common/ash/theme_frame_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/ash/theme_frame_incognito_active.png b/chrome/app/theme/default_100_percent/common/ash/theme_frame_incognito_active.png
deleted file mode 100644
index 562b7006..0000000
--- a/chrome/app/theme/default_100_percent/common/ash/theme_frame_incognito_active.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/ash/theme_frame_incognito_inactive.png b/chrome/app/theme/default_100_percent/common/ash/theme_frame_incognito_inactive.png
deleted file mode 100644
index 03aa8df..0000000
--- a/chrome/app/theme/default_100_percent/common/ash/theme_frame_incognito_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/ash/theme_frame_active.png b/chrome/app/theme/default_200_percent/common/ash/theme_frame_active.png
deleted file mode 100644
index 25af833..0000000
--- a/chrome/app/theme/default_200_percent/common/ash/theme_frame_active.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/ash/theme_frame_inactive.png b/chrome/app/theme/default_200_percent/common/ash/theme_frame_inactive.png
deleted file mode 100644
index 0621c9c5..0000000
--- a/chrome/app/theme/default_200_percent/common/ash/theme_frame_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/ash/theme_frame_incognito_active.png b/chrome/app/theme/default_200_percent/common/ash/theme_frame_incognito_active.png
deleted file mode 100644
index 08538659..0000000
--- a/chrome/app/theme/default_200_percent/common/ash/theme_frame_incognito_active.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/ash/theme_frame_incognito_inactive.png b/chrome/app/theme/default_200_percent/common/ash/theme_frame_incognito_inactive.png
deleted file mode 100644
index 4ab1f86..0000000
--- a/chrome/app/theme/default_200_percent/common/ash/theme_frame_incognito_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/material_100_percent/common/ash/theme_frame_active.png b/chrome/app/theme/material_100_percent/common/ash/theme_frame_active.png
deleted file mode 100644
index d3ca6df..0000000
--- a/chrome/app/theme/material_100_percent/common/ash/theme_frame_active.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/material_100_percent/common/ash/theme_frame_inactive.png b/chrome/app/theme/material_100_percent/common/ash/theme_frame_inactive.png
deleted file mode 100644
index 168adfe..0000000
--- a/chrome/app/theme/material_100_percent/common/ash/theme_frame_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/material_100_percent/common/ash/theme_frame_incognito_active.png b/chrome/app/theme/material_100_percent/common/ash/theme_frame_incognito_active.png
deleted file mode 100644
index 0aa348e0..0000000
--- a/chrome/app/theme/material_100_percent/common/ash/theme_frame_incognito_active.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/material_100_percent/common/ash/theme_frame_incognito_inactive.png b/chrome/app/theme/material_100_percent/common/ash/theme_frame_incognito_inactive.png
deleted file mode 100644
index e16113d..0000000
--- a/chrome/app/theme/material_100_percent/common/ash/theme_frame_incognito_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/material_200_percent/common/ash/theme_frame_active.png b/chrome/app/theme/material_200_percent/common/ash/theme_frame_active.png
deleted file mode 100644
index bae3dee..0000000
--- a/chrome/app/theme/material_200_percent/common/ash/theme_frame_active.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/material_200_percent/common/ash/theme_frame_inactive.png b/chrome/app/theme/material_200_percent/common/ash/theme_frame_inactive.png
deleted file mode 100644
index 607b687..0000000
--- a/chrome/app/theme/material_200_percent/common/ash/theme_frame_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/material_200_percent/common/ash/theme_frame_incognito_active.png b/chrome/app/theme/material_200_percent/common/ash/theme_frame_incognito_active.png
deleted file mode 100644
index 7ab1c27..0000000
--- a/chrome/app/theme/material_200_percent/common/ash/theme_frame_incognito_active.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/material_200_percent/common/ash/theme_frame_incognito_inactive.png b/chrome/app/theme/material_200_percent/common/ash/theme_frame_incognito_inactive.png
deleted file mode 100644
index cbe79f0..0000000
--- a/chrome/app/theme/material_200_percent/common/ash/theme_frame_incognito_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index f6f79ff1..48b8755b 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -846,11 +846,10 @@
         <structure type="chrome_scaled_image" name="IDR_THEME_FRAME_INCOGNITO_INACTIVE" file="theme_frame_incognito_inactive.png" />
       </if>
       <if expr="use_ash">
-        <!-- Ash has a gray frame, Windows uses blue. -->
-        <structure type="chrome_scaled_image" name="IDR_THEME_FRAME" file="common/ash/theme_frame_active.png" />
-        <structure type="chrome_scaled_image" name="IDR_THEME_FRAME_INACTIVE" file="common/ash/theme_frame_inactive.png" />
-        <structure type="chrome_scaled_image" name="IDR_THEME_FRAME_INCOGNITO" file="common/ash/theme_frame_incognito_active.png" />
-        <structure type="chrome_scaled_image" name="IDR_THEME_FRAME_INCOGNITO_INACTIVE" file="common/ash/theme_frame_incognito_inactive.png" />
+        <structure type="chrome_scaled_image" name="IDR_THEME_FRAME" file="notused.png" />
+        <structure type="chrome_scaled_image" name="IDR_THEME_FRAME_INACTIVE" file="notused.png" />
+        <structure type="chrome_scaled_image" name="IDR_THEME_FRAME_INCOGNITO" file="notused.png" />
+        <structure type="chrome_scaled_image" name="IDR_THEME_FRAME_INCOGNITO_INACTIVE" file="notused.png" />
       </if>
       <structure type="chrome_scaled_image" name="IDR_THEME_FRAME_OVERLAY" file="notused.png" />
       <structure type="chrome_scaled_image" name="IDR_THEME_FRAME_OVERLAY_INACTIVE" file="notused.png" />
diff --git a/chrome/browser/themes/theme_properties.cc b/chrome/browser/themes/theme_properties.cc
index 04c82b0d..8500f131 100644
--- a/chrome/browser/themes/theme_properties.cc
+++ b/chrome/browser/themes/theme_properties.cc
@@ -26,9 +26,9 @@
 #if defined(OS_CHROMEOS)
 // Used for theme fallback colors.
 const SkColor kDefaultColorFrame[] = {
-    SkColorSetRGB(109, 109, 109), SkColorSetRGB(204, 204, 204)};
+    SkColorSetRGB(0xC3, 0xC3, 0xC4), SkColorSetRGB(204, 204, 204)};
 const SkColor kDefaultColorFrameInactive[] = {
-    SkColorSetRGB(176, 176, 176), SkColorSetRGB(220, 220, 220)};
+    SkColorSetRGB(0xCD, 0xCD, 0xCE), SkColorSetRGB(220, 220, 220)};
 #elif defined(OS_MACOSX)
 const SkColor kDefaultColorFrame = SkColorSetRGB(224, 224, 224);
 const SkColor kDefaultColorFrameInactive = SkColorSetRGB(246, 246, 246);
@@ -37,10 +37,19 @@
 const SkColor kDefaultColorFrameInactive = SkColorSetRGB(161, 182, 228);
 #endif  // OS_CHROMEOS
 
-const SkColor kDefaultColorFrameIncognito[] = {
-    SkColorSetRGB(83, 106, 139), SkColorSetRGB(160, 160, 162)};
+// These colors are the same between CrOS and !CrOS for MD, so this ifdef can be
+// removed when we stop supporting pre-MD.
+#if defined(OS_CHROMEOS)
+const SkColor kDefaultColorFrameIncognito[] = {SkColorSetRGB(0xA0, 0xA0, 0xA4),
+                                               SkColorSetRGB(0x28, 0x2B, 0x2D)};
 const SkColor kDefaultColorFrameIncognitoInactive[] = {
-    SkColorSetRGB(126, 139, 156), SkColorSetRGB(120, 120, 122)};
+    SkColorSetRGB(0xAA, 0xAA, 0xAE), SkColorSetRGB(0x14, 0x17, 0x19)};
+#else
+const SkColor kDefaultColorFrameIncognito[] = {SkColorSetRGB(83, 106, 139),
+                                               SkColorSetRGB(0x28, 0x2B, 0x2D)};
+const SkColor kDefaultColorFrameIncognitoInactive[] = {
+    SkColorSetRGB(126, 139, 156), SkColorSetRGB(0x14, 0x17, 0x19)};
+#endif
 
 #if defined(OS_MACOSX)
 const SkColor kDefaultColorToolbar = SkColorSetRGB(230, 230, 230);
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc
index 0221a2be..77c20b8 100644
--- a/chrome/browser/themes/theme_service.cc
+++ b/chrome/browser/themes/theme_service.cc
@@ -167,7 +167,7 @@
       installed_pending_load_id_(kDefaultThemeID),
       number_of_infobars_(0),
       original_theme_provider_(*this, false),
-      otr_theme_provider_(*this, true),
+      incognito_theme_provider_(*this, true),
       weak_ptr_factory_(this) {}
 
 ThemeService::~ThemeService() {
@@ -339,14 +339,14 @@
   return profile_->GetPrefs()->GetString(prefs::kCurrentThemeID);
 }
 
-color_utils::HSL ThemeService::GetTint(int id, bool otr) const {
+color_utils::HSL ThemeService::GetTint(int id, bool incognito) const {
   DCHECK(CalledOnValidThread());
 
   color_utils::HSL hsl;
   if (theme_supplier_ && theme_supplier_->GetTint(id, &hsl))
     return hsl;
 
-  return ThemeProperties::GetDefaultTint(id, otr);
+  return ThemeProperties::GetDefaultTint(id, incognito);
 }
 
 void ThemeService::ClearAllThemeData() {
@@ -443,8 +443,8 @@
   return UsingDefaultTheme();
 }
 
-gfx::ImageSkia* ThemeService::GetImageSkiaNamed(int id) const {
-  gfx::Image image = GetImageNamed(id);
+gfx::ImageSkia* ThemeService::GetImageSkiaNamed(int id, bool incognito) const {
+  gfx::Image image = GetImageNamed(id, incognito);
   if (image.IsEmpty())
     return nullptr;
   // TODO(pkotwicz): Remove this const cast.  The gfx::Image interface returns
@@ -452,13 +452,13 @@
   return const_cast<gfx::ImageSkia*>(image.ToImageSkia());
 }
 
-SkColor ThemeService::GetColor(int id, bool otr) const {
+SkColor ThemeService::GetColor(int id, bool incognito) const {
   DCHECK(CalledOnValidThread());
 
   // For legacy reasons, |theme_supplier_| requires the incognito variants
   // of color IDs.
   int theme_supplier_id = id;
-  if (otr) {
+  if (incognito) {
     if (id == ThemeProperties::COLOR_FRAME)
       theme_supplier_id = ThemeProperties::COLOR_FRAME_INCOGNITO;
     else if (id == ThemeProperties::COLOR_FRAME_INACTIVE)
@@ -476,36 +476,38 @@
       ThemeProperties::COLOR_SUPERVISED_USER_LABEL_BACKGROUND;
   switch (id) {
     case ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON:
-      return color_utils::HSLShift(gfx::kChromeIconGrey,
-                                   GetTint(ThemeProperties::TINT_BUTTONS, otr));
+      return color_utils::HSLShift(
+          gfx::kChromeIconGrey,
+          GetTint(ThemeProperties::TINT_BUTTONS, incognito));
     case ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON_INACTIVE:
       // The active color is overridden in Gtk2UI.
       return SkColorSetA(
-          GetColor(ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON, otr), 0x33);
+          GetColor(ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON, incognito),
+          0x33);
     case ThemeProperties::COLOR_BACKGROUND_TAB:
       return color_utils::HSLShift(
-          GetColor(ThemeProperties::COLOR_TOOLBAR, otr),
-          GetTint(ThemeProperties::TINT_BACKGROUND_TAB, otr));
+          GetColor(ThemeProperties::COLOR_TOOLBAR, incognito),
+          GetTint(ThemeProperties::TINT_BACKGROUND_TAB, incognito));
     case ThemeProperties::COLOR_DETACHED_BOOKMARK_BAR_BACKGROUND:
       if (UsingDefaultTheme())
         break;
-      return GetColor(ThemeProperties::COLOR_TOOLBAR, otr);
+      return GetColor(ThemeProperties::COLOR_TOOLBAR, incognito);
     case ThemeProperties::COLOR_DETACHED_BOOKMARK_BAR_SEPARATOR:
       if (UsingDefaultTheme())
         break;
       // Use 50% of bookmark text color as separator color.
-      return SkColorSetA(GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT, otr),
-                         128);
+      return SkColorSetA(
+          GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT, incognito), 128);
     case ThemeProperties::COLOR_NTP_SECTION_HEADER_TEXT:
-      return IncreaseLightness(GetColor(kNtpText, otr), 0.30);
+      return IncreaseLightness(GetColor(kNtpText, incognito), 0.30);
     case ThemeProperties::COLOR_NTP_SECTION_HEADER_TEXT_HOVER:
-      return GetColor(kNtpText, otr);
+      return GetColor(kNtpText, incognito);
     case ThemeProperties::COLOR_NTP_SECTION_HEADER_RULE:
-      return IncreaseLightness(GetColor(kNtpText, otr), 0.70);
+      return IncreaseLightness(GetColor(kNtpText, incognito), 0.70);
     case ThemeProperties::COLOR_NTP_SECTION_HEADER_RULE_LIGHT:
-      return IncreaseLightness(GetColor(kNtpText, otr), 0.86);
+      return IncreaseLightness(GetColor(kNtpText, incognito), 0.86);
     case ThemeProperties::COLOR_NTP_TEXT_LIGHT:
-      return IncreaseLightness(GetColor(kNtpText, otr), 0.40);
+      return IncreaseLightness(GetColor(kNtpText, incognito), 0.40);
     case ThemeProperties::COLOR_TAB_THROBBER_SPINNING:
     case ThemeProperties::COLOR_TAB_THROBBER_WAITING: {
       SkColor base_color =
@@ -513,18 +515,18 @@
                                ? ui::NativeTheme::kColorId_ThrobberSpinningColor
                                : ui::NativeTheme::kColorId_ThrobberWaitingColor,
                            nullptr);
-      color_utils::HSL hsl = GetTint(ThemeProperties::TINT_BUTTONS, otr);
+      color_utils::HSL hsl = GetTint(ThemeProperties::TINT_BUTTONS, incognito);
       return color_utils::HSLShift(base_color, hsl);
     }
 #if defined(ENABLE_SUPERVISED_USERS)
     case ThemeProperties::COLOR_SUPERVISED_USER_LABEL:
-      return color_utils::GetReadableColor(SK_ColorWHITE,
-                                           GetColor(kLabelBackground, otr));
+      return color_utils::GetReadableColor(
+          SK_ColorWHITE, GetColor(kLabelBackground, incognito));
     case ThemeProperties::COLOR_SUPERVISED_USER_LABEL_BACKGROUND:
       return color_utils::BlendTowardOppositeLuminance(
-          GetColor(ThemeProperties::COLOR_FRAME, otr), 0x80);
+          GetColor(ThemeProperties::COLOR_FRAME, incognito), 0x80);
     case ThemeProperties::COLOR_SUPERVISED_USER_LABEL_BORDER:
-      return color_utils::AlphaBlend(GetColor(kLabelBackground, otr),
+      return color_utils::AlphaBlend(GetColor(kLabelBackground, incognito),
                                      SK_ColorBLACK, 230);
 #endif
     case ThemeProperties::COLOR_STATUS_BAR_TEXT: {
@@ -533,8 +535,9 @@
       // views couldn't do alpha blending. Even though this is no longer the
       // case, this blending decision is built into the majority of themes that
       // exist, and we must keep doing it.
-      SkColor toolbar_color = GetColor(ThemeProperties::COLOR_TOOLBAR, otr);
-      SkColor text_color = GetColor(ThemeProperties::COLOR_TAB_TEXT, otr);
+      SkColor toolbar_color =
+          GetColor(ThemeProperties::COLOR_TOOLBAR, incognito);
+      SkColor text_color = GetColor(ThemeProperties::COLOR_TAB_TEXT, incognito);
       return SkColorSetARGB(
           SkColorGetA(text_color),
           (SkColorGetR(text_color) + SkColorGetR(toolbar_color)) / 2,
@@ -543,7 +546,7 @@
     }
   }
 
-  return ThemeProperties::GetDefaultColor(id, otr);
+  return ThemeProperties::GetDefaultColor(id, incognito);
 }
 
 int ThemeService::GetDisplayProperty(int id) const {
@@ -605,15 +608,23 @@
   return data;
 }
 
-gfx::Image ThemeService::GetImageNamed(int id) const {
+gfx::Image ThemeService::GetImageNamed(int id, bool incognito) const {
   DCHECK(CalledOnValidThread());
 
+  int adjusted_id = id;
+  if (incognito) {
+    if (id == IDR_THEME_FRAME)
+      adjusted_id = IDR_THEME_FRAME_INCOGNITO;
+    else if (id == IDR_THEME_FRAME_INACTIVE)
+      adjusted_id = IDR_THEME_FRAME_INCOGNITO_INACTIVE;
+  }
+
   gfx::Image image;
   if (theme_supplier_)
-    image = theme_supplier_->GetImageNamed(id);
+    image = theme_supplier_->GetImageNamed(adjusted_id);
 
   if (image.IsEmpty())
-    image = rb_.GetNativeImageNamed(id);
+    image = rb_.GetNativeImageNamed(adjusted_id);
 
   return image;
 }
@@ -748,7 +759,7 @@
 #else
   bool incognito = profile->GetProfileType() == Profile::INCOGNITO_PROFILE;
 #endif
-  return incognito ? service->otr_theme_provider_
+  return incognito ? service->incognito_theme_provider_
                    : service->original_theme_provider_;
 }
 
@@ -761,7 +772,7 @@
 
 gfx::ImageSkia* ThemeService::BrowserThemeProvider::GetImageSkiaNamed(
     int id) const {
-  return theme_service_.GetImageSkiaNamed(id);
+  return theme_service_.GetImageSkiaNamed(id, incognito_);
 }
 
 SkColor ThemeService::BrowserThemeProvider::GetColor(int id) const {
diff --git a/chrome/browser/themes/theme_service.h b/chrome/browser/themes/theme_service.h
index 04442b2..cabfefe 100644
--- a/chrome/browser/themes/theme_service.h
+++ b/chrome/browser/themes/theme_service.h
@@ -137,7 +137,7 @@
   virtual bool ShouldInitWithSystemTheme() const;
 
   // Get the specified tint - |id| is one of the TINT_* enum values.
-  color_utils::HSL GetTint(int id, bool otr) const;
+  color_utils::HSL GetTint(int id, bool incognito) const;
 
   // Clears all the override fields and saves the dictionary.
   virtual void ClearAllThemeData();
@@ -208,7 +208,7 @@
 
   // These methods provide the implementation for ui::ThemeProvider (exposed
   // via BrowserThemeProvider).
-  gfx::ImageSkia* GetImageSkiaNamed(int id) const;
+  gfx::ImageSkia* GetImageSkiaNamed(int id, bool incognito) const;
   SkColor GetColor(int id, bool incognito) const;
   int GetDisplayProperty(int id) const;
   bool ShouldUseNativeFrame() const;
@@ -227,7 +227,7 @@
   //
   // TODO(erg): Make this part of the ui::ThemeProvider and the main way to get
   // theme properties out of the theme provider since it's cross platform.
-  gfx::Image GetImageNamed(int id) const;
+  gfx::Image GetImageNamed(int id, bool incognito) const;
 
   // Called when the extension service is ready.
   void OnExtensionServiceReady();
@@ -297,7 +297,7 @@
 #endif
 
   BrowserThemeProvider original_theme_provider_;
-  BrowserThemeProvider otr_theme_provider_;
+  BrowserThemeProvider incognito_theme_provider_;
 
   base::WeakPtrFactory<ThemeService> weak_ptr_factory_;
 
diff --git a/chrome/browser/ui/views/frame/browser_header_painter_ash.cc b/chrome/browser/ui/views/frame/browser_header_painter_ash.cc
index 33bbabe..bf27474 100644
--- a/chrome/browser/ui/views/frame/browser_header_painter_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_header_painter_ash.cc
@@ -8,13 +8,13 @@
 #include "ash/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/frame/header_painter_util.h"
 #include "base/logging.h"  // DCHECK
+#include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/frame/browser_frame.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "grit/ash_resources.h"
 #include "grit/theme_resources.h"
 #include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkPaint.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "ui/base/material_design/material_design_controller.h"
@@ -38,15 +38,10 @@
 // Duration of crossfade animation for activating and deactivating frame.
 const int kActivationCrossfadeDurationMs = 200;
 
-// Tiles an image into an area, rounding the top corners. Samples |image|
-// starting |image_inset_x| pixels from the left of the image.
-void TileRoundRect(gfx::Canvas* canvas,
-                   const gfx::ImageSkia& image,
-                   const SkPaint& paint,
-                   const gfx::Rect& bounds,
-                   int top_left_corner_radius,
-                   int top_right_corner_radius,
-                   int image_inset_x) {
+// Creates a path with rounded top corners.
+SkPath MakeRoundRectPath(const gfx::Rect& bounds,
+                         int top_left_corner_radius,
+                         int top_right_corner_radius) {
   SkRect rect = gfx::RectToSkRect(bounds);
   const SkScalar kTopLeftRadius = SkIntToScalar(top_left_corner_radius);
   const SkScalar kTopRightRadius = SkIntToScalar(top_right_corner_radius);
@@ -57,7 +52,7 @@
       0, 0};  // bottom-left
   SkPath path;
   path.addRoundRect(rect, radii, SkPath::kCW_Direction);
-  canvas->DrawImageInPath(image, -image_inset_x, 0, path, paint);
+  return path;
 }
 
 // Tiles |frame_image| and |frame_overlay_image| into an area, rounding the top
@@ -69,19 +64,23 @@
                                  const gfx::Rect& bounds,
                                  int corner_radius,
                                  int image_inset_x) {
-  SkXfermode::Mode normal_mode;
-  SkXfermode::AsMode(nullptr, &normal_mode);
-
+  SkPath frame_path = MakeRoundRectPath(bounds, corner_radius, corner_radius);
   // If |paint| is using an unusual SkXfermode::Mode (this is the case while
   // crossfading), we must create a new canvas to overlay |frame_image| and
   // |frame_overlay_image| using |normal_mode| and then paint the result
   // using the unusual mode. We try to avoid this because creating a new
   // browser-width canvas is expensive.
+  SkXfermode::Mode normal_mode;
+  SkXfermode::AsMode(nullptr, &normal_mode);
   bool fast_path = (frame_overlay_image.isNull() ||
       SkXfermode::IsMode(paint.getXfermode(), normal_mode));
   if (fast_path) {
-    TileRoundRect(canvas, frame_image, paint, bounds, corner_radius,
-        corner_radius, image_inset_x);
+    if (frame_image.isNull()) {
+      canvas->DrawPath(frame_path, paint);
+    } else {
+      canvas->DrawImageInPath(frame_image, -image_inset_x, 0, frame_path,
+                              paint);
+    }
 
     if (!frame_overlay_image.isNull()) {
       // Adjust |bounds| such that |frame_overlay_image| is not tiled.
@@ -92,18 +91,23 @@
       int top_right_corner_radius = corner_radius;
       if (overlay_bounds.width() < bounds.width() - corner_radius)
         top_right_corner_radius = 0;
-      TileRoundRect(canvas, frame_overlay_image, paint, overlay_bounds,
-          top_left_corner_radius, top_right_corner_radius, 0);
+      canvas->DrawImageInPath(
+          frame_overlay_image, 0, 0,
+          MakeRoundRectPath(overlay_bounds, top_left_corner_radius,
+                            top_right_corner_radius),
+          paint);
     }
   } else {
     gfx::Canvas temporary_canvas(bounds.size(), canvas->image_scale(), false);
-    temporary_canvas.TileImageInt(frame_image,
-                                  image_inset_x, 0,
-                                  0, 0,
-                                  bounds.width(), bounds.height());
+    if (frame_image.isNull()) {
+      temporary_canvas.DrawColor(paint.getColor());
+    } else {
+      temporary_canvas.TileImageInt(frame_image, image_inset_x, 0, 0, 0,
+                                    bounds.width(), bounds.height());
+    }
     temporary_canvas.DrawImageInt(frame_overlay_image, 0, 0);
-    TileRoundRect(canvas, gfx::ImageSkia(temporary_canvas.ExtractImageRep()),
-        paint, bounds, corner_radius, corner_radius, 0);
+    canvas->DrawImageInPath(gfx::ImageSkia(temporary_canvas.ExtractImageRep()),
+                            0, 0, frame_path, paint);
   }
 }
 
@@ -192,29 +196,25 @@
     if (active_alpha > 0)
       paint.setXfermodeMode(SkXfermode::kPlus_Mode);
 
-    gfx::ImageSkia inactive_frame_image;
-    gfx::ImageSkia inactive_frame_overlay_image;
-    GetFrameImages(MODE_INACTIVE, &inactive_frame_image,
-        &inactive_frame_overlay_image);
+    gfx::ImageSkia inactive_frame_image = GetFrameImage(MODE_INACTIVE);
+    gfx::ImageSkia inactive_frame_overlay_image =
+        GetFrameOverlayImage(MODE_INACTIVE);
 
     paint.setAlpha(inactive_alpha);
+    paint.setColor(SkColorSetA(GetFrameColor(MODE_INACTIVE), inactive_alpha));
     PaintFrameImagesInRoundRect(
-        canvas,
-        inactive_frame_image,
-        inactive_frame_overlay_image,
-        paint,
-        GetPaintedBounds(),
-        corner_radius,
+        canvas, inactive_frame_image, inactive_frame_overlay_image, paint,
+        GetPaintedBounds(), corner_radius,
         ash::HeaderPainterUtil::GetThemeBackgroundXInset());
   }
 
   if (active_alpha > 0) {
-    gfx::ImageSkia active_frame_image;
-    gfx::ImageSkia active_frame_overlay_image;
-    GetFrameImages(MODE_ACTIVE, &active_frame_image,
-        &active_frame_overlay_image);
+    gfx::ImageSkia active_frame_image = GetFrameImage(MODE_ACTIVE);
+    gfx::ImageSkia active_frame_overlay_image =
+        GetFrameOverlayImage(MODE_ACTIVE);
 
     paint.setAlpha(active_alpha);
+    paint.setColor(SkColorSetA(GetFrameColor(MODE_ACTIVE), active_alpha));
     PaintFrameImagesInRoundRect(
         canvas,
         active_frame_image,
@@ -353,55 +353,41 @@
                                   gfx::Canvas::NO_SUBPIXEL_RENDERING);
 }
 
-void BrowserHeaderPainterAsh::GetFrameImages(
-    Mode mode,
-    gfx::ImageSkia* frame_image,
-    gfx::ImageSkia* frame_overlay_image) const {
-  if (is_tabbed_) {
-    GetFrameImagesForTabbedBrowser(mode, frame_image, frame_overlay_image);
-  } else {
-    *frame_image = GetFrameImageForNonTabbedBrowser(mode);
-    *frame_overlay_image = gfx::ImageSkia();
-  }
-}
-
-void BrowserHeaderPainterAsh::GetFrameImagesForTabbedBrowser(
-    Mode mode,
-    gfx::ImageSkia* frame_image,
-    gfx::ImageSkia* frame_overlay_image) const {
-  int frame_image_id = 0;
-  int frame_overlay_image_id = 0;
+gfx::ImageSkia BrowserHeaderPainterAsh::GetFrameImage(Mode mode) const {
+  if (!is_tabbed_)
+    return gfx::ImageSkia();
 
   const ui::ThemeProvider* tp = frame_->GetThemeProvider();
-  if (tp->HasCustomImage(IDR_THEME_FRAME_OVERLAY) && !is_incognito_) {
-    frame_overlay_image_id = (mode == MODE_ACTIVE) ?
-        IDR_THEME_FRAME_OVERLAY : IDR_THEME_FRAME_OVERLAY_INACTIVE;
-  }
+  int frame_image_id =
+      (mode == MODE_ACTIVE) ? IDR_THEME_FRAME : IDR_THEME_FRAME_INACTIVE;
 
-  if (mode == MODE_ACTIVE) {
-    frame_image_id = is_incognito_ ?
-        IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME;
-  } else {
-    frame_image_id = is_incognito_ ?
-        IDR_THEME_FRAME_INCOGNITO_INACTIVE : IDR_THEME_FRAME_INACTIVE;
-  }
-
-  *frame_image = *tp->GetImageSkiaNamed(frame_image_id);
-  *frame_overlay_image = (frame_overlay_image_id == 0) ?
-      gfx::ImageSkia() : *tp->GetImageSkiaNamed(frame_overlay_image_id);
+  // Even if there's no explicit custom image for IDR_THEME_FRAME_INACTIVE, one
+  // will be generated for it based on IDR_THEME_FRAME.
+  return tp->HasCustomImage(frame_image_id) ||
+                 tp->HasCustomImage(IDR_THEME_FRAME)
+             ? *tp->GetImageSkiaNamed(frame_image_id)
+             : gfx::ImageSkia();
 }
 
-gfx::ImageSkia BrowserHeaderPainterAsh::GetFrameImageForNonTabbedBrowser(
-    Mode mode) const {
-  // Request the images from the ResourceBundle (and not from the ThemeProvider)
-  // in order to get the default non-themed assets.
-  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-  if (mode == MODE_ACTIVE) {
-    return *rb.GetImageSkiaNamed(is_incognito_ ?
-        IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME);
-  }
-  return *rb.GetImageSkiaNamed(is_incognito_ ?
-      IDR_THEME_FRAME_INCOGNITO_INACTIVE : IDR_THEME_FRAME_INACTIVE);
+gfx::ImageSkia BrowserHeaderPainterAsh::GetFrameOverlayImage(Mode mode) const {
+  if (is_incognito_ || !is_tabbed_)
+    return gfx::ImageSkia();
+
+  const ui::ThemeProvider* tp = frame_->GetThemeProvider();
+  int frame_overlay_image_id = (mode == MODE_ACTIVE)
+                                   ? IDR_THEME_FRAME_OVERLAY
+                                   : IDR_THEME_FRAME_OVERLAY_INACTIVE;
+  return tp->HasCustomImage(frame_overlay_image_id)
+             ? *tp->GetImageSkiaNamed(frame_overlay_image_id)
+             : gfx::ImageSkia();
+}
+
+SkColor BrowserHeaderPainterAsh::GetFrameColor(Mode mode) const {
+  int color = (mode == MODE_ACTIVE) ? ThemeProperties::COLOR_FRAME
+                                    : ThemeProperties::COLOR_FRAME_INACTIVE;
+  // We only theme tabbed windows; fall back to default for non-tabbed.
+  return is_tabbed_ ? frame_->GetThemeProvider()->GetColor(color)
+                    : ThemeProperties::GetDefaultColor(color, is_incognito_);
 }
 
 void BrowserHeaderPainterAsh::UpdateCaptionButtons() {
diff --git a/chrome/browser/ui/views/frame/browser_header_painter_ash.h b/chrome/browser/ui/views/frame/browser_header_painter_ash.h
index 8d27f54d..e5dc84f9 100644
--- a/chrome/browser/ui/views/frame/browser_header_painter_ash.h
+++ b/chrome/browser/ui/views/frame/browser_header_painter_ash.h
@@ -9,6 +9,7 @@
 #include "base/compiler_specific.h"  // override
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
+#include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/animation/animation_delegate.h"
 
 class BrowserView;
@@ -62,24 +63,17 @@
   // Paints the title bar, primarily the title string.
   void PaintTitleBar(gfx::Canvas* canvas);
 
-  // Sets |frame_image| and |frame_overlay_image| to the frame image and the
-  // frame overlay image respectivately which should be used to paint the
-  // header.
-  void GetFrameImages(Mode mode,
-                      gfx::ImageSkia* frame_image,
-                      gfx::ImageSkia* frame_overlay_image) const;
+  // Gets the base image to paint for the frame. This may be null, in which case
+  // GetFrameColor() should be used instead.
+  gfx::ImageSkia GetFrameImage(Mode mode) const;
 
-  // Sets |frame_image| and |frame_overlay_image| to the frame image and the
-  // frame overlay image respectively that should be used to paint the header
-  // for tabbed browser windows.
-  void GetFrameImagesForTabbedBrowser(
-      Mode mode,
-      gfx::ImageSkia* frame_image,
-      gfx::ImageSkia* frame_overlay_image) const;
+  // Gets the overlay image to paint on top of the base image. This may be null,
+  // in which case nothing will be drawn.
+  gfx::ImageSkia GetFrameOverlayImage(Mode mode) const;
 
-  // Returns the frame image which should be used to paint the header for popup
-  // browser windows and for hosted app windows which show the toolbar.
-  gfx::ImageSkia GetFrameImageForNonTabbedBrowser(Mode mode) const;
+  // Gets the color to use to paint the frame (when GetFrameImage() returns
+  // a null image).
+  SkColor GetFrameColor(Mode mode) const;
 
   // Updates the size and icons used for the minimize, restore, and close
   // buttons.
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
index 81a8a276..c44d5894 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -104,6 +104,7 @@
   return browser_view_->IsBrowserTypeNormal();
 }
 
+#if !defined(OS_CHROMEOS)
 SkColor BrowserNonClientFrameView::GetFrameColor() const {
   ThemeProperties::OverwritableByUserThemeProperty color_id =
       ShouldPaintAsActive() ? ThemeProperties::COLOR_FRAME
@@ -154,16 +155,7 @@
   }
   return nullptr;
 }
-
-int BrowserNonClientFrameView::GetTopAreaHeight() const {
-  gfx::ImageSkia* frame_image = GetFrameImage();
-  int top_area_height = frame_image->height();
-  if (browser_view_->IsTabStripVisible()) {
-    top_area_height = std::max(top_area_height,
-      GetBoundsForTabStrip(browser_view_->tabstrip()).bottom());
-  }
-  return top_area_height;
-}
+#endif  // !defined(OS_CHROMEOS)
 
 void BrowserNonClientFrameView::UpdateAvatar() {
 #if !defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
index 4c9be1c..ade7448 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -72,11 +72,12 @@
   // not.
   virtual bool ShouldPaintAsThemed() const;
 
+#if !defined(OS_CHROMEOS)
   // Compute aspects of the frame needed to paint the frame background.
   SkColor GetFrameColor() const;
   gfx::ImageSkia* GetFrameImage() const;
   gfx::ImageSkia* GetFrameOverlayImage() const;
-  int GetTopAreaHeight() const;
+#endif
 
   // Updates the avatar button using the old or new UI based on the BrowserView
   // type, and the presence of the --enable-new-avatar-menu flag. Calls either
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
index 2103c64..edf02a0 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -569,6 +569,17 @@
       IsMaximized());
 }
 
+int OpaqueBrowserFrameView::GetTopAreaHeight() const {
+  gfx::ImageSkia* frame_image = GetFrameImage();
+  int top_area_height = frame_image->height();
+  if (browser_view()->IsTabStripVisible()) {
+    top_area_height =
+        std::max(top_area_height,
+                 GetBoundsForTabStrip(browser_view()->tabstrip()).bottom());
+  }
+  return top_area_height;
+}
+
 void OpaqueBrowserFrameView::PaintRestoredFrameBorder(
     gfx::Canvas* canvas) const {
   frame_background_->set_frame_color(GetFrameColor());
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
index 8048bb5..d4afe01 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
@@ -134,6 +134,9 @@
   // Returns true if the view should draw its own custom title bar.
   bool ShouldShowWindowTitleBar() const;
 
+  // Computes the height of the top area of the frame.
+  int GetTopAreaHeight() const;
+
   // Paint various sub-components of this view.  The *FrameBorder() functions
   // also paint the background of the titlebar area, since the top frame border
   // and titlebar background are a contiguous component.