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 |