12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/theme_handler.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/grit/generated_resources.h"
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest.h"
13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "extensions/common/manifest_constants.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace keys = manifest_keys;
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace errors = manifest_errors;
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool LoadImages(const base::DictionaryValue* theme_value,
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                base::string16* error,
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                ThemeInfo* theme_info) {
267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const base::DictionaryValue* images_value = NULL;
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (theme_value->GetDictionary(keys::kThemeImages, &images_value)) {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Validate that the images are all strings.
297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    for (base::DictionaryValue::Iterator iter(*images_value); !iter.IsAtEnd();
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         iter.Advance()) {
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // The value may be a dictionary of scales and files paths.
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Or the value may be a file path, in which case a scale
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // of 100% is assumed.
347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (iter.value().IsType(base::Value::TYPE_DICTIONARY)) {
357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        const base::DictionaryValue* inner_value = NULL;
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if (iter.value().GetAsDictionary(&inner_value)) {
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          for (base::DictionaryValue::Iterator inner_iter(*inner_value);
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               !inner_iter.IsAtEnd(); inner_iter.Advance()) {
397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            if (!inner_iter.value().IsType(base::Value::TYPE_STRING)) {
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              *error = base::ASCIIToUTF16(errors::kInvalidThemeImages);
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              return false;
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            }
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          }
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        } else {
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          *error = base::ASCIIToUTF16(errors::kInvalidThemeImages);
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          return false;
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      } else if (!iter.value().IsType(base::Value::TYPE_STRING)) {
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        *error = base::ASCIIToUTF16(errors::kInvalidThemeImages);
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    theme_info->theme_images_.reset(images_value->DeepCopy());
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool LoadColors(const base::DictionaryValue* theme_value,
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                base::string16* error,
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                ThemeInfo* theme_info) {
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const base::DictionaryValue* colors_value = NULL;
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (theme_value->GetDictionary(keys::kThemeColors, &colors_value)) {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Validate that the colors are RGB or RGBA lists.
647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    for (base::DictionaryValue::Iterator iter(*colors_value); !iter.IsAtEnd();
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         iter.Advance()) {
667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const base::ListValue* color_list = NULL;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      double alpha = 0.0;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int color = 0;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // The color must be a list...
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!iter.value().GetAsList(&color_list) ||
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // ... and either 3 items (RGB) or 4 (RGBA).
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          ((color_list->GetSize() != 3) &&
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           ((color_list->GetSize() != 4) ||
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // For RGBA, the fourth item must be a real or int alpha value.
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // Note that GetDouble() can get an integer value.
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            !color_list->GetDouble(3, &alpha))) ||
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // For both RGB and RGBA, the first three items must be ints (R,G,B).
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          !color_list->GetInteger(0, &color) ||
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          !color_list->GetInteger(1, &color) ||
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          !color_list->GetInteger(2, &color)) {
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        *error = base::ASCIIToUTF16(errors::kInvalidThemeColors);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    theme_info->theme_colors_.reset(colors_value->DeepCopy());
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool LoadTints(const base::DictionaryValue* theme_value,
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               base::string16* error,
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               ThemeInfo* theme_info) {
937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const base::DictionaryValue* tints_value = NULL;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!theme_value->GetDictionary(keys::kThemeTints, &tints_value))
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Validate that the tints are all reals.
987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (base::DictionaryValue::Iterator iter(*tints_value); !iter.IsAtEnd();
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter.Advance()) {
1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const base::ListValue* tint_list = NULL;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double v = 0.0;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!iter.value().GetAsList(&tint_list) ||
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        tint_list->GetSize() != 3 ||
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        !tint_list->GetDouble(0, &v) ||
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        !tint_list->GetDouble(1, &v) ||
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        !tint_list->GetDouble(2, &v)) {
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *error = base::ASCIIToUTF16(errors::kInvalidThemeTints);
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  theme_info->theme_tints_.reset(tints_value->DeepCopy());
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool LoadDisplayProperties(const base::DictionaryValue* theme_value,
116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                           base::string16* error,
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           ThemeInfo* theme_info) {
1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const base::DictionaryValue* display_properties_value = NULL;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (theme_value->GetDictionary(keys::kThemeDisplayProperties,
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 &display_properties_value)) {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    theme_info->theme_display_properties_.reset(
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        display_properties_value->DeepCopy());
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const ThemeInfo* GetInfo(const Extension* extension) {
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return static_cast<ThemeInfo*>(extension->GetManifestData(keys::kTheme));
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThemeInfo::ThemeInfo() {
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThemeInfo::~ThemeInfo() {
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const base::DictionaryValue* ThemeInfo::GetImages(const Extension* extension) {
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const ThemeInfo* theme_info = GetInfo(extension);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return theme_info ? theme_info->theme_images_.get() : NULL;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const base::DictionaryValue* ThemeInfo::GetColors(const Extension* extension) {
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const ThemeInfo* theme_info = GetInfo(extension);
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return theme_info ? theme_info->theme_colors_.get() : NULL;
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const base::DictionaryValue* ThemeInfo::GetTints(const Extension* extension) {
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const ThemeInfo* theme_info = GetInfo(extension);
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return theme_info ? theme_info->theme_tints_.get() : NULL;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const base::DictionaryValue* ThemeInfo::GetDisplayProperties(
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Extension* extension) {
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const ThemeInfo* theme_info = GetInfo(extension);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return theme_info ? theme_info->theme_display_properties_.get() : NULL;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThemeHandler::ThemeHandler() {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ThemeHandler::~ThemeHandler() {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ThemeHandler::Parse(Extension* extension, base::string16* error) {
1717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const base::DictionaryValue* theme_value = NULL;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!extension->manifest()->GetDictionary(keys::kTheme, &theme_value)) {
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *error = base::ASCIIToUTF16(errors::kInvalidTheme);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ThemeInfo> theme_info(new ThemeInfo);
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!LoadImages(theme_value, error, theme_info.get()))
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!LoadColors(theme_value, error, theme_info.get()))
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!LoadTints(theme_value, error, theme_info.get()))
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!LoadDisplayProperties(theme_value, error, theme_info.get()))
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extension->SetManifestData(keys::kTheme, theme_info.release());
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ThemeHandler::Validate(const Extension* extension,
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            std::string* error,
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            std::vector<InstallWarning>* warnings) const {
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Validate that theme images exist.
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (extension->is_theme()) {
1967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const base::DictionaryValue* images_value =
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        extensions::ThemeInfo::GetImages(extension);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (images_value) {
1997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      for (base::DictionaryValue::Iterator iter(*images_value); !iter.IsAtEnd();
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           iter.Advance()) {
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::string val;
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (iter.value().GetAsString(&val)) {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::FilePath image_path = extension->path().Append(
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              base::FilePath::FromUTF8Unsafe(val));
2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          if (!base::PathExists(image_path)) {
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            *error =
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                l10n_util::GetStringFUTF8(IDS_EXTENSION_INVALID_IMAGE_PATH,
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          image_path.LossyDisplayName());
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return false;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<std::string> ThemeHandler::Keys() const {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return SingleKey(keys::kTheme);
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace extensions
223