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