Home | History | Annotate | Download | only in config
      1 // Copyright (c) 2013 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 "gpu/config/gpu_control_list.h"
      6 
      7 #include "base/cpu.h"
      8 #include "base/json/json_reader.h"
      9 #include "base/logging.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/strings/string_split.h"
     12 #include "base/strings/string_util.h"
     13 #include "base/strings/stringprintf.h"
     14 #include "base/sys_info.h"
     15 #include "gpu/config/gpu_info.h"
     16 #include "gpu/config/gpu_util.h"
     17 
     18 namespace gpu {
     19 namespace {
     20 
     21 // Break a version string into segments.  Return true if each segment is
     22 // a valid number, and not all segment is 0.
     23 bool ProcessVersionString(const std::string& version_string,
     24                           char splitter,
     25                           std::vector<std::string>* version) {
     26   DCHECK(version);
     27   base::SplitString(version_string, splitter, version);
     28   if (version->size() == 0)
     29     return false;
     30   // If the splitter is '-', we assume it's a date with format "mm-dd-yyyy";
     31   // we split it into the order of "yyyy", "mm", "dd".
     32   if (splitter == '-') {
     33     std::string year = (*version)[version->size() - 1];
     34     for (int i = version->size() - 1; i > 0; --i) {
     35       (*version)[i] = (*version)[i - 1];
     36     }
     37     (*version)[0] = year;
     38   }
     39   bool all_zero = true;
     40   for (size_t i = 0; i < version->size(); ++i) {
     41     unsigned num = 0;
     42     if (!base::StringToUint((*version)[i], &num))
     43       return false;
     44     if (num)
     45       all_zero = false;
     46   }
     47   return !all_zero;
     48 }
     49 
     50 // Compare two number strings using numerical ordering.
     51 // Return  0 if number = number_ref,
     52 //         1 if number > number_ref,
     53 //        -1 if number < number_ref.
     54 int CompareNumericalNumberStrings(
     55     const std::string& number, const std::string& number_ref) {
     56   unsigned value1 = 0;
     57   unsigned value2 = 0;
     58   bool valid = base::StringToUint(number, &value1);
     59   DCHECK(valid);
     60   valid = base::StringToUint(number_ref, &value2);
     61   DCHECK(valid);
     62   if (value1 == value2)
     63     return 0;
     64   if (value1 > value2)
     65     return 1;
     66   return -1;
     67 }
     68 
     69 // Compare two number strings using lexical ordering.
     70 // Return  0 if number = number_ref,
     71 //         1 if number > number_ref,
     72 //        -1 if number < number_ref.
     73 // We only compare as many digits as number_ref contains.
     74 // If number_ref is xxx, it's considered as xxx*
     75 // For example: CompareLexicalNumberStrings("121", "12") returns 0,
     76 //              CompareLexicalNumberStrings("12", "121") returns -1.
     77 int CompareLexicalNumberStrings(
     78     const std::string& number, const std::string& number_ref) {
     79   for (size_t i = 0; i < number_ref.length(); ++i) {
     80     unsigned value1 = 0;
     81     if (i < number.length())
     82       value1 = number[i] - '0';
     83     unsigned value2 = number_ref[i] - '0';
     84     if (value1 > value2)
     85       return 1;
     86     if (value1 < value2)
     87       return -1;
     88   }
     89   return 0;
     90 }
     91 
     92 const char kMultiGpuStyleStringAMDSwitchable[] = "amd_switchable";
     93 const char kMultiGpuStyleStringAMDSwitchableDiscrete[] =
     94     "amd_switchable_discrete";
     95 const char kMultiGpuStyleStringAMDSwitchableIntegrated[] =
     96     "amd_switchable_integrated";
     97 const char kMultiGpuStyleStringOptimus[] = "optimus";
     98 
     99 const char kMultiGpuCategoryStringPrimary[] = "primary";
    100 const char kMultiGpuCategoryStringSecondary[] = "secondary";
    101 const char kMultiGpuCategoryStringActive[] = "active";
    102 const char kMultiGpuCategoryStringAny[] = "any";
    103 
    104 const char kGLTypeStringGL[] = "gl";
    105 const char kGLTypeStringGLES[] = "gles";
    106 const char kGLTypeStringANGLE[] = "angle";
    107 
    108 const char kVersionStyleStringNumerical[] = "numerical";
    109 const char kVersionStyleStringLexical[] = "lexical";
    110 
    111 const char kOp[] = "op";
    112 
    113 }  // namespace anonymous
    114 
    115 GpuControlList::VersionInfo::VersionInfo(
    116     const std::string& version_op,
    117     const std::string& version_style,
    118     const std::string& version_string,
    119     const std::string& version_string2)
    120     : version_style_(kVersionStyleNumerical) {
    121   op_ = StringToNumericOp(version_op);
    122   if (op_ == kUnknown || op_ == kAny)
    123     return;
    124   version_style_ = StringToVersionStyle(version_style);
    125   if (!ProcessVersionString(version_string, '.', &version_)) {
    126     op_ = kUnknown;
    127     return;
    128   }
    129   if (op_ == kBetween) {
    130     if (!ProcessVersionString(version_string2, '.', &version2_))
    131       op_ = kUnknown;
    132   }
    133 }
    134 
    135 GpuControlList::VersionInfo::~VersionInfo() {
    136 }
    137 
    138 bool GpuControlList::VersionInfo::Contains(
    139     const std::string& version_string) const {
    140   return Contains(version_string, '.');
    141 }
    142 
    143 bool GpuControlList::VersionInfo::Contains(
    144     const std::string& version_string, char splitter) const {
    145   if (op_ == kUnknown)
    146     return false;
    147   if (op_ == kAny)
    148     return true;
    149   std::vector<std::string> version;
    150   if (!ProcessVersionString(version_string, splitter, &version))
    151     return false;
    152   int relation = Compare(version, version_, version_style_);
    153   if (op_ == kEQ)
    154     return (relation == 0);
    155   else if (op_ == kLT)
    156     return (relation < 0);
    157   else if (op_ == kLE)
    158     return (relation <= 0);
    159   else if (op_ == kGT)
    160     return (relation > 0);
    161   else if (op_ == kGE)
    162     return (relation >= 0);
    163   // op_ == kBetween
    164   if (relation < 0)
    165     return false;
    166   return Compare(version, version2_, version_style_) <= 0;
    167 }
    168 
    169 bool GpuControlList::VersionInfo::IsValid() const {
    170   return (op_ != kUnknown && version_style_ != kVersionStyleUnknown);
    171 }
    172 
    173 bool GpuControlList::VersionInfo::IsLexical() const {
    174   return version_style_ == kVersionStyleLexical;
    175 }
    176 
    177 // static
    178 int GpuControlList::VersionInfo::Compare(
    179     const std::vector<std::string>& version,
    180     const std::vector<std::string>& version_ref,
    181     VersionStyle version_style) {
    182   DCHECK(version.size() > 0 && version_ref.size() > 0);
    183   DCHECK(version_style != kVersionStyleUnknown);
    184   for (size_t i = 0; i < version_ref.size(); ++i) {
    185     if (i >= version.size())
    186       return 0;
    187     int ret = 0;
    188     // We assume both versions are checked by ProcessVersionString().
    189     if (i > 0 && version_style == kVersionStyleLexical)
    190       ret = CompareLexicalNumberStrings(version[i], version_ref[i]);
    191     else
    192       ret = CompareNumericalNumberStrings(version[i], version_ref[i]);
    193     if (ret != 0)
    194       return ret;
    195   }
    196   return 0;
    197 }
    198 
    199 // static
    200 GpuControlList::VersionInfo::VersionStyle
    201 GpuControlList::VersionInfo::StringToVersionStyle(
    202     const std::string& version_style) {
    203   if (version_style.empty() || version_style == kVersionStyleStringNumerical)
    204     return kVersionStyleNumerical;
    205   if (version_style == kVersionStyleStringLexical)
    206     return kVersionStyleLexical;
    207   return kVersionStyleUnknown;
    208 }
    209 
    210 GpuControlList::OsInfo::OsInfo(const std::string& os,
    211                              const std::string& version_op,
    212                              const std::string& version_string,
    213                              const std::string& version_string2) {
    214   type_ = StringToOsType(os);
    215   if (type_ != kOsUnknown) {
    216     version_info_.reset(new VersionInfo(
    217         version_op, std::string(), version_string, version_string2));
    218   }
    219 }
    220 
    221 GpuControlList::OsInfo::~OsInfo() {}
    222 
    223 bool GpuControlList::OsInfo::Contains(
    224     OsType type, const std::string& version) const {
    225   if (!IsValid())
    226     return false;
    227   if (type_ != type && type_ != kOsAny)
    228     return false;
    229   std::string processed_version;
    230   size_t pos = version.find_first_not_of("0123456789.");
    231   if (pos != std::string::npos)
    232     processed_version = version.substr(0, pos);
    233   else
    234     processed_version = version;
    235 
    236   return version_info_->Contains(processed_version);
    237 }
    238 
    239 bool GpuControlList::OsInfo::IsValid() const {
    240   return type_ != kOsUnknown && version_info_->IsValid();
    241 }
    242 
    243 GpuControlList::OsType GpuControlList::OsInfo::type() const {
    244   return type_;
    245 }
    246 
    247 GpuControlList::OsType GpuControlList::OsInfo::StringToOsType(
    248     const std::string& os) {
    249   if (os == "win")
    250     return kOsWin;
    251   else if (os == "macosx")
    252     return kOsMacosx;
    253   else if (os == "android")
    254     return kOsAndroid;
    255   else if (os == "linux")
    256     return kOsLinux;
    257   else if (os == "chromeos")
    258     return kOsChromeOS;
    259   else if (os == "any")
    260     return kOsAny;
    261   return kOsUnknown;
    262 }
    263 
    264 GpuControlList::StringInfo::StringInfo(const std::string& string_op,
    265                                      const std::string& string_value) {
    266   op_ = StringToOp(string_op);
    267   value_ = StringToLowerASCII(string_value);
    268 }
    269 
    270 bool GpuControlList::StringInfo::Contains(const std::string& value) const {
    271   std::string my_value = StringToLowerASCII(value);
    272   switch (op_) {
    273     case kContains:
    274       return strstr(my_value.c_str(), value_.c_str()) != NULL;
    275     case kBeginWith:
    276       return StartsWithASCII(my_value, value_, false);
    277     case kEndWith:
    278       return EndsWith(my_value, value_, false);
    279     case kEQ:
    280       return value_ == my_value;
    281     default:
    282       return false;
    283   }
    284 }
    285 
    286 bool GpuControlList::StringInfo::IsValid() const {
    287   return op_ != kUnknown;
    288 }
    289 
    290 GpuControlList::StringInfo::Op GpuControlList::StringInfo::StringToOp(
    291     const std::string& string_op) {
    292   if (string_op == "=")
    293     return kEQ;
    294   else if (string_op == "contains")
    295     return kContains;
    296   else if (string_op == "beginwith")
    297     return kBeginWith;
    298   else if (string_op == "endwith")
    299     return kEndWith;
    300   return kUnknown;
    301 }
    302 
    303 GpuControlList::FloatInfo::FloatInfo(const std::string& float_op,
    304                                      const std::string& float_value,
    305                                      const std::string& float_value2)
    306     : op_(kUnknown),
    307       value_(0.f),
    308       value2_(0.f) {
    309   op_ = StringToNumericOp(float_op);
    310   if (op_ == kAny)
    311     return;
    312   double dvalue = 0;
    313   if (!base::StringToDouble(float_value, &dvalue)) {
    314     op_ = kUnknown;
    315     return;
    316   }
    317   value_ = static_cast<float>(dvalue);
    318   if (op_ == kBetween) {
    319     if (!base::StringToDouble(float_value2, &dvalue)) {
    320       op_ = kUnknown;
    321       return;
    322     }
    323     value2_ = static_cast<float>(dvalue);
    324   }
    325 }
    326 
    327 bool GpuControlList::FloatInfo::Contains(float value) const {
    328   if (op_ == kUnknown)
    329     return false;
    330   if (op_ == kAny)
    331     return true;
    332   if (op_ == kEQ)
    333     return (value == value_);
    334   if (op_ == kLT)
    335     return (value < value_);
    336   if (op_ == kLE)
    337     return (value <= value_);
    338   if (op_ == kGT)
    339     return (value > value_);
    340   if (op_ == kGE)
    341     return (value >= value_);
    342   DCHECK(op_ == kBetween);
    343   return ((value_ <= value && value <= value2_) ||
    344           (value2_ <= value && value <= value_));
    345 }
    346 
    347 bool GpuControlList::FloatInfo::IsValid() const {
    348   return op_ != kUnknown;
    349 }
    350 
    351 GpuControlList::IntInfo::IntInfo(const std::string& int_op,
    352                                  const std::string& int_value,
    353                                  const std::string& int_value2)
    354     : op_(kUnknown),
    355       value_(0),
    356       value2_(0) {
    357   op_ = StringToNumericOp(int_op);
    358   if (op_ == kAny)
    359     return;
    360   if (!base::StringToInt(int_value, &value_)) {
    361     op_ = kUnknown;
    362     return;
    363   }
    364   if (op_ == kBetween &&
    365       !base::StringToInt(int_value2, &value2_))
    366     op_ = kUnknown;
    367 }
    368 
    369 bool GpuControlList::IntInfo::Contains(int value) const {
    370   if (op_ == kUnknown)
    371     return false;
    372   if (op_ == kAny)
    373     return true;
    374   if (op_ == kEQ)
    375     return (value == value_);
    376   if (op_ == kLT)
    377     return (value < value_);
    378   if (op_ == kLE)
    379     return (value <= value_);
    380   if (op_ == kGT)
    381     return (value > value_);
    382   if (op_ == kGE)
    383     return (value >= value_);
    384   DCHECK(op_ == kBetween);
    385   return ((value_ <= value && value <= value2_) ||
    386           (value2_ <= value && value <= value_));
    387 }
    388 
    389 bool GpuControlList::IntInfo::IsValid() const {
    390   return op_ != kUnknown;
    391 }
    392 
    393 GpuControlList::BoolInfo::BoolInfo(bool value) : value_(value) {}
    394 
    395 bool GpuControlList::BoolInfo::Contains(bool value) const {
    396   return value_ == value;
    397 }
    398 
    399 // static
    400 GpuControlList::ScopedGpuControlListEntry
    401 GpuControlList::GpuControlListEntry::GetEntryFromValue(
    402     const base::DictionaryValue* value, bool top_level,
    403     const FeatureMap& feature_map,
    404     bool supports_feature_type_all) {
    405   DCHECK(value);
    406   ScopedGpuControlListEntry entry(new GpuControlListEntry());
    407 
    408   size_t dictionary_entry_count = 0;
    409 
    410   if (top_level) {
    411     uint32 id;
    412     if (!value->GetInteger("id", reinterpret_cast<int*>(&id)) ||
    413         !entry->SetId(id)) {
    414       LOG(WARNING) << "Malformed id entry " << entry->id();
    415       return NULL;
    416     }
    417     dictionary_entry_count++;
    418 
    419     bool disabled;
    420     if (value->GetBoolean("disabled", &disabled)) {
    421       entry->SetDisabled(disabled);
    422       dictionary_entry_count++;
    423     }
    424   }
    425 
    426   std::string description;
    427   if (value->GetString("description", &description)) {
    428     entry->description_ = description;
    429     dictionary_entry_count++;
    430   } else {
    431     entry->description_ = "The GPU is unavailable for an unexplained reason.";
    432   }
    433 
    434   const base::ListValue* cr_bugs;
    435   if (value->GetList("cr_bugs", &cr_bugs)) {
    436     for (size_t i = 0; i < cr_bugs->GetSize(); ++i) {
    437       int bug_id;
    438       if (cr_bugs->GetInteger(i, &bug_id)) {
    439         entry->cr_bugs_.push_back(bug_id);
    440       } else {
    441         LOG(WARNING) << "Malformed cr_bugs entry " << entry->id();
    442         return NULL;
    443       }
    444     }
    445     dictionary_entry_count++;
    446   }
    447 
    448   const base::ListValue* webkit_bugs;
    449   if (value->GetList("webkit_bugs", &webkit_bugs)) {
    450     for (size_t i = 0; i < webkit_bugs->GetSize(); ++i) {
    451       int bug_id;
    452       if (webkit_bugs->GetInteger(i, &bug_id)) {
    453         entry->webkit_bugs_.push_back(bug_id);
    454       } else {
    455         LOG(WARNING) << "Malformed webkit_bugs entry " << entry->id();
    456         return NULL;
    457       }
    458     }
    459     dictionary_entry_count++;
    460   }
    461 
    462   const base::DictionaryValue* os_value = NULL;
    463   if (value->GetDictionary("os", &os_value)) {
    464     std::string os_type;
    465     std::string os_version_op = "any";
    466     std::string os_version_string;
    467     std::string os_version_string2;
    468     os_value->GetString("type", &os_type);
    469     const base::DictionaryValue* os_version_value = NULL;
    470     if (os_value->GetDictionary("version", &os_version_value)) {
    471       os_version_value->GetString(kOp, &os_version_op);
    472       os_version_value->GetString("value", &os_version_string);
    473       os_version_value->GetString("value2", &os_version_string2);
    474     }
    475     if (!entry->SetOsInfo(os_type, os_version_op, os_version_string,
    476                           os_version_string2)) {
    477       LOG(WARNING) << "Malformed os entry " << entry->id();
    478       return NULL;
    479     }
    480     dictionary_entry_count++;
    481   }
    482 
    483   std::string vendor_id;
    484   if (value->GetString("vendor_id", &vendor_id)) {
    485     if (!entry->SetVendorId(vendor_id)) {
    486       LOG(WARNING) << "Malformed vendor_id entry " << entry->id();
    487       return NULL;
    488     }
    489     dictionary_entry_count++;
    490   }
    491 
    492   const base::ListValue* device_id_list;
    493   if (value->GetList("device_id", &device_id_list)) {
    494     for (size_t i = 0; i < device_id_list->GetSize(); ++i) {
    495       std::string device_id;
    496       if (!device_id_list->GetString(i, &device_id) ||
    497           !entry->AddDeviceId(device_id)) {
    498         LOG(WARNING) << "Malformed device_id entry " << entry->id();
    499         return NULL;
    500       }
    501     }
    502     dictionary_entry_count++;
    503   }
    504 
    505   std::string multi_gpu_style;
    506   if (value->GetString("multi_gpu_style", &multi_gpu_style)) {
    507     if (!entry->SetMultiGpuStyle(multi_gpu_style)) {
    508       LOG(WARNING) << "Malformed multi_gpu_style entry " << entry->id();
    509       return NULL;
    510     }
    511     dictionary_entry_count++;
    512   }
    513 
    514   std::string multi_gpu_category;
    515   if (value->GetString("multi_gpu_category", &multi_gpu_category)) {
    516     if (!entry->SetMultiGpuCategory(multi_gpu_category)) {
    517       LOG(WARNING) << "Malformed multi_gpu_category entry " << entry->id();
    518       return NULL;
    519     }
    520     dictionary_entry_count++;
    521   }
    522 
    523   const base::DictionaryValue* driver_vendor_value = NULL;
    524   if (value->GetDictionary("driver_vendor", &driver_vendor_value)) {
    525     std::string vendor_op;
    526     std::string vendor_value;
    527     driver_vendor_value->GetString(kOp, &vendor_op);
    528     driver_vendor_value->GetString("value", &vendor_value);
    529     if (!entry->SetDriverVendorInfo(vendor_op, vendor_value)) {
    530       LOG(WARNING) << "Malformed driver_vendor entry " << entry->id();
    531       return NULL;
    532     }
    533     dictionary_entry_count++;
    534   }
    535 
    536   const base::DictionaryValue* driver_version_value = NULL;
    537   if (value->GetDictionary("driver_version", &driver_version_value)) {
    538     std::string driver_version_op = "any";
    539     std::string driver_version_style;
    540     std::string driver_version_string;
    541     std::string driver_version_string2;
    542     driver_version_value->GetString(kOp, &driver_version_op);
    543     driver_version_value->GetString("style", &driver_version_style);
    544     driver_version_value->GetString("value", &driver_version_string);
    545     driver_version_value->GetString("value2", &driver_version_string2);
    546     if (!entry->SetDriverVersionInfo(driver_version_op,
    547                                      driver_version_style,
    548                                      driver_version_string,
    549                                      driver_version_string2)) {
    550       LOG(WARNING) << "Malformed driver_version entry " << entry->id();
    551       return NULL;
    552     }
    553     dictionary_entry_count++;
    554   }
    555 
    556   const base::DictionaryValue* driver_date_value = NULL;
    557   if (value->GetDictionary("driver_date", &driver_date_value)) {
    558     std::string driver_date_op = "any";
    559     std::string driver_date_string;
    560     std::string driver_date_string2;
    561     driver_date_value->GetString(kOp, &driver_date_op);
    562     driver_date_value->GetString("value", &driver_date_string);
    563     driver_date_value->GetString("value2", &driver_date_string2);
    564     if (!entry->SetDriverDateInfo(driver_date_op, driver_date_string,
    565                                   driver_date_string2)) {
    566       LOG(WARNING) << "Malformed driver_date entry " << entry->id();
    567       return NULL;
    568     }
    569     dictionary_entry_count++;
    570   }
    571 
    572   std::string gl_type;
    573   if (value->GetString("gl_type", &gl_type)) {
    574     if (!entry->SetGLType(gl_type)) {
    575       LOG(WARNING) << "Malformed gl_type entry " << entry->id();
    576       return NULL;
    577     }
    578     dictionary_entry_count++;
    579   }
    580 
    581   const base::DictionaryValue* gl_version_value = NULL;
    582   if (value->GetDictionary("gl_version", &gl_version_value)) {
    583     std::string version_op = "any";
    584     std::string version_string;
    585     std::string version_string2;
    586     gl_version_value->GetString(kOp, &version_op);
    587     gl_version_value->GetString("value", &version_string);
    588     gl_version_value->GetString("value2", &version_string2);
    589     if (!entry->SetGLVersionInfo(
    590             version_op, version_string, version_string2)) {
    591       LOG(WARNING) << "Malformed gl_version entry " << entry->id();
    592       return NULL;
    593     }
    594     dictionary_entry_count++;
    595   }
    596 
    597   const base::DictionaryValue* gl_vendor_value = NULL;
    598   if (value->GetDictionary("gl_vendor", &gl_vendor_value)) {
    599     std::string vendor_op;
    600     std::string vendor_value;
    601     gl_vendor_value->GetString(kOp, &vendor_op);
    602     gl_vendor_value->GetString("value", &vendor_value);
    603     if (!entry->SetGLVendorInfo(vendor_op, vendor_value)) {
    604       LOG(WARNING) << "Malformed gl_vendor entry " << entry->id();
    605       return NULL;
    606     }
    607     dictionary_entry_count++;
    608   }
    609 
    610   const base::DictionaryValue* gl_renderer_value = NULL;
    611   if (value->GetDictionary("gl_renderer", &gl_renderer_value)) {
    612     std::string renderer_op;
    613     std::string renderer_value;
    614     gl_renderer_value->GetString(kOp, &renderer_op);
    615     gl_renderer_value->GetString("value", &renderer_value);
    616     if (!entry->SetGLRendererInfo(renderer_op, renderer_value)) {
    617       LOG(WARNING) << "Malformed gl_renderer entry " << entry->id();
    618       return NULL;
    619     }
    620     dictionary_entry_count++;
    621   }
    622 
    623   const base::DictionaryValue* gl_extensions_value = NULL;
    624   if (value->GetDictionary("gl_extensions", &gl_extensions_value)) {
    625     std::string extensions_op;
    626     std::string extensions_value;
    627     gl_extensions_value->GetString(kOp, &extensions_op);
    628     gl_extensions_value->GetString("value", &extensions_value);
    629     if (!entry->SetGLExtensionsInfo(extensions_op, extensions_value)) {
    630       LOG(WARNING) << "Malformed gl_extensions entry " << entry->id();
    631       return NULL;
    632     }
    633     dictionary_entry_count++;
    634   }
    635 
    636   const base::DictionaryValue* gl_reset_notification_strategy_value = NULL;
    637   if (value->GetDictionary("gl_reset_notification_strategy",
    638                            &gl_reset_notification_strategy_value)) {
    639     std::string op;
    640     std::string int_value;
    641     std::string int_value2;
    642     gl_reset_notification_strategy_value->GetString(kOp, &op);
    643     gl_reset_notification_strategy_value->GetString("value", &int_value);
    644     gl_reset_notification_strategy_value->GetString("value2", &int_value2);
    645     if (!entry->SetGLResetNotificationStrategyInfo(
    646             op, int_value, int_value2)) {
    647       LOG(WARNING) << "Malformed gl_reset_notification_strategy entry "
    648                    << entry->id();
    649       return NULL;
    650     }
    651     dictionary_entry_count++;
    652   }
    653 
    654   const base::DictionaryValue* cpu_brand_value = NULL;
    655   if (value->GetDictionary("cpu_info", &cpu_brand_value)) {
    656     std::string cpu_op;
    657     std::string cpu_value;
    658     cpu_brand_value->GetString(kOp, &cpu_op);
    659     cpu_brand_value->GetString("value", &cpu_value);
    660     if (!entry->SetCpuBrand(cpu_op, cpu_value)) {
    661       LOG(WARNING) << "Malformed cpu_brand entry " << entry->id();
    662       return NULL;
    663     }
    664     dictionary_entry_count++;
    665   }
    666 
    667   const base::DictionaryValue* perf_graphics_value = NULL;
    668   if (value->GetDictionary("perf_graphics", &perf_graphics_value)) {
    669     std::string op;
    670     std::string float_value;
    671     std::string float_value2;
    672     perf_graphics_value->GetString(kOp, &op);
    673     perf_graphics_value->GetString("value", &float_value);
    674     perf_graphics_value->GetString("value2", &float_value2);
    675     if (!entry->SetPerfGraphicsInfo(op, float_value, float_value2)) {
    676       LOG(WARNING) << "Malformed perf_graphics entry " << entry->id();
    677       return NULL;
    678     }
    679     dictionary_entry_count++;
    680   }
    681 
    682   const base::DictionaryValue* perf_gaming_value = NULL;
    683   if (value->GetDictionary("perf_gaming", &perf_gaming_value)) {
    684     std::string op;
    685     std::string float_value;
    686     std::string float_value2;
    687     perf_gaming_value->GetString(kOp, &op);
    688     perf_gaming_value->GetString("value", &float_value);
    689     perf_gaming_value->GetString("value2", &float_value2);
    690     if (!entry->SetPerfGamingInfo(op, float_value, float_value2)) {
    691       LOG(WARNING) << "Malformed perf_gaming entry " << entry->id();
    692       return NULL;
    693     }
    694     dictionary_entry_count++;
    695   }
    696 
    697   const base::DictionaryValue* perf_overall_value = NULL;
    698   if (value->GetDictionary("perf_overall", &perf_overall_value)) {
    699     std::string op;
    700     std::string float_value;
    701     std::string float_value2;
    702     perf_overall_value->GetString(kOp, &op);
    703     perf_overall_value->GetString("value", &float_value);
    704     perf_overall_value->GetString("value2", &float_value2);
    705     if (!entry->SetPerfOverallInfo(op, float_value, float_value2)) {
    706       LOG(WARNING) << "Malformed perf_overall entry " << entry->id();
    707       return NULL;
    708     }
    709     dictionary_entry_count++;
    710   }
    711 
    712   const base::ListValue* machine_model_name_list;
    713   if (value->GetList("machine_model_name", &machine_model_name_list)) {
    714     for (size_t i = 0; i < machine_model_name_list->GetSize(); ++i) {
    715       std::string model_name;
    716       if (!machine_model_name_list->GetString(i, &model_name) ||
    717           !entry->AddMachineModelName(model_name)) {
    718         LOG(WARNING) << "Malformed machine_model_name entry " << entry->id();
    719         return NULL;
    720       }
    721     }
    722     dictionary_entry_count++;
    723   }
    724 
    725   const base::DictionaryValue* machine_model_version_value = NULL;
    726   if (value->GetDictionary(
    727           "machine_model_version", &machine_model_version_value)) {
    728     std::string version_op = "any";
    729     std::string version_string;
    730     std::string version_string2;
    731     machine_model_version_value->GetString(kOp, &version_op);
    732     machine_model_version_value->GetString("value", &version_string);
    733     machine_model_version_value->GetString("value2", &version_string2);
    734     if (!entry->SetMachineModelVersionInfo(
    735             version_op, version_string, version_string2)) {
    736       LOG(WARNING) << "Malformed machine_model_version entry " << entry->id();
    737       return NULL;
    738     }
    739     dictionary_entry_count++;
    740   }
    741 
    742   const base::DictionaryValue* gpu_count_value = NULL;
    743   if (value->GetDictionary("gpu_count", &gpu_count_value)) {
    744     std::string op;
    745     std::string int_value;
    746     std::string int_value2;
    747     gpu_count_value->GetString(kOp, &op);
    748     gpu_count_value->GetString("value", &int_value);
    749     gpu_count_value->GetString("value2", &int_value2);
    750     if (!entry->SetGpuCountInfo(op, int_value, int_value2)) {
    751       LOG(WARNING) << "Malformed gpu_count entry " << entry->id();
    752       return NULL;
    753     }
    754     dictionary_entry_count++;
    755   }
    756 
    757   bool direct_rendering;
    758   if (value->GetBoolean("direct_rendering", &direct_rendering)) {
    759     entry->SetDirectRenderingInfo(direct_rendering);
    760     dictionary_entry_count++;
    761   }
    762 
    763   if (top_level) {
    764     const base::ListValue* feature_value = NULL;
    765     if (value->GetList("features", &feature_value)) {
    766       std::vector<std::string> feature_list;
    767       for (size_t i = 0; i < feature_value->GetSize(); ++i) {
    768         std::string feature;
    769         if (feature_value->GetString(i, &feature)) {
    770           feature_list.push_back(feature);
    771         } else {
    772           LOG(WARNING) << "Malformed feature entry " << entry->id();
    773           return NULL;
    774         }
    775       }
    776       if (!entry->SetFeatures(
    777               feature_list, feature_map, supports_feature_type_all)) {
    778         LOG(WARNING) << "Malformed feature entry " << entry->id();
    779         return NULL;
    780       }
    781       dictionary_entry_count++;
    782     }
    783   }
    784 
    785   if (top_level) {
    786     const base::ListValue* exception_list_value = NULL;
    787     if (value->GetList("exceptions", &exception_list_value)) {
    788       for (size_t i = 0; i < exception_list_value->GetSize(); ++i) {
    789         const base::DictionaryValue* exception_value = NULL;
    790         if (!exception_list_value->GetDictionary(i, &exception_value)) {
    791           LOG(WARNING) << "Malformed exceptions entry " << entry->id();
    792           return NULL;
    793         }
    794         ScopedGpuControlListEntry exception(GetEntryFromValue(
    795             exception_value, false, feature_map, supports_feature_type_all));
    796         if (exception.get() == NULL) {
    797           LOG(WARNING) << "Malformed exceptions entry " << entry->id();
    798           return NULL;
    799         }
    800         // Exception should inherit vendor_id from parent, otherwise if only
    801         // device_ids are specified in Exception, the info will be incomplete.
    802         if (exception->vendor_id_ == 0 && entry->vendor_id_ != 0)
    803           exception->vendor_id_ = entry->vendor_id_;
    804         entry->AddException(exception);
    805       }
    806       dictionary_entry_count++;
    807     }
    808   }
    809 
    810   if (value->size() != dictionary_entry_count) {
    811     LOG(WARNING) << "Entry with unknown fields " << entry->id();
    812     return NULL;
    813   }
    814 
    815   // If GL_VERSION is specified, but no info about whether it's GL or GLES,
    816   // we use the default for the platform.  See GLType enum declaration.
    817   if (entry->gl_version_info_.get() != NULL && entry->gl_type_ == kGLTypeNone)
    818     entry->gl_type_ = GetDefaultGLType();
    819 
    820   return entry;
    821 }
    822 
    823 GpuControlList::GpuControlListEntry::GpuControlListEntry()
    824     : id_(0),
    825       disabled_(false),
    826       vendor_id_(0),
    827       multi_gpu_style_(kMultiGpuStyleNone),
    828       multi_gpu_category_(kMultiGpuCategoryPrimary),
    829       gl_type_(kGLTypeNone) {
    830 }
    831 
    832 GpuControlList::GpuControlListEntry::~GpuControlListEntry() { }
    833 
    834 bool GpuControlList::GpuControlListEntry::SetId(uint32 id) {
    835   if (id != 0) {
    836     id_ = id;
    837     return true;
    838   }
    839   return false;
    840 }
    841 
    842 void GpuControlList::GpuControlListEntry::SetDisabled(bool disabled) {
    843   disabled_ = disabled;
    844 }
    845 
    846 bool GpuControlList::GpuControlListEntry::SetOsInfo(
    847     const std::string& os,
    848     const std::string& version_op,
    849     const std::string& version_string,
    850     const std::string& version_string2) {
    851   os_info_.reset(new OsInfo(os, version_op, version_string, version_string2));
    852   return os_info_->IsValid();
    853 }
    854 
    855 bool GpuControlList::GpuControlListEntry::SetVendorId(
    856     const std::string& vendor_id_string) {
    857   vendor_id_ = 0;
    858   return base::HexStringToUInt(vendor_id_string, &vendor_id_) &&
    859       vendor_id_ != 0;
    860 }
    861 
    862 bool GpuControlList::GpuControlListEntry::AddDeviceId(
    863     const std::string& device_id_string) {
    864   uint32 device_id = 0;
    865   if (base::HexStringToUInt(device_id_string, &device_id) && device_id != 0) {
    866     device_id_list_.push_back(device_id);
    867     return true;
    868   }
    869   return false;
    870 }
    871 
    872 bool GpuControlList::GpuControlListEntry::SetMultiGpuStyle(
    873     const std::string& multi_gpu_style_string) {
    874   MultiGpuStyle style = StringToMultiGpuStyle(multi_gpu_style_string);
    875   if (style == kMultiGpuStyleNone)
    876     return false;
    877   multi_gpu_style_ = style;
    878   return true;
    879 }
    880 
    881 bool GpuControlList::GpuControlListEntry::SetMultiGpuCategory(
    882     const std::string& multi_gpu_category_string) {
    883   MultiGpuCategory category =
    884       StringToMultiGpuCategory(multi_gpu_category_string);
    885   if (category == kMultiGpuCategoryNone)
    886     return false;
    887   multi_gpu_category_ = category;
    888   return true;
    889 }
    890 
    891 bool GpuControlList::GpuControlListEntry::SetGLType(
    892     const std::string& gl_type_string) {
    893   GLType gl_type = StringToGLType(gl_type_string);
    894   if (gl_type == kGLTypeNone)
    895     return false;
    896   gl_type_ = gl_type;
    897   return true;
    898 }
    899 
    900 bool GpuControlList::GpuControlListEntry::SetDriverVendorInfo(
    901     const std::string& vendor_op,
    902     const std::string& vendor_value) {
    903   driver_vendor_info_.reset(new StringInfo(vendor_op, vendor_value));
    904   return driver_vendor_info_->IsValid();
    905 }
    906 
    907 bool GpuControlList::GpuControlListEntry::SetDriverVersionInfo(
    908     const std::string& version_op,
    909     const std::string& version_style,
    910     const std::string& version_string,
    911     const std::string& version_string2) {
    912   driver_version_info_.reset(new VersionInfo(
    913       version_op, version_style, version_string, version_string2));
    914   return driver_version_info_->IsValid();
    915 }
    916 
    917 bool GpuControlList::GpuControlListEntry::SetDriverDateInfo(
    918     const std::string& date_op,
    919     const std::string& date_string,
    920     const std::string& date_string2) {
    921   driver_date_info_.reset(
    922       new VersionInfo(date_op, std::string(), date_string, date_string2));
    923   return driver_date_info_->IsValid();
    924 }
    925 
    926 bool GpuControlList::GpuControlListEntry::SetGLVersionInfo(
    927     const std::string& version_op,
    928     const std::string& version_string,
    929     const std::string& version_string2) {
    930   gl_version_info_.reset(new VersionInfo(
    931       version_op, std::string(), version_string, version_string2));
    932   return gl_version_info_->IsValid();
    933 }
    934 
    935 bool GpuControlList::GpuControlListEntry::SetGLVendorInfo(
    936     const std::string& vendor_op,
    937     const std::string& vendor_value) {
    938   gl_vendor_info_.reset(new StringInfo(vendor_op, vendor_value));
    939   return gl_vendor_info_->IsValid();
    940 }
    941 
    942 bool GpuControlList::GpuControlListEntry::SetGLRendererInfo(
    943     const std::string& renderer_op,
    944     const std::string& renderer_value) {
    945   gl_renderer_info_.reset(new StringInfo(renderer_op, renderer_value));
    946   return gl_renderer_info_->IsValid();
    947 }
    948 
    949 bool GpuControlList::GpuControlListEntry::SetGLExtensionsInfo(
    950     const std::string& extensions_op,
    951     const std::string& extensions_value) {
    952   gl_extensions_info_.reset(new StringInfo(extensions_op, extensions_value));
    953   return gl_extensions_info_->IsValid();
    954 }
    955 
    956 bool GpuControlList::GpuControlListEntry::SetGLResetNotificationStrategyInfo(
    957     const std::string& op,
    958     const std::string& int_string,
    959     const std::string& int_string2) {
    960   gl_reset_notification_strategy_info_.reset(
    961       new IntInfo(op, int_string, int_string2));
    962   return gl_reset_notification_strategy_info_->IsValid();
    963 }
    964 
    965 bool GpuControlList::GpuControlListEntry::SetCpuBrand(
    966     const std::string& cpu_op,
    967     const std::string& cpu_value) {
    968   cpu_brand_.reset(new StringInfo(cpu_op, cpu_value));
    969   return cpu_brand_->IsValid();
    970 }
    971 
    972 bool GpuControlList::GpuControlListEntry::SetPerfGraphicsInfo(
    973     const std::string& op,
    974     const std::string& float_string,
    975     const std::string& float_string2) {
    976   perf_graphics_info_.reset(new FloatInfo(op, float_string, float_string2));
    977   return perf_graphics_info_->IsValid();
    978 }
    979 
    980 bool GpuControlList::GpuControlListEntry::SetPerfGamingInfo(
    981     const std::string& op,
    982     const std::string& float_string,
    983     const std::string& float_string2) {
    984   perf_gaming_info_.reset(new FloatInfo(op, float_string, float_string2));
    985   return perf_gaming_info_->IsValid();
    986 }
    987 
    988 bool GpuControlList::GpuControlListEntry::SetPerfOverallInfo(
    989     const std::string& op,
    990     const std::string& float_string,
    991     const std::string& float_string2) {
    992   perf_overall_info_.reset(new FloatInfo(op, float_string, float_string2));
    993   return perf_overall_info_->IsValid();
    994 }
    995 
    996 bool GpuControlList::GpuControlListEntry::AddMachineModelName(
    997     const std::string& model_name) {
    998   if (model_name.empty())
    999     return false;
   1000   machine_model_name_list_.push_back(model_name);
   1001   return true;
   1002 }
   1003 
   1004 bool GpuControlList::GpuControlListEntry::SetMachineModelVersionInfo(
   1005     const std::string& version_op,
   1006     const std::string& version_string,
   1007     const std::string& version_string2) {
   1008   machine_model_version_info_.reset(new VersionInfo(
   1009       version_op, std::string(), version_string, version_string2));
   1010   return machine_model_version_info_->IsValid();
   1011 }
   1012 
   1013 bool GpuControlList::GpuControlListEntry::SetGpuCountInfo(
   1014     const std::string& op,
   1015     const std::string& int_string,
   1016     const std::string& int_string2) {
   1017   gpu_count_info_.reset(new IntInfo(op, int_string, int_string2));
   1018   return gpu_count_info_->IsValid();
   1019 }
   1020 
   1021 void GpuControlList::GpuControlListEntry::SetDirectRenderingInfo(bool value) {
   1022   direct_rendering_info_.reset(new BoolInfo(value));
   1023 }
   1024 
   1025 bool GpuControlList::GpuControlListEntry::SetFeatures(
   1026     const std::vector<std::string>& feature_strings,
   1027     const FeatureMap& feature_map,
   1028     bool supports_feature_type_all) {
   1029   size_t size = feature_strings.size();
   1030   if (size == 0)
   1031     return false;
   1032   features_.clear();
   1033   for (size_t i = 0; i < size; ++i) {
   1034     int feature = 0;
   1035     if (supports_feature_type_all && feature_strings[i] == "all") {
   1036       for (FeatureMap::const_iterator iter = feature_map.begin();
   1037            iter != feature_map.end(); ++iter)
   1038         features_.insert(iter->second);
   1039       continue;
   1040     }
   1041     if (!StringToFeature(feature_strings[i], &feature, feature_map)) {
   1042       features_.clear();
   1043       return false;
   1044     }
   1045     features_.insert(feature);
   1046   }
   1047   return true;
   1048 }
   1049 
   1050 void GpuControlList::GpuControlListEntry::AddException(
   1051     ScopedGpuControlListEntry exception) {
   1052   exceptions_.push_back(exception);
   1053 }
   1054 
   1055 bool GpuControlList::GpuControlListEntry::GLVersionInfoMismatch(
   1056     const std::string& gl_version) const {
   1057   if (gl_version.empty())
   1058     return false;
   1059 
   1060   if (gl_version_info_.get() == NULL && gl_type_ == kGLTypeNone)
   1061     return false;
   1062 
   1063   std::vector<std::string> segments;
   1064   base::SplitString(gl_version, ' ', &segments);
   1065   std::string number;
   1066   GLType gl_type = kGLTypeNone;
   1067   if (segments.size() > 2 &&
   1068       segments[0] == "OpenGL" && segments[1] == "ES") {
   1069     number = segments[2];
   1070     gl_type = kGLTypeGLES;
   1071     if (segments.size() > 3 &&
   1072         StartsWithASCII(segments[3], "(ANGLE", false)) {
   1073       gl_type = kGLTypeANGLE;
   1074     }
   1075   } else {
   1076     number = segments[0];
   1077     gl_type = kGLTypeGL;
   1078   }
   1079 
   1080   if (gl_type_ != kGLTypeNone && gl_type_ != gl_type)
   1081     return true;
   1082   if (gl_version_info_.get() != NULL && !gl_version_info_->Contains(number))
   1083     return true;
   1084   return false;
   1085 }
   1086 
   1087 // static
   1088 GpuControlList::GpuControlListEntry::MultiGpuStyle
   1089 GpuControlList::GpuControlListEntry::StringToMultiGpuStyle(
   1090     const std::string& style) {
   1091   if (style == kMultiGpuStyleStringOptimus)
   1092     return kMultiGpuStyleOptimus;
   1093   if (style == kMultiGpuStyleStringAMDSwitchable)
   1094     return kMultiGpuStyleAMDSwitchable;
   1095   if (style == kMultiGpuStyleStringAMDSwitchableIntegrated)
   1096     return kMultiGpuStyleAMDSwitchableIntegrated;
   1097   if (style == kMultiGpuStyleStringAMDSwitchableDiscrete)
   1098     return kMultiGpuStyleAMDSwitchableDiscrete;
   1099   return kMultiGpuStyleNone;
   1100 }
   1101 
   1102 // static
   1103 GpuControlList::GpuControlListEntry::MultiGpuCategory
   1104 GpuControlList::GpuControlListEntry::StringToMultiGpuCategory(
   1105     const std::string& category) {
   1106   if (category == kMultiGpuCategoryStringPrimary)
   1107     return kMultiGpuCategoryPrimary;
   1108   if (category == kMultiGpuCategoryStringSecondary)
   1109     return kMultiGpuCategorySecondary;
   1110   if (category == kMultiGpuCategoryStringActive)
   1111     return kMultiGpuCategoryActive;
   1112   if (category == kMultiGpuCategoryStringAny)
   1113     return kMultiGpuCategoryAny;
   1114   return kMultiGpuCategoryNone;
   1115 }
   1116 
   1117 // static
   1118 GpuControlList::GpuControlListEntry::GLType
   1119 GpuControlList::GpuControlListEntry::StringToGLType(
   1120     const std::string& gl_type) {
   1121   if (gl_type == kGLTypeStringGL)
   1122     return kGLTypeGL;
   1123   if (gl_type == kGLTypeStringGLES)
   1124     return kGLTypeGLES;
   1125   if (gl_type == kGLTypeStringANGLE)
   1126     return kGLTypeANGLE;
   1127   return kGLTypeNone;
   1128 }
   1129 
   1130 // static
   1131 GpuControlList::GpuControlListEntry::GLType
   1132 GpuControlList::GpuControlListEntry::GetDefaultGLType() {
   1133 #if defined(OS_CHROMEOS)
   1134   return kGLTypeGL;
   1135 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
   1136   return kGLTypeGL;
   1137 #elif defined(OS_MACOSX)
   1138   return kGLTypeGL;
   1139 #elif defined(OS_WIN)
   1140   return kGLTypeANGLE;
   1141 #elif defined(OS_ANDROID)
   1142   return kGLTypeGLES;
   1143 #else
   1144   return kGLTypeNone;
   1145 #endif
   1146 }
   1147 
   1148 void GpuControlList::GpuControlListEntry::LogControlListMatch(
   1149     const std::string& control_list_logging_name) const {
   1150   static const char kControlListMatchMessage[] =
   1151       "Control list match for rule #%u in %s.";
   1152   VLOG(1) << base::StringPrintf(kControlListMatchMessage, id_,
   1153                                 control_list_logging_name.c_str());
   1154 }
   1155 
   1156 bool GpuControlList::GpuControlListEntry::Contains(
   1157     OsType os_type, const std::string& os_version,
   1158     const GPUInfo& gpu_info) const {
   1159   DCHECK(os_type != kOsAny);
   1160   if (os_info_.get() != NULL && !os_info_->Contains(os_type, os_version))
   1161     return false;
   1162   if (vendor_id_ != 0) {
   1163     std::vector<GPUInfo::GPUDevice> candidates;
   1164     switch (multi_gpu_category_) {
   1165       case kMultiGpuCategoryPrimary:
   1166         candidates.push_back(gpu_info.gpu);
   1167         break;
   1168       case kMultiGpuCategorySecondary:
   1169         candidates = gpu_info.secondary_gpus;
   1170         break;
   1171       case kMultiGpuCategoryAny:
   1172         candidates = gpu_info.secondary_gpus;
   1173         candidates.push_back(gpu_info.gpu);
   1174         break;
   1175       case kMultiGpuCategoryActive:
   1176         if (gpu_info.gpu.active)
   1177           candidates.push_back(gpu_info.gpu);
   1178         for (size_t ii = 0; ii < gpu_info.secondary_gpus.size(); ++ii) {
   1179           if (gpu_info.secondary_gpus[ii].active)
   1180             candidates.push_back(gpu_info.secondary_gpus[ii]);
   1181         }
   1182       default:
   1183         break;
   1184     }
   1185 
   1186     GPUInfo::GPUDevice gpu;
   1187     gpu.vendor_id = vendor_id_;
   1188     bool found = false;
   1189     if (device_id_list_.empty()) {
   1190       for (size_t ii = 0; ii < candidates.size(); ++ii) {
   1191         if (gpu.vendor_id == candidates[ii].vendor_id) {
   1192           found = true;
   1193           break;
   1194         }
   1195       }
   1196     } else {
   1197       for (size_t ii = 0; ii < device_id_list_.size(); ++ii) {
   1198         gpu.device_id = device_id_list_[ii];
   1199         for (size_t jj = 0; jj < candidates.size(); ++jj) {
   1200           if (gpu.vendor_id == candidates[jj].vendor_id &&
   1201               gpu.device_id == candidates[jj].device_id) {
   1202             found = true;
   1203             break;
   1204           }
   1205         }
   1206       }
   1207     }
   1208     if (!found)
   1209       return false;
   1210   }
   1211   switch (multi_gpu_style_) {
   1212     case kMultiGpuStyleOptimus:
   1213       if (!gpu_info.optimus)
   1214         return false;
   1215       break;
   1216     case kMultiGpuStyleAMDSwitchable:
   1217       if (!gpu_info.amd_switchable)
   1218         return false;
   1219       break;
   1220     case kMultiGpuStyleAMDSwitchableDiscrete:
   1221       if (!gpu_info.amd_switchable)
   1222         return false;
   1223       // The discrete GPU is always the primary GPU.
   1224       // This is guaranteed by GpuInfoCollector.
   1225       if (!gpu_info.gpu.active)
   1226         return false;
   1227       break;
   1228     case kMultiGpuStyleAMDSwitchableIntegrated:
   1229       if (!gpu_info.amd_switchable)
   1230         return false;
   1231       // Assume the integrated GPU is the first in the secondary GPU list.
   1232       if (gpu_info.secondary_gpus.size() == 0 ||
   1233           !gpu_info.secondary_gpus[0].active)
   1234         return false;
   1235       break;
   1236     case kMultiGpuStyleNone:
   1237       break;
   1238   }
   1239   if (driver_vendor_info_.get() != NULL && !gpu_info.driver_vendor.empty() &&
   1240       !driver_vendor_info_->Contains(gpu_info.driver_vendor))
   1241     return false;
   1242   if (driver_version_info_.get() != NULL && !gpu_info.driver_version.empty()) {
   1243     if (!driver_version_info_->Contains(gpu_info.driver_version))
   1244       return false;
   1245   }
   1246   if (driver_date_info_.get() != NULL && !gpu_info.driver_date.empty()) {
   1247     if (!driver_date_info_->Contains(gpu_info.driver_date, '-'))
   1248       return false;
   1249   }
   1250   if (GLVersionInfoMismatch(gpu_info.gl_version))
   1251     return false;
   1252   if (gl_vendor_info_.get() != NULL && !gpu_info.gl_vendor.empty() &&
   1253       !gl_vendor_info_->Contains(gpu_info.gl_vendor))
   1254     return false;
   1255   if (gl_renderer_info_.get() != NULL && !gpu_info.gl_renderer.empty() &&
   1256       !gl_renderer_info_->Contains(gpu_info.gl_renderer))
   1257     return false;
   1258   if (gl_extensions_info_.get() != NULL && !gpu_info.gl_extensions.empty() &&
   1259       !gl_extensions_info_->Contains(gpu_info.gl_extensions))
   1260     return false;
   1261   if (gl_reset_notification_strategy_info_.get() != NULL &&
   1262       !gl_reset_notification_strategy_info_->Contains(
   1263           gpu_info.gl_reset_notification_strategy))
   1264     return false;
   1265   if (perf_graphics_info_.get() != NULL &&
   1266       (gpu_info.performance_stats.graphics == 0.0 ||
   1267        !perf_graphics_info_->Contains(gpu_info.performance_stats.graphics)))
   1268     return false;
   1269   if (perf_gaming_info_.get() != NULL &&
   1270       (gpu_info.performance_stats.gaming == 0.0 ||
   1271        !perf_gaming_info_->Contains(gpu_info.performance_stats.gaming)))
   1272     return false;
   1273   if (perf_overall_info_.get() != NULL &&
   1274       (gpu_info.performance_stats.overall == 0.0 ||
   1275        !perf_overall_info_->Contains(gpu_info.performance_stats.overall)))
   1276     return false;
   1277   if (!machine_model_name_list_.empty()) {
   1278     if (gpu_info.machine_model_name.empty())
   1279       return false;
   1280     bool found_match = false;
   1281     for (size_t ii = 0; ii < machine_model_name_list_.size(); ++ii) {
   1282       if (machine_model_name_list_[ii] == gpu_info.machine_model_name) {
   1283         found_match = true;
   1284         break;
   1285       }
   1286     }
   1287     if (!found_match)
   1288       return false;
   1289   }
   1290   if (machine_model_version_info_.get() != NULL &&
   1291       (gpu_info.machine_model_version.empty() ||
   1292        !machine_model_version_info_->Contains(gpu_info.machine_model_version)))
   1293     return false;
   1294   if (gpu_count_info_.get() != NULL &&
   1295       !gpu_count_info_->Contains(gpu_info.secondary_gpus.size() + 1))
   1296     return false;
   1297   if (direct_rendering_info_.get() != NULL &&
   1298       !direct_rendering_info_->Contains(gpu_info.direct_rendering))
   1299     return false;
   1300   if (cpu_brand_.get() != NULL) {
   1301     base::CPU cpu_info;
   1302     if (!cpu_brand_->Contains(cpu_info.cpu_brand()))
   1303       return false;
   1304   }
   1305 
   1306   for (size_t i = 0; i < exceptions_.size(); ++i) {
   1307     if (exceptions_[i]->Contains(os_type, os_version, gpu_info) &&
   1308         !exceptions_[i]->NeedsMoreInfo(gpu_info))
   1309       return false;
   1310   }
   1311   return true;
   1312 }
   1313 
   1314 bool GpuControlList::GpuControlListEntry::NeedsMoreInfo(
   1315     const GPUInfo& gpu_info) const {
   1316   // We only check for missing info that might be collected with a gl context.
   1317   // If certain info is missing due to some error, say, we fail to collect
   1318   // vendor_id/device_id, then even if we launch GPU process and create a gl
   1319   // context, we won't gather such missing info, so we still return false.
   1320   if (driver_vendor_info_.get() && gpu_info.driver_vendor.empty())
   1321     return true;
   1322   if (driver_version_info_.get() && gpu_info.driver_version.empty())
   1323     return true;
   1324   if (gl_vendor_info_.get() && gpu_info.gl_vendor.empty())
   1325     return true;
   1326   if (gl_renderer_info_.get() && gpu_info.gl_renderer.empty())
   1327     return true;
   1328   for (size_t i = 0; i < exceptions_.size(); ++i) {
   1329     if (exceptions_[i]->NeedsMoreInfo(gpu_info))
   1330       return true;
   1331   }
   1332   return false;
   1333 }
   1334 
   1335 GpuControlList::OsType GpuControlList::GpuControlListEntry::GetOsType() const {
   1336   if (os_info_.get() == NULL)
   1337     return kOsAny;
   1338   return os_info_->type();
   1339 }
   1340 
   1341 uint32 GpuControlList::GpuControlListEntry::id() const {
   1342   return id_;
   1343 }
   1344 
   1345 bool GpuControlList::GpuControlListEntry::disabled() const {
   1346   return disabled_;
   1347 }
   1348 
   1349 const std::set<int>& GpuControlList::GpuControlListEntry::features() const {
   1350   return features_;
   1351 }
   1352 
   1353 void GpuControlList::GpuControlListEntry::GetFeatureNames(
   1354     base::ListValue* feature_names,
   1355     const FeatureMap& feature_map,
   1356     bool supports_feature_type_all) const {
   1357   DCHECK(feature_names);
   1358   if (supports_feature_type_all && features_.size() == feature_map.size()) {
   1359     feature_names->AppendString("all");
   1360     return;
   1361   }
   1362   for (FeatureMap::const_iterator iter = feature_map.begin();
   1363        iter != feature_map.end(); ++iter) {
   1364     if (features_.count(iter->second) > 0)
   1365       feature_names->AppendString(iter->first);
   1366   }
   1367 }
   1368 
   1369 // static
   1370 bool GpuControlList::GpuControlListEntry::StringToFeature(
   1371     const std::string& feature_name, int* feature_id,
   1372     const FeatureMap& feature_map) {
   1373   FeatureMap::const_iterator iter = feature_map.find(feature_name);
   1374   if (iter != feature_map.end()) {
   1375     *feature_id = iter->second;
   1376     return true;
   1377   }
   1378   return false;
   1379 }
   1380 
   1381 GpuControlList::GpuControlList()
   1382     : max_entry_id_(0),
   1383       needs_more_info_(false),
   1384       supports_feature_type_all_(false),
   1385       control_list_logging_enabled_(false) {
   1386 }
   1387 
   1388 GpuControlList::~GpuControlList() {
   1389   Clear();
   1390 }
   1391 
   1392 bool GpuControlList::LoadList(
   1393     const std::string& json_context,
   1394     GpuControlList::OsFilter os_filter) {
   1395   scoped_ptr<base::Value> root;
   1396   root.reset(base::JSONReader::Read(json_context));
   1397   if (root.get() == NULL || !root->IsType(base::Value::TYPE_DICTIONARY))
   1398     return false;
   1399 
   1400   base::DictionaryValue* root_dictionary =
   1401       static_cast<base::DictionaryValue*>(root.get());
   1402   DCHECK(root_dictionary);
   1403   return LoadList(*root_dictionary, os_filter);
   1404 }
   1405 
   1406 bool GpuControlList::LoadList(const base::DictionaryValue& parsed_json,
   1407                               GpuControlList::OsFilter os_filter) {
   1408   std::vector<ScopedGpuControlListEntry> entries;
   1409 
   1410   parsed_json.GetString("version", &version_);
   1411   std::vector<std::string> pieces;
   1412   if (!ProcessVersionString(version_, '.', &pieces))
   1413     return false;
   1414 
   1415   const base::ListValue* list = NULL;
   1416   if (!parsed_json.GetList("entries", &list))
   1417     return false;
   1418 
   1419   uint32 max_entry_id = 0;
   1420   for (size_t i = 0; i < list->GetSize(); ++i) {
   1421     const base::DictionaryValue* list_item = NULL;
   1422     bool valid = list->GetDictionary(i, &list_item);
   1423     if (!valid || list_item == NULL)
   1424       return false;
   1425     ScopedGpuControlListEntry entry(GpuControlListEntry::GetEntryFromValue(
   1426         list_item, true, feature_map_, supports_feature_type_all_));
   1427     if (entry.get() == NULL)
   1428       return false;
   1429     if (entry->id() > max_entry_id)
   1430       max_entry_id = entry->id();
   1431     entries.push_back(entry);
   1432   }
   1433 
   1434   Clear();
   1435   OsType my_os = GetOsType();
   1436   for (size_t i = 0; i < entries.size(); ++i) {
   1437     OsType entry_os = entries[i]->GetOsType();
   1438     if (os_filter == GpuControlList::kAllOs ||
   1439         entry_os == kOsAny || entry_os == my_os)
   1440       entries_.push_back(entries[i]);
   1441   }
   1442   max_entry_id_ = max_entry_id;
   1443   return true;
   1444 }
   1445 
   1446 std::set<int> GpuControlList::MakeDecision(
   1447     GpuControlList::OsType os,
   1448     std::string os_version,
   1449     const GPUInfo& gpu_info) {
   1450   active_entries_.clear();
   1451   std::set<int> features;
   1452 
   1453   needs_more_info_ = false;
   1454   std::set<int> possible_features;
   1455 
   1456   if (os == kOsAny)
   1457     os = GetOsType();
   1458   if (os_version.empty())
   1459     os_version = base::SysInfo::OperatingSystemVersion();
   1460 
   1461   for (size_t i = 0; i < entries_.size(); ++i) {
   1462     if (entries_[i]->Contains(os, os_version, gpu_info)) {
   1463       if (!entries_[i]->disabled()) {
   1464         if (control_list_logging_enabled_)
   1465           entries_[i]->LogControlListMatch(control_list_logging_name_);
   1466         MergeFeatureSets(&possible_features, entries_[i]->features());
   1467         if (!entries_[i]->NeedsMoreInfo(gpu_info))
   1468           MergeFeatureSets(&features, entries_[i]->features());
   1469       }
   1470       active_entries_.push_back(entries_[i]);
   1471     }
   1472   }
   1473 
   1474   if (possible_features.size() > features.size())
   1475     needs_more_info_ = true;
   1476 
   1477   return features;
   1478 }
   1479 
   1480 void GpuControlList::GetDecisionEntries(
   1481     std::vector<uint32>* entry_ids, bool disabled) const {
   1482   DCHECK(entry_ids);
   1483   entry_ids->clear();
   1484   for (size_t i = 0; i < active_entries_.size(); ++i) {
   1485     if (disabled == active_entries_[i]->disabled())
   1486       entry_ids->push_back(active_entries_[i]->id());
   1487   }
   1488 }
   1489 
   1490 void GpuControlList::GetReasons(base::ListValue* problem_list,
   1491                                 const std::string& tag) const {
   1492   DCHECK(problem_list);
   1493   for (size_t i = 0; i < active_entries_.size(); ++i) {
   1494     GpuControlListEntry* entry = active_entries_[i].get();
   1495     if (entry->disabled())
   1496       continue;
   1497     base::DictionaryValue* problem = new base::DictionaryValue();
   1498 
   1499     problem->SetString("description", entry->description());
   1500 
   1501     base::ListValue* cr_bugs = new base::ListValue();
   1502     for (size_t j = 0; j < entry->cr_bugs().size(); ++j)
   1503       cr_bugs->Append(new base::FundamentalValue(entry->cr_bugs()[j]));
   1504     problem->Set("crBugs", cr_bugs);
   1505 
   1506     base::ListValue* webkit_bugs = new base::ListValue();
   1507     for (size_t j = 0; j < entry->webkit_bugs().size(); ++j) {
   1508       webkit_bugs->Append(new base::FundamentalValue(entry->webkit_bugs()[j]));
   1509     }
   1510     problem->Set("webkitBugs", webkit_bugs);
   1511 
   1512     base::ListValue* features = new base::ListValue();
   1513     entry->GetFeatureNames(features, feature_map_, supports_feature_type_all_);
   1514     problem->Set("affectedGpuSettings", features);
   1515 
   1516     DCHECK(tag == "workarounds" || tag == "disabledFeatures");
   1517     problem->SetString("tag", tag);
   1518 
   1519     problem_list->Append(problem);
   1520   }
   1521 }
   1522 
   1523 size_t GpuControlList::num_entries() const {
   1524   return entries_.size();
   1525 }
   1526 
   1527 uint32 GpuControlList::max_entry_id() const {
   1528   return max_entry_id_;
   1529 }
   1530 
   1531 std::string GpuControlList::version() const {
   1532   return version_;
   1533 }
   1534 
   1535 GpuControlList::OsType GpuControlList::GetOsType() {
   1536 #if defined(OS_CHROMEOS)
   1537   return kOsChromeOS;
   1538 #elif defined(OS_WIN)
   1539   return kOsWin;
   1540 #elif defined(OS_ANDROID)
   1541   return kOsAndroid;
   1542 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
   1543   return kOsLinux;
   1544 #elif defined(OS_MACOSX)
   1545   return kOsMacosx;
   1546 #else
   1547   return kOsUnknown;
   1548 #endif
   1549 }
   1550 
   1551 void GpuControlList::Clear() {
   1552   entries_.clear();
   1553   active_entries_.clear();
   1554   max_entry_id_ = 0;
   1555 }
   1556 
   1557 // static
   1558 GpuControlList::NumericOp GpuControlList::StringToNumericOp(
   1559     const std::string& op) {
   1560   if (op == "=")
   1561     return kEQ;
   1562   if (op == "<")
   1563     return kLT;
   1564   if (op == "<=")
   1565     return kLE;
   1566   if (op == ">")
   1567     return kGT;
   1568   if (op == ">=")
   1569     return kGE;
   1570   if (op == "any")
   1571     return kAny;
   1572   if (op == "between")
   1573     return kBetween;
   1574   return kUnknown;
   1575 }
   1576 
   1577 void GpuControlList::AddSupportedFeature(
   1578     const std::string& feature_name, int feature_id) {
   1579   feature_map_[feature_name] = feature_id;
   1580 }
   1581 
   1582 void GpuControlList::set_supports_feature_type_all(bool supported) {
   1583   supports_feature_type_all_ = supported;
   1584 }
   1585 
   1586 }  // namespace gpu
   1587 
   1588