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