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