summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorzmo@chromium.org <zmo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-06 18:19:55 +0000
committerzmo@chromium.org <zmo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-06 18:19:55 +0000
commitb669fd10946e4330e9f6913e0260a229d7461f60 (patch)
treef7b2c909881299b5e8a4ef7d6200d90acbbcc967 /content
parentd668899a93d2703291133659a26f725c54dfa46d (diff)
downloadchromium_src-b669fd10946e4330e9f6913e0260a229d7461f60.zip
chromium_src-b669fd10946e4330e9f6913e0260a229d7461f60.tar.gz
chromium_src-b669fd10946e4330e9f6913e0260a229d7461f60.tar.bz2
Move gpu blacklist to content side.
When it's on the content side, it can be part of the GpuDataManager, so we don't need to make it a Singleton. Also, this CL did some cleanup related to this moving. The main reason for this refactoring is because blacklist is tightly coupled with GpuDataManager. Putting them on the this side makes it much easier to test the code, and the design is much better. BUG= TEST=bots Review URL: https://chromiumcodereview.appspot.com/10908110 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155218 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/gpu/gpu_blacklist.cc1164
-rw-r--r--content/browser/gpu/gpu_blacklist.h401
-rw-r--r--content/browser/gpu/gpu_blacklist_unittest.cc984
-rw-r--r--content/browser/gpu/gpu_data_manager_impl.cc49
-rw-r--r--content/browser/gpu/gpu_data_manager_impl.h23
-rw-r--r--content/browser/gpu/gpu_data_manager_impl_unittest.cc3
-rw-r--r--content/browser/gpu/gpu_util.cc223
-rw-r--r--content/browser/gpu/gpu_util.h41
-rw-r--r--content/browser/gpu/gpu_util_unittest.cc87
-rw-r--r--content/content_browser.gypi4
-rw-r--r--content/content_tests.gypi2
-rw-r--r--content/public/browser/gpu_data_manager.h20
12 files changed, 2977 insertions, 24 deletions
diff --git a/content/browser/gpu/gpu_blacklist.cc b/content/browser/gpu/gpu_blacklist.cc
new file mode 100644
index 0000000..403a894
--- /dev/null
+++ b/content/browser/gpu/gpu_blacklist.cc
@@ -0,0 +1,1164 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/gpu/gpu_blacklist.h"
+
+#include "base/command_line.h"
+#include "base/json/json_reader.h"
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/string_split.h"
+#include "base/string_util.h"
+#include "base/sys_info.h"
+#include "base/version.h"
+#include "content/browser/gpu/gpu_util.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/gpu_info.h"
+
+using content::GpuFeatureType;
+
+namespace {
+
+// Encode a date as Version, where [0] is year, [1] is month, and [2] is day.
+void GetDateFromString(const std::string& date_string, Version* version) {
+ // TODO(zmo): verify if in Windows registry, driver dates are always in the
+ // format of "mm-dd-yyyy".
+ std::vector<std::string> pieces;
+ base::SplitString(date_string, '-', &pieces);
+ if (pieces.size() != 3) {
+ *version = Version();
+ return;
+ }
+ std::string date_as_version_string = pieces[2];
+ for (size_t i = 0; i < 2; ++i) {
+ date_as_version_string += ".";
+ date_as_version_string += pieces[i];
+ }
+ *version = Version(date_as_version_string);
+}
+
+// We assume the input format is major.minor, and we treat major version
+// as numerical and minor as lexical.
+// Otherwise we simply return the original string.
+// For example, if input numerical is 8.103, returned lexical is 8.1.0.3.
+std::string NumericalToLexical(const std::string& numerical) {
+ std::string lexical;
+ bool valid = true;
+ size_t pos = numerical.find_first_of('.');
+ if (pos != std::string::npos && pos + 1 < numerical.length()) {
+ lexical = numerical.substr(0, pos);
+ for (size_t i = pos + 1; i < numerical.length(); ++i) {
+ if (!IsAsciiDigit(numerical[i])) {
+ valid = false;
+ break;
+ }
+ lexical += '.';
+ lexical += numerical[i];
+ }
+ } else {
+ valid = false;
+ }
+ if (valid)
+ return lexical;
+ return numerical;
+}
+
+bool GpuUnmatched(uint32 vendor_id, const std::vector<uint32>& device_id_list,
+ const content::GPUInfo::GPUDevice& gpu) {
+ if (vendor_id == 0)
+ return false;
+ if (vendor_id != gpu.vendor_id)
+ return true;
+ bool device_specified = false;
+ for (size_t i = 0; i < device_id_list.size(); ++i) {
+ if (device_id_list[i] == 0)
+ continue;
+ if (device_id_list[i] == gpu.device_id)
+ return false;
+ device_specified = true;
+ }
+ return device_specified;
+}
+
+const char kMultiGpuStyleStringAMDSwitchable[] = "amd_switchable";
+const char kMultiGpuStyleStringOptimus[] = "optimus";
+
+const char kMultiGpuCategoryStringPrimary[] = "primary";
+const char kMultiGpuCategoryStringSecondary[] = "secondary";
+const char kMultiGpuCategoryStringAny[] = "any";
+
+const char kVersionStyleStringNumerical[] = "numerical";
+const char kVersionStyleStringLexical[] = "lexical";
+
+} // namespace anonymous
+
+GpuBlacklist::VersionInfo::VersionInfo(
+ const std::string& version_op,
+ const std::string& version_style,
+ const std::string& version_string,
+ const std::string& version_string2)
+ : version_style_(kVersionStyleNumerical) {
+ op_ = StringToNumericOp(version_op);
+ if (op_ == kUnknown || op_ == kAny)
+ return;
+ version_style_ = StringToVersionStyle(version_style);
+ std::string processed_version_string, processed_version_string2;
+ if (version_style_ == kVersionStyleLexical) {
+ processed_version_string = NumericalToLexical(version_string);
+ processed_version_string2 = NumericalToLexical(version_string2);
+ } else {
+ processed_version_string = version_string;
+ processed_version_string2 = version_string2;
+ }
+ version_.reset(new Version(processed_version_string));
+ if (!version_->IsValid()) {
+ op_ = kUnknown;
+ return;
+ }
+ if (op_ == kBetween) {
+ version2_.reset(new Version(processed_version_string2));
+ if (!version2_->IsValid())
+ op_ = kUnknown;
+ }
+}
+
+GpuBlacklist::VersionInfo::~VersionInfo() {
+}
+
+bool GpuBlacklist::VersionInfo::Contains(const Version& version) const {
+ if (op_ == kUnknown)
+ return false;
+ if (op_ == kAny)
+ return true;
+ if (op_ == kEQ) {
+ // Handles cases where 10.6 is considered as containing 10.6.*.
+ const std::vector<uint16>& components_reference = version_->components();
+ const std::vector<uint16>& components = version.components();
+ for (size_t i = 0; i < components_reference.size(); ++i) {
+ if (i >= components.size() && components_reference[i] != 0)
+ return false;
+ if (components[i] != components_reference[i])
+ return false;
+ }
+ return true;
+ }
+ int relation = version.CompareTo(*version_);
+ if (op_ == kEQ)
+ return (relation == 0);
+ else if (op_ == kLT)
+ return (relation < 0);
+ else if (op_ == kLE)
+ return (relation <= 0);
+ else if (op_ == kGT)
+ return (relation > 0);
+ else if (op_ == kGE)
+ return (relation >= 0);
+ // op_ == kBetween
+ if (relation < 0)
+ return false;
+ return version.CompareTo(*version2_) <= 0;
+}
+
+bool GpuBlacklist::VersionInfo::IsValid() const {
+ return (op_ != kUnknown && version_style_ != kVersionStyleUnknown);
+}
+
+bool GpuBlacklist::VersionInfo::IsLexical() const {
+ return version_style_ == kVersionStyleLexical;
+}
+
+// static
+GpuBlacklist::VersionInfo::VersionStyle
+GpuBlacklist::VersionInfo::StringToVersionStyle(
+ const std::string& version_style) {
+ if (version_style.empty() || version_style == kVersionStyleStringNumerical)
+ return kVersionStyleNumerical;
+ if (version_style == kVersionStyleStringLexical)
+ return kVersionStyleLexical;
+ return kVersionStyleUnknown;
+}
+
+GpuBlacklist::OsInfo::OsInfo(const std::string& os,
+ const std::string& version_op,
+ const std::string& version_string,
+ const std::string& version_string2) {
+ type_ = StringToOsType(os);
+ if (type_ != kOsUnknown) {
+ version_info_.reset(
+ new VersionInfo(version_op, "", version_string, version_string2));
+ }
+}
+
+GpuBlacklist::OsInfo::~OsInfo() {}
+
+bool GpuBlacklist::OsInfo::Contains(OsType type,
+ const Version& version) const {
+ if (!IsValid())
+ return false;
+ if (type_ != type && type_ != kOsAny)
+ return false;
+ return version_info_->Contains(version);
+}
+
+bool GpuBlacklist::OsInfo::IsValid() const {
+ return type_ != kOsUnknown && version_info_->IsValid();
+}
+
+GpuBlacklist::OsType GpuBlacklist::OsInfo::type() const {
+ return type_;
+}
+
+GpuBlacklist::OsType GpuBlacklist::OsInfo::StringToOsType(
+ const std::string& os) {
+ if (os == "win")
+ return kOsWin;
+ else if (os == "macosx")
+ return kOsMacosx;
+ else if (os == "linux")
+ return kOsLinux;
+ else if (os == "chromeos")
+ return kOsChromeOS;
+ else if (os == "any")
+ return kOsAny;
+ return kOsUnknown;
+}
+
+GpuBlacklist::StringInfo::StringInfo(const std::string& string_op,
+ const std::string& string_value) {
+ op_ = StringToOp(string_op);
+ value_ = StringToLowerASCII(string_value);
+}
+
+bool GpuBlacklist::StringInfo::Contains(const std::string& value) const {
+ std::string my_value = StringToLowerASCII(value);
+ switch (op_) {
+ case kContains:
+ return strstr(my_value.c_str(), value_.c_str()) != NULL;
+ case kBeginWith:
+ return StartsWithASCII(my_value, value_, false);
+ case kEndWith:
+ return EndsWith(my_value, value_, false);
+ case kEQ:
+ return value_ == my_value;
+ default:
+ return false;
+ }
+}
+
+bool GpuBlacklist::StringInfo::IsValid() const {
+ return op_ != kUnknown;
+}
+
+GpuBlacklist::StringInfo::Op GpuBlacklist::StringInfo::StringToOp(
+ const std::string& string_op) {
+ if (string_op == "=")
+ return kEQ;
+ else if (string_op == "contains")
+ return kContains;
+ else if (string_op == "beginwith")
+ return kBeginWith;
+ else if (string_op == "endwith")
+ return kEndWith;
+ return kUnknown;
+}
+
+GpuBlacklist::FloatInfo::FloatInfo(const std::string& float_op,
+ const std::string& float_value,
+ const std::string& float_value2)
+ : op_(kUnknown),
+ value_(0.f),
+ value2_(0.f) {
+ double dvalue = 0;
+ if (!base::StringToDouble(float_value, &dvalue)) {
+ op_ = kUnknown;
+ return;
+ }
+ value_ = static_cast<float>(dvalue);
+ op_ = StringToNumericOp(float_op);
+ if (op_ == kBetween) {
+ if (!base::StringToDouble(float_value2, &dvalue)) {
+ op_ = kUnknown;
+ return;
+ }
+ value2_ = static_cast<float>(dvalue);
+ }
+}
+
+bool GpuBlacklist::FloatInfo::Contains(float value) const {
+ if (op_ == kUnknown)
+ return false;
+ if (op_ == kAny)
+ return true;
+ if (op_ == kEQ)
+ return (value == value_);
+ if (op_ == kLT)
+ return (value < value_);
+ if (op_ == kLE)
+ return (value <= value_);
+ if (op_ == kGT)
+ return (value > value_);
+ if (op_ == kGE)
+ return (value >= value_);
+ DCHECK(op_ == kBetween);
+ return ((value_ <= value && value <= value2_) ||
+ (value2_ <= value && value <= value_));
+}
+
+bool GpuBlacklist::FloatInfo::IsValid() const {
+ return op_ != kUnknown;
+}
+
+// static
+GpuBlacklist::ScopedGpuBlacklistEntry
+GpuBlacklist::GpuBlacklistEntry::GetGpuBlacklistEntryFromValue(
+ const DictionaryValue* value, bool top_level) {
+ DCHECK(value);
+ ScopedGpuBlacklistEntry entry(new GpuBlacklistEntry());
+
+ size_t dictionary_entry_count = 0;
+
+ if (top_level) {
+ uint32 id;
+ if (!value->GetInteger("id", reinterpret_cast<int*>(&id)) ||
+ !entry->SetId(id)) {
+ LOG(WARNING) << "Malformed id entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+
+ bool disabled;
+ if (value->GetBoolean("disabled", &disabled)) {
+ entry->SetDisabled(disabled);
+ dictionary_entry_count++;
+ }
+ }
+
+ std::string description;
+ if (value->GetString("description", &description)) {
+ entry->description_ = description;
+ dictionary_entry_count++;
+ } else {
+ entry->description_ = "The GPU is unavailable for an unexplained reason.";
+ }
+
+ const ListValue* cr_bugs;
+ if (value->GetList("cr_bugs", &cr_bugs)) {
+ for (size_t i = 0; i < cr_bugs->GetSize(); ++i) {
+ int bug_id;
+ if (cr_bugs->GetInteger(i, &bug_id)) {
+ entry->cr_bugs_.push_back(bug_id);
+ } else {
+ LOG(WARNING) << "Malformed cr_bugs entry " << entry->id();
+ return NULL;
+ }
+ }
+ dictionary_entry_count++;
+ }
+
+ const ListValue* webkit_bugs;
+ if (value->GetList("webkit_bugs", &webkit_bugs)) {
+ for (size_t i = 0; i < webkit_bugs->GetSize(); ++i) {
+ int bug_id;
+ if (webkit_bugs->GetInteger(i, &bug_id)) {
+ entry->webkit_bugs_.push_back(bug_id);
+ } else {
+ LOG(WARNING) << "Malformed webkit_bugs entry " << entry->id();
+ return NULL;
+ }
+ }
+ dictionary_entry_count++;
+ }
+
+ const DictionaryValue* os_value = NULL;
+ if (value->GetDictionary("os", &os_value)) {
+ std::string os_type;
+ std::string os_version_op = "any";
+ std::string os_version_string;
+ std::string os_version_string2;
+ os_value->GetString("type", &os_type);
+ const DictionaryValue* os_version_value = NULL;
+ if (os_value->GetDictionary("version", &os_version_value)) {
+ os_version_value->GetString("op", &os_version_op);
+ os_version_value->GetString("number", &os_version_string);
+ os_version_value->GetString("number2", &os_version_string2);
+ }
+ if (!entry->SetOsInfo(os_type, os_version_op, os_version_string,
+ os_version_string2)) {
+ LOG(WARNING) << "Malformed os entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ std::string vendor_id;
+ if (value->GetString("vendor_id", &vendor_id)) {
+ if (!entry->SetVendorId(vendor_id)) {
+ LOG(WARNING) << "Malformed vendor_id entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const ListValue* device_id_list;
+ if (value->GetList("device_id", &device_id_list)) {
+ for (size_t i = 0; i < device_id_list->GetSize(); ++i) {
+ std::string device_id;
+ if (!device_id_list->GetString(i, &device_id) ||
+ !entry->AddDeviceId(device_id)) {
+ LOG(WARNING) << "Malformed device_id entry " << entry->id();
+ return NULL;
+ }
+ }
+ dictionary_entry_count++;
+ }
+
+ std::string multi_gpu_style;
+ if (value->GetString("multi_gpu_style", &multi_gpu_style)) {
+ if (!entry->SetMultiGpuStyle(multi_gpu_style)) {
+ LOG(WARNING) << "Malformed multi_gpu_style entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ std::string multi_gpu_category;
+ if (value->GetString("multi_gpu_category", &multi_gpu_category)) {
+ if (!entry->SetMultiGpuCategory(multi_gpu_category)) {
+ LOG(WARNING) << "Malformed multi_gpu_category entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const DictionaryValue* driver_vendor_value = NULL;
+ if (value->GetDictionary("driver_vendor", &driver_vendor_value)) {
+ std::string vendor_op;
+ std::string vendor_value;
+ driver_vendor_value->GetString("op", &vendor_op);
+ driver_vendor_value->GetString("value", &vendor_value);
+ if (!entry->SetDriverVendorInfo(vendor_op, vendor_value)) {
+ LOG(WARNING) << "Malformed driver_vendor entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const DictionaryValue* driver_version_value = NULL;
+ if (value->GetDictionary("driver_version", &driver_version_value)) {
+ std::string driver_version_op = "any";
+ std::string driver_version_style;
+ std::string driver_version_string;
+ std::string driver_version_string2;
+ driver_version_value->GetString("op", &driver_version_op);
+ driver_version_value->GetString("style", &driver_version_style);
+ driver_version_value->GetString("number", &driver_version_string);
+ driver_version_value->GetString("number2", &driver_version_string2);
+ if (!entry->SetDriverVersionInfo(driver_version_op,
+ driver_version_style,
+ driver_version_string,
+ driver_version_string2)) {
+ LOG(WARNING) << "Malformed driver_version entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const DictionaryValue* driver_date_value = NULL;
+ if (value->GetDictionary("driver_date", &driver_date_value)) {
+ std::string driver_date_op = "any";
+ std::string driver_date_string;
+ std::string driver_date_string2;
+ driver_date_value->GetString("op", &driver_date_op);
+ driver_date_value->GetString("number", &driver_date_string);
+ driver_date_value->GetString("number2", &driver_date_string2);
+ if (!entry->SetDriverDateInfo(driver_date_op, driver_date_string,
+ driver_date_string2)) {
+ LOG(WARNING) << "Malformed driver_date entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const DictionaryValue* gl_vendor_value = NULL;
+ if (value->GetDictionary("gl_vendor", &gl_vendor_value)) {
+ std::string vendor_op;
+ std::string vendor_value;
+ gl_vendor_value->GetString("op", &vendor_op);
+ gl_vendor_value->GetString("value", &vendor_value);
+ if (!entry->SetGLVendorInfo(vendor_op, vendor_value)) {
+ LOG(WARNING) << "Malformed gl_vendor entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const DictionaryValue* gl_renderer_value = NULL;
+ if (value->GetDictionary("gl_renderer", &gl_renderer_value)) {
+ std::string renderer_op;
+ std::string renderer_value;
+ gl_renderer_value->GetString("op", &renderer_op);
+ gl_renderer_value->GetString("value", &renderer_value);
+ if (!entry->SetGLRendererInfo(renderer_op, renderer_value)) {
+ LOG(WARNING) << "Malformed gl_renderer entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const DictionaryValue* perf_graphics_value = NULL;
+ if (value->GetDictionary("perf_graphics", &perf_graphics_value)) {
+ std::string op;
+ std::string float_value;
+ std::string float_value2;
+ perf_graphics_value->GetString("op", &op);
+ perf_graphics_value->GetString("value", &float_value);
+ perf_graphics_value->GetString("value2", &float_value2);
+ if (!entry->SetPerfGraphicsInfo(op, float_value, float_value2)) {
+ LOG(WARNING) << "Malformed perf_graphics entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const DictionaryValue* perf_gaming_value = NULL;
+ if (value->GetDictionary("perf_gaming", &perf_gaming_value)) {
+ std::string op;
+ std::string float_value;
+ std::string float_value2;
+ perf_gaming_value->GetString("op", &op);
+ perf_gaming_value->GetString("value", &float_value);
+ perf_gaming_value->GetString("value2", &float_value2);
+ if (!entry->SetPerfGamingInfo(op, float_value, float_value2)) {
+ LOG(WARNING) << "Malformed perf_gaming entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ const DictionaryValue* perf_overall_value = NULL;
+ if (value->GetDictionary("perf_overall", &perf_overall_value)) {
+ std::string op;
+ std::string float_value;
+ std::string float_value2;
+ perf_overall_value->GetString("op", &op);
+ perf_overall_value->GetString("value", &float_value);
+ perf_overall_value->GetString("value2", &float_value2);
+ if (!entry->SetPerfOverallInfo(op, float_value, float_value2)) {
+ LOG(WARNING) << "Malformed perf_overall entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ if (top_level) {
+ const ListValue* blacklist_value = NULL;
+ if (!value->GetList("blacklist", &blacklist_value)) {
+ LOG(WARNING) << "Malformed blacklist entry " << entry->id();
+ return NULL;
+ }
+ std::vector<std::string> blacklist;
+ for (size_t i = 0; i < blacklist_value->GetSize(); ++i) {
+ std::string feature;
+ if (blacklist_value->GetString(i, &feature)) {
+ blacklist.push_back(feature);
+ } else {
+ LOG(WARNING) << "Malformed blacklist entry " << entry->id();
+ return NULL;
+ }
+ }
+ if (!entry->SetBlacklistedFeatures(blacklist)) {
+ LOG(WARNING) << "Malformed blacklist entry " << entry->id();
+ return NULL;
+ }
+ dictionary_entry_count++;
+ }
+
+ if (top_level) {
+ const ListValue* exception_list_value = NULL;
+ if (value->GetList("exceptions", &exception_list_value)) {
+ for (size_t i = 0; i < exception_list_value->GetSize(); ++i) {
+ const DictionaryValue* exception_value = NULL;
+ if (!exception_list_value->GetDictionary(i, &exception_value)) {
+ LOG(WARNING) << "Malformed exceptions entry " << entry->id();
+ return NULL;
+ }
+ ScopedGpuBlacklistEntry exception(
+ GetGpuBlacklistEntryFromValue(exception_value, false));
+ if (exception == NULL) {
+ LOG(WARNING) << "Malformed exceptions entry " << entry->id();
+ return NULL;
+ }
+ if (exception->contains_unknown_fields_) {
+ LOG(WARNING) << "Exception with unknown fields " << entry->id();
+ entry->contains_unknown_fields_ = true;
+ } else {
+ entry->AddException(exception);
+ }
+ }
+ dictionary_entry_count++;
+ }
+
+ const DictionaryValue* browser_version_value = NULL;
+ // browser_version is processed in LoadGpuBlacklist().
+ if (value->GetDictionary("browser_version", &browser_version_value))
+ dictionary_entry_count++;
+ }
+
+ if (value->size() != dictionary_entry_count) {
+ LOG(WARNING) << "Entry with unknown fields " << entry->id();
+ entry->contains_unknown_fields_ = true;
+ }
+ return entry;
+}
+
+GpuBlacklist::GpuBlacklistEntry::GpuBlacklistEntry()
+ : id_(0),
+ disabled_(false),
+ vendor_id_(0),
+ multi_gpu_style_(kMultiGpuStyleNone),
+ multi_gpu_category_(kMultiGpuCategoryPrimary),
+ feature_type_(content::GPU_FEATURE_TYPE_UNKNOWN),
+ contains_unknown_fields_(false),
+ contains_unknown_features_(false) {
+}
+
+GpuBlacklist::GpuBlacklistEntry::~GpuBlacklistEntry() { }
+
+bool GpuBlacklist::GpuBlacklistEntry::SetId(uint32 id) {
+ if (id != 0) {
+ id_ = id;
+ return true;
+ }
+ return false;
+}
+
+void GpuBlacklist::GpuBlacklistEntry::SetDisabled(bool disabled) {
+ disabled_ = disabled;
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::SetOsInfo(
+ const std::string& os,
+ const std::string& version_op,
+ const std::string& version_string,
+ const std::string& version_string2) {
+ os_info_.reset(new OsInfo(os, version_op, version_string, version_string2));
+ return os_info_->IsValid();
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::SetVendorId(
+ const std::string& vendor_id_string) {
+ vendor_id_ = 0;
+ return base::HexStringToInt(vendor_id_string,
+ reinterpret_cast<int*>(&vendor_id_));
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::AddDeviceId(
+ const std::string& device_id_string) {
+ uint32 device_id = 0;
+ if (base::HexStringToInt(device_id_string,
+ reinterpret_cast<int*>(&device_id))) {
+ device_id_list_.push_back(device_id);
+ return true;
+ }
+ return false;
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::SetMultiGpuStyle(
+ const std::string& multi_gpu_style_string) {
+ MultiGpuStyle style = StringToMultiGpuStyle(multi_gpu_style_string);
+ if (style == kMultiGpuStyleNone)
+ return false;
+ multi_gpu_style_ = style;
+ return true;
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::SetMultiGpuCategory(
+ const std::string& multi_gpu_category_string) {
+ MultiGpuCategory category =
+ StringToMultiGpuCategory(multi_gpu_category_string);
+ if (category == kMultiGpuCategoryNone)
+ return false;
+ multi_gpu_category_ = category;
+ return true;
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::SetDriverVendorInfo(
+ const std::string& vendor_op,
+ const std::string& vendor_value) {
+ driver_vendor_info_.reset(
+ new StringInfo(vendor_op, vendor_value));
+ return driver_vendor_info_->IsValid();
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::SetDriverVersionInfo(
+ const std::string& version_op,
+ const std::string& version_style,
+ const std::string& version_string,
+ const std::string& version_string2) {
+ driver_version_info_.reset(new VersionInfo(
+ version_op, version_style, version_string, version_string2));
+ return driver_version_info_->IsValid();
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::SetDriverDateInfo(
+ const std::string& date_op,
+ const std::string& date_string,
+ const std::string& date_string2) {
+ driver_date_info_.reset(
+ new VersionInfo(date_op, "", date_string, date_string2));
+ return driver_date_info_->IsValid();
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::SetGLVendorInfo(
+ const std::string& vendor_op,
+ const std::string& vendor_value) {
+ gl_vendor_info_.reset(
+ new StringInfo(vendor_op, vendor_value));
+ return gl_vendor_info_->IsValid();
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::SetGLRendererInfo(
+ const std::string& renderer_op,
+ const std::string& renderer_value) {
+ gl_renderer_info_.reset(
+ new StringInfo(renderer_op, renderer_value));
+ return gl_renderer_info_->IsValid();
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::SetPerfGraphicsInfo(
+ const std::string& op,
+ const std::string& float_string,
+ const std::string& float_string2) {
+ perf_graphics_info_.reset(
+ new FloatInfo(op, float_string, float_string2));
+ return perf_graphics_info_->IsValid();
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::SetPerfGamingInfo(
+ const std::string& op,
+ const std::string& float_string,
+ const std::string& float_string2) {
+ perf_gaming_info_.reset(
+ new FloatInfo(op, float_string, float_string2));
+ return perf_gaming_info_->IsValid();
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::SetPerfOverallInfo(
+ const std::string& op,
+ const std::string& float_string,
+ const std::string& float_string2) {
+ perf_overall_info_.reset(
+ new FloatInfo(op, float_string, float_string2));
+ return perf_overall_info_->IsValid();
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::SetBlacklistedFeatures(
+ const std::vector<std::string>& blacklisted_features) {
+ size_t size = blacklisted_features.size();
+ if (size == 0)
+ return false;
+ int feature_type = content::GPU_FEATURE_TYPE_UNKNOWN;
+ for (size_t i = 0; i < size; ++i) {
+ GpuFeatureType type =
+ gpu_util::StringToGpuFeatureType(blacklisted_features[i]);
+ switch (type) {
+ case content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS:
+ case content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING:
+ case content::GPU_FEATURE_TYPE_WEBGL:
+ case content::GPU_FEATURE_TYPE_MULTISAMPLING:
+ case content::GPU_FEATURE_TYPE_FLASH3D:
+ case content::GPU_FEATURE_TYPE_FLASH_STAGE3D:
+ case content::GPU_FEATURE_TYPE_TEXTURE_SHARING:
+ case content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE:
+ case content::GPU_FEATURE_TYPE_ALL:
+ feature_type |= type;
+ break;
+ case content::GPU_FEATURE_TYPE_UNKNOWN:
+ contains_unknown_features_ = true;
+ break;
+ }
+ }
+ feature_type_ = static_cast<GpuFeatureType>(feature_type);
+ return true;
+}
+
+void GpuBlacklist::GpuBlacklistEntry::AddException(
+ ScopedGpuBlacklistEntry exception) {
+ exceptions_.push_back(exception);
+}
+
+// static
+GpuBlacklist::GpuBlacklistEntry::MultiGpuStyle
+GpuBlacklist::GpuBlacklistEntry::StringToMultiGpuStyle(
+ const std::string& style) {
+ if (style == kMultiGpuStyleStringOptimus)
+ return kMultiGpuStyleOptimus;
+ if (style == kMultiGpuStyleStringAMDSwitchable)
+ return kMultiGpuStyleAMDSwitchable;
+ return kMultiGpuStyleNone;
+}
+
+// static
+GpuBlacklist::GpuBlacklistEntry::MultiGpuCategory
+GpuBlacklist::GpuBlacklistEntry::StringToMultiGpuCategory(
+ const std::string& category) {
+ if (category == kMultiGpuCategoryStringPrimary)
+ return kMultiGpuCategoryPrimary;
+ if (category == kMultiGpuCategoryStringSecondary)
+ return kMultiGpuCategorySecondary;
+ if (category == kMultiGpuCategoryStringAny)
+ return kMultiGpuCategoryAny;
+ return kMultiGpuCategoryNone;
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::Contains(
+ OsType os_type, const Version& os_version,
+ const content::GPUInfo& gpu_info) const {
+ DCHECK(os_type != kOsAny);
+ if (os_info_.get() != NULL && !os_info_->Contains(os_type, os_version))
+ return false;
+ bool is_not_primary_gpu =
+ GpuUnmatched(vendor_id_, device_id_list_, gpu_info.gpu);
+ bool is_not_secondary_gpu = true;
+ for (size_t i = 0; i < gpu_info.secondary_gpus.size(); ++i) {
+ is_not_secondary_gpu = is_not_secondary_gpu &&
+ GpuUnmatched(vendor_id_, device_id_list_, gpu_info.secondary_gpus[i]);
+ }
+ switch (multi_gpu_category_) {
+ case kMultiGpuCategoryPrimary:
+ if (is_not_primary_gpu)
+ return false;
+ break;
+ case kMultiGpuCategorySecondary:
+ if (is_not_secondary_gpu)
+ return false;
+ break;
+ case kMultiGpuCategoryAny:
+ if (is_not_primary_gpu && is_not_secondary_gpu)
+ return false;
+ break;
+ default:
+ break;
+ }
+ switch (multi_gpu_style_) {
+ case kMultiGpuStyleOptimus:
+ if (!gpu_info.optimus)
+ return false;
+ break;
+ case kMultiGpuStyleAMDSwitchable:
+ if (!gpu_info.amd_switchable)
+ return false;
+ break;
+ default:
+ break;
+ }
+ if (driver_vendor_info_.get() != NULL &&
+ !driver_vendor_info_->Contains(gpu_info.driver_vendor))
+ return false;
+ if (driver_version_info_.get() != NULL) {
+ std::string processed_driver_version;
+ if (driver_version_info_->IsLexical())
+ processed_driver_version = NumericalToLexical(gpu_info.driver_version);
+ else
+ processed_driver_version = gpu_info.driver_version;
+ Version driver_version(processed_driver_version);
+ if (!driver_version.IsValid() ||
+ !driver_version_info_->Contains(driver_version))
+ return false;
+ }
+ if (driver_date_info_.get() != NULL) {
+ Version driver_date;
+ GetDateFromString(gpu_info.driver_date, &driver_date);
+ if (!driver_date.IsValid() || !driver_date_info_->Contains(driver_date))
+ return false;
+ }
+ if (gl_vendor_info_.get() != NULL &&
+ !gl_vendor_info_->Contains(gpu_info.gl_vendor))
+ return false;
+ if (gl_renderer_info_.get() != NULL &&
+ !gl_renderer_info_->Contains(gpu_info.gl_renderer))
+ return false;
+ if (perf_graphics_info_.get() != NULL &&
+ (gpu_info.performance_stats.graphics == 0.0 ||
+ !perf_graphics_info_->Contains(gpu_info.performance_stats.graphics)))
+ return false;
+ if (perf_gaming_info_.get() != NULL &&
+ (gpu_info.performance_stats.gaming == 0.0 ||
+ !perf_gaming_info_->Contains(gpu_info.performance_stats.gaming)))
+ return false;
+ if (perf_overall_info_.get() != NULL &&
+ (gpu_info.performance_stats.overall == 0.0 ||
+ !perf_overall_info_->Contains(gpu_info.performance_stats.overall)))
+ return false;
+ for (size_t i = 0; i < exceptions_.size(); ++i) {
+ if (exceptions_[i]->Contains(os_type, os_version, gpu_info))
+ return false;
+ }
+ return true;
+}
+
+GpuBlacklist::OsType GpuBlacklist::GpuBlacklistEntry::GetOsType() const {
+ if (os_info_.get() == NULL)
+ return kOsAny;
+ return os_info_->type();
+}
+
+uint32 GpuBlacklist::GpuBlacklistEntry::id() const {
+ return id_;
+}
+
+bool GpuBlacklist::GpuBlacklistEntry::disabled() const {
+ return disabled_;
+}
+
+GpuFeatureType GpuBlacklist::GpuBlacklistEntry::GetGpuFeatureType() const {
+ return feature_type_;
+}
+
+GpuBlacklist::GpuBlacklist()
+ : max_entry_id_(0),
+ contains_unknown_fields_(false) {
+}
+
+GpuBlacklist::~GpuBlacklist() {
+ Clear();
+}
+
+bool GpuBlacklist::LoadGpuBlacklist(
+ const std::string& json_context, GpuBlacklist::OsFilter os_filter) {
+ const std::string browser_version_string = "0";
+ return LoadGpuBlacklist(browser_version_string, json_context, os_filter);
+}
+
+bool GpuBlacklist::LoadGpuBlacklist(
+ const std::string& browser_version_string,
+ const std::string& json_context,
+ GpuBlacklist::OsFilter os_filter) {
+ browser_version_.reset(new Version(browser_version_string));
+ DCHECK(browser_version_->IsValid());
+
+ scoped_ptr<Value> root;
+ root.reset(base::JSONReader::Read(json_context));
+ if (root.get() == NULL || !root->IsType(Value::TYPE_DICTIONARY))
+ return false;
+
+ DictionaryValue* root_dictionary = static_cast<DictionaryValue*>(root.get());
+ DCHECK(root_dictionary);
+ return LoadGpuBlacklist(*root_dictionary, os_filter);
+}
+
+bool GpuBlacklist::LoadGpuBlacklist(
+ const DictionaryValue& parsed_json, GpuBlacklist::OsFilter os_filter) {
+ std::vector<ScopedGpuBlacklistEntry> entries;
+
+ std::string version_string;
+ parsed_json.GetString("version", &version_string);
+ version_.reset(new Version(version_string));
+ if (!version_->IsValid())
+ return false;
+
+ const ListValue* list = NULL;
+ if (!parsed_json.GetList("entries", &list))
+ return false;
+
+ uint32 max_entry_id = 0;
+ bool contains_unknown_fields = false;
+ for (size_t i = 0; i < list->GetSize(); ++i) {
+ const DictionaryValue* list_item = NULL;
+ bool valid = list->GetDictionary(i, &list_item);
+ if (!valid || list_item == NULL)
+ return false;
+ // Check browser version compatibility: if the entry is not for the
+ // current browser version, don't process it.
+ BrowserVersionSupport browser_version_support =
+ IsEntrySupportedByCurrentBrowserVersion(list_item);
+ if (browser_version_support == kMalformed)
+ return false;
+ if (browser_version_support == kUnsupported)
+ continue;
+ DCHECK(browser_version_support == kSupported);
+ ScopedGpuBlacklistEntry entry(
+ GpuBlacklistEntry::GetGpuBlacklistEntryFromValue(list_item, true));
+ if (entry == NULL)
+ return false;
+ if (entry->id() > max_entry_id)
+ max_entry_id = entry->id();
+ // If an unknown field is encountered, skip the entry; if an unknown
+ // feature is encountered, ignore the feature, but keep the entry.
+ if (entry->contains_unknown_fields()) {
+ contains_unknown_fields = true;
+ continue;
+ }
+ if (entry->contains_unknown_features())
+ contains_unknown_fields = true;
+ entries.push_back(entry);
+ }
+
+ Clear();
+ OsType my_os = GetOsType();
+ for (size_t i = 0; i < entries.size(); ++i) {
+ OsType entry_os = entries[i]->GetOsType();
+ if (os_filter == GpuBlacklist::kAllOs ||
+ entry_os == kOsAny || entry_os == my_os)
+ blacklist_.push_back(entries[i]);
+ }
+ max_entry_id_ = max_entry_id;
+ contains_unknown_fields_ = contains_unknown_fields;
+ return true;
+}
+
+GpuFeatureType GpuBlacklist::DetermineGpuFeatureType(
+ GpuBlacklist::OsType os,
+ Version* os_version,
+ const content::GPUInfo& gpu_info) {
+ active_entries_.clear();
+ int type = 0;
+
+ if (os == kOsAny)
+ os = GetOsType();
+ scoped_ptr<Version> my_os_version;
+ if (os_version == NULL) {
+ std::string version_string = base::SysInfo::OperatingSystemVersion();
+ size_t pos = version_string.find_first_not_of("0123456789.");
+ if (pos != std::string::npos)
+ version_string = version_string.substr(0, pos);
+ my_os_version.reset(new Version(version_string));
+ os_version = my_os_version.get();
+ }
+ DCHECK(os_version != NULL);
+
+ for (size_t i = 0; i < blacklist_.size(); ++i) {
+ if (blacklist_[i]->Contains(os, *os_version, gpu_info)) {
+ if (!blacklist_[i]->disabled())
+ type |= blacklist_[i]->GetGpuFeatureType();
+ active_entries_.push_back(blacklist_[i]);
+ }
+ }
+ return static_cast<GpuFeatureType>(type);
+}
+
+void GpuBlacklist::GetGpuFeatureTypeEntries(
+ content::GpuFeatureType feature,
+ std::vector<uint32>& entry_ids,
+ bool disabled) const {
+ entry_ids.clear();
+ for (size_t i = 0; i < active_entries_.size(); ++i) {
+ if (((feature & active_entries_[i]->GetGpuFeatureType()) != 0) &&
+ disabled == active_entries_[i]->disabled())
+ entry_ids.push_back(active_entries_[i]->id());
+ }
+}
+
+void GpuBlacklist::GetBlacklistReasons(ListValue* problem_list) const {
+ DCHECK(problem_list);
+ for (size_t i = 0; i < active_entries_.size(); ++i) {
+ GpuBlacklistEntry* entry = active_entries_[i];
+ if (entry->disabled())
+ continue;
+ DictionaryValue* problem = new DictionaryValue();
+
+ problem->SetString("description", entry->description());
+
+ ListValue* cr_bugs = new ListValue();
+ for (size_t j = 0; j < entry->cr_bugs().size(); ++j)
+ cr_bugs->Append(Value::CreateIntegerValue(entry->cr_bugs()[j]));
+ problem->Set("crBugs", cr_bugs);
+
+ ListValue* webkit_bugs = new ListValue();
+ for (size_t j = 0; j < entry->webkit_bugs().size(); ++j) {
+ webkit_bugs->Append(Value::CreateIntegerValue(
+ entry->webkit_bugs()[j]));
+ }
+ problem->Set("webkitBugs", webkit_bugs);
+
+ problem_list->Append(problem);
+ }
+}
+
+size_t GpuBlacklist::num_entries() const {
+ return blacklist_.size();
+}
+
+uint32 GpuBlacklist::max_entry_id() const {
+ return max_entry_id_;
+}
+
+std::string GpuBlacklist::GetVersion() const {
+ if (version_.get() == NULL)
+ return std::string();
+ const std::vector<uint16>& components_reference = version_->components();
+ if (components_reference.size() != 2)
+ return std::string();
+
+ std::string version_string =
+ base::UintToString(static_cast<unsigned>(components_reference[0])) +
+ "." +
+ base::UintToString(static_cast<unsigned>(components_reference[1]));
+ return version_string;
+}
+
+GpuBlacklist::OsType GpuBlacklist::GetOsType() {
+#if defined(OS_CHROMEOS)
+ return kOsChromeOS;
+#elif defined(OS_WIN)
+ return kOsWin;
+#elif defined(OS_LINUX) || defined(OS_OPENBSD)
+ return kOsLinux;
+#elif defined(OS_MACOSX)
+ return kOsMacosx;
+#else
+ return kOsUnknown;
+#endif
+}
+
+void GpuBlacklist::Clear() {
+ blacklist_.clear();
+ active_entries_.clear();
+ max_entry_id_ = 0;
+ contains_unknown_fields_ = false;
+}
+
+GpuBlacklist::BrowserVersionSupport
+GpuBlacklist::IsEntrySupportedByCurrentBrowserVersion(
+ const DictionaryValue* value) {
+ DCHECK(value);
+ const DictionaryValue* browser_version_value = NULL;
+ if (value->GetDictionary("browser_version", &browser_version_value)) {
+ std::string version_op = "any";
+ std::string version_string;
+ std::string version_string2;
+ browser_version_value->GetString("op", &version_op);
+ browser_version_value->GetString("number", &version_string);
+ browser_version_value->GetString("number2", &version_string2);
+ scoped_ptr<VersionInfo> browser_version_info;
+ browser_version_info.reset(
+ new VersionInfo(version_op, "", version_string, version_string2));
+ if (!browser_version_info->IsValid())
+ return kMalformed;
+ if (browser_version_info->Contains(*browser_version_))
+ return kSupported;
+ return kUnsupported;
+ }
+ return kSupported;
+}
+
+// static
+GpuBlacklist::NumericOp GpuBlacklist::StringToNumericOp(
+ const std::string& op) {
+ if (op == "=")
+ return kEQ;
+ if (op == "<")
+ return kLT;
+ if (op == "<=")
+ return kLE;
+ if (op == ">")
+ return kGT;
+ if (op == ">=")
+ return kGE;
+ if (op == "any")
+ return kAny;
+ if (op == "between")
+ return kBetween;
+ return kUnknown;
+}
diff --git a/content/browser/gpu/gpu_blacklist.h b/content/browser/gpu/gpu_blacklist.h
new file mode 100644
index 0000000..61801c3
--- /dev/null
+++ b/content/browser/gpu/gpu_blacklist.h
@@ -0,0 +1,401 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_GPU_GPU_BLACKLIST_H_
+#define CONTENT_BROWSER_GPU_GPU_BLACKLIST_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "content/common/content_export.h"
+#include "content/public/common/gpu_feature_type.h"
+
+class Version;
+
+namespace content {
+struct GPUInfo;
+}
+
+class CONTENT_EXPORT GpuBlacklist {
+ public:
+ enum OsType {
+ kOsLinux,
+ kOsMacosx,
+ kOsWin,
+ kOsChromeOS,
+ kOsAny,
+ kOsUnknown
+ };
+
+ enum OsFilter {
+ // In loading, ignore all entries that belong to other OS.
+ kCurrentOsOnly,
+ // In loading, keep all entries. This is for testing only.
+ kAllOs
+ };
+
+ GpuBlacklist();
+ virtual ~GpuBlacklist();
+
+ // Loads blacklist information from a json file.
+ // If failed, the current GpuBlacklist is un-touched.
+ bool LoadGpuBlacklist(const std::string& json_context, OsFilter os_filter);
+ bool LoadGpuBlacklist(const std::string& browser_version_string,
+ const std::string& json_context,
+ OsFilter os_filter);
+
+ // Collects system information and combines them with gpu_info and blacklist
+ // information to determine gpu feature flags.
+ // If os is kOsAny, use the current OS; if os_version is null, use the
+ // current OS version.
+ content::GpuFeatureType DetermineGpuFeatureType(
+ OsType os, Version* os_version, const content::GPUInfo& gpu_info);
+
+ // Collects the active entries that set the "feature" flag from the last
+ // DetermineGpuFeatureType() call. This tells which entries are responsible
+ // for raising a certain flag, i.e, for blacklisting a certain feature.
+ // Examples of "feature":
+ // GPU_FEATURE_TYPE_ALL - any of the supported features;
+ // GPU_FEATURE_TYPE_WEBGL - a single feature;
+ // GPU_FEATURE_TYPE_WEBGL | GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
+ // - two features.
+ // If disabled set to true, return entries that are disabled; otherwise,
+ // return enabled entries.
+ void GetGpuFeatureTypeEntries(content::GpuFeatureType feature,
+ std::vector<uint32>& entry_ids,
+ bool disabled) const;
+
+ // Returns the description and bugs from active entries from the last
+ // DetermineGpuFeatureType() call.
+ //
+ // Each problems has:
+ // {
+ // "description": "Your GPU is too old",
+ // "crBugs": [1234],
+ // "webkitBugs": []
+ // }
+ void GetBlacklistReasons(ListValue* problem_list) const;
+
+ // Return the largest entry id. This is used for histogramming.
+ uint32 max_entry_id() const;
+
+ // Returns the version of the current blacklist.
+ std::string GetVersion() const;
+
+ private:
+ friend class GpuBlacklistTest;
+ FRIEND_TEST_ALL_PREFIXES(GpuBlacklistTest, ChromeVersionEntry);
+ FRIEND_TEST_ALL_PREFIXES(GpuBlacklistTest, CurrentBlacklistValidation);
+ FRIEND_TEST_ALL_PREFIXES(GpuBlacklistTest, UnknownField);
+ FRIEND_TEST_ALL_PREFIXES(GpuBlacklistTest, UnknownExceptionField);
+ FRIEND_TEST_ALL_PREFIXES(GpuBlacklistTest, UnknownFeature);
+
+ enum BrowserVersionSupport {
+ kSupported,
+ kUnsupported,
+ kMalformed
+ };
+
+ enum NumericOp {
+ kBetween, // <= * <=
+ kEQ, // =
+ kLT, // <
+ kLE, // <=
+ kGT, // >
+ kGE, // >=
+ kAny,
+ kUnknown // Indicates the data is invalid.
+ };
+
+ class VersionInfo {
+ public:
+ // If version_style is empty, it defaults to kNumerical.
+ VersionInfo(const std::string& version_op,
+ const std::string& version_style,
+ const std::string& version_string,
+ const std::string& version_string2);
+ ~VersionInfo();
+
+ // Determines if a given version is included in the VersionInfo range.
+ bool Contains(const Version& version) const;
+
+ // Determine if the version_style is lexical.
+ bool IsLexical() const;
+
+ // Determines if the VersionInfo contains valid information.
+ bool IsValid() const;
+
+ private:
+ enum VersionStyle {
+ kVersionStyleNumerical,
+ kVersionStyleLexical,
+ kVersionStyleUnknown
+ };
+
+ static VersionStyle StringToVersionStyle(const std::string& version_style);
+
+ NumericOp op_;
+ VersionStyle version_style_;
+ scoped_ptr<Version> version_;
+ scoped_ptr<Version> version2_;
+ };
+
+ class OsInfo {
+ public:
+ OsInfo(const std::string& os,
+ const std::string& version_op,
+ const std::string& version_string,
+ const std::string& version_string2);
+ ~OsInfo();
+
+ // Determines if a given os/version is included in the OsInfo set.
+ bool Contains(OsType type, const Version& version) const;
+
+ // Determines if the VersionInfo contains valid information.
+ bool IsValid() const;
+
+ OsType type() const;
+
+ // Maps string to OsType; returns kOsUnknown if it's not a valid os.
+ static OsType StringToOsType(const std::string& os);
+
+ private:
+ OsType type_;
+ scoped_ptr<VersionInfo> version_info_;
+ };
+
+ class StringInfo {
+ public:
+ StringInfo(const std::string& string_op, const std::string& string_value);
+
+ // Determines if a given string is included in the StringInfo.
+ bool Contains(const std::string& value) const;
+
+ // Determines if the StringInfo contains valid information.
+ bool IsValid() const;
+
+ private:
+ enum Op {
+ kContains,
+ kBeginWith,
+ kEndWith,
+ kEQ, // =
+ kUnknown // Indicates StringInfo data is invalid.
+ };
+
+ // Maps string to Op; returns kUnknown if it's not a valid Op.
+ static Op StringToOp(const std::string& string_op);
+
+ Op op_;
+ std::string value_;
+ };
+
+ class FloatInfo {
+ public:
+ FloatInfo(const std::string& float_op,
+ const std::string& float_value,
+ const std::string& float_value2);
+
+ // Determines if a given float is included in the FloatInfo.
+ bool Contains(float value) const;
+
+ // Determines if the FloatInfo contains valid information.
+ bool IsValid() const;
+
+ private:
+ NumericOp op_;
+ float value_;
+ float value2_;
+ };
+
+ class GpuBlacklistEntry;
+ typedef scoped_refptr<GpuBlacklistEntry> ScopedGpuBlacklistEntry;
+
+ class GpuBlacklistEntry : public base::RefCounted<GpuBlacklistEntry> {
+ public:
+ // Constructs GpuBlacklistEntry from DictionaryValue loaded from json.
+ // Top-level entry must have an id number. Others are exceptions.
+ static ScopedGpuBlacklistEntry GetGpuBlacklistEntryFromValue(
+ const base::DictionaryValue* value, bool top_level);
+
+ // Determines if a given os/gc/driver is included in the Entry set.
+ bool Contains(OsType os_type,
+ const Version& os_version,
+ const content::GPUInfo& gpu_info) const;
+
+ // Returns the OsType.
+ OsType GetOsType() const;
+
+ // Returns the entry's unique id. 0 is reserved.
+ uint32 id() const;
+
+ // Returns whether the entry is disabled.
+ bool disabled() const;
+
+ // Returns the description of the entry
+ const std::string& description() const { return description_; }
+
+ // Returns a list of Chromium and Webkit bugs applicable to this entry
+ const std::vector<int>& cr_bugs() const { return cr_bugs_; }
+ const std::vector<int>& webkit_bugs() const { return webkit_bugs_; }
+
+ // Returns the GpuFeatureType.
+ content::GpuFeatureType GetGpuFeatureType() const;
+
+ // Returns true if an unknown field is encountered.
+ bool contains_unknown_fields() const {
+ return contains_unknown_fields_;
+ }
+ // Returns true if an unknown blacklist feature is encountered.
+ bool contains_unknown_features() const {
+ return contains_unknown_features_;
+ }
+
+ private:
+ friend class base::RefCounted<GpuBlacklistEntry>;
+
+ enum MultiGpuStyle {
+ kMultiGpuStyleOptimus,
+ kMultiGpuStyleAMDSwitchable,
+ kMultiGpuStyleNone
+ };
+
+ enum MultiGpuCategory {
+ kMultiGpuCategoryPrimary,
+ kMultiGpuCategorySecondary,
+ kMultiGpuCategoryAny,
+ kMultiGpuCategoryNone
+ };
+
+ GpuBlacklistEntry();
+ ~GpuBlacklistEntry();
+
+ bool SetId(uint32 id);
+
+ void SetDisabled(bool disabled);
+
+ bool SetOsInfo(const std::string& os,
+ const std::string& version_op,
+ const std::string& version_string,
+ const std::string& version_string2);
+
+ bool SetVendorId(const std::string& vendor_id_string);
+
+ bool AddDeviceId(const std::string& device_id_string);
+
+ bool SetMultiGpuStyle(const std::string& multi_gpu_style_string);
+
+ bool SetMultiGpuCategory(const std::string& multi_gpu_category_string);
+
+ bool SetDriverVendorInfo(const std::string& vendor_op,
+ const std::string& vendor_value);
+
+ bool SetDriverVersionInfo(const std::string& version_op,
+ const std::string& version_style,
+ const std::string& version_string,
+ const std::string& version_string2);
+
+ bool SetDriverDateInfo(const std::string& date_op,
+ const std::string& date_string,
+ const std::string& date_string2);
+
+ bool SetGLVendorInfo(const std::string& vendor_op,
+ const std::string& vendor_value);
+
+ bool SetGLRendererInfo(const std::string& renderer_op,
+ const std::string& renderer_value);
+
+ bool SetPerfGraphicsInfo(const std::string& op,
+ const std::string& float_string,
+ const std::string& float_string2);
+
+ bool SetPerfGamingInfo(const std::string& op,
+ const std::string& float_string,
+ const std::string& float_string2);
+
+ bool SetPerfOverallInfo(const std::string& op,
+ const std::string& float_string,
+ const std::string& float_string2);
+
+ bool SetBlacklistedFeatures(
+ const std::vector<std::string>& blacklisted_features);
+
+ void AddException(ScopedGpuBlacklistEntry exception);
+
+ static MultiGpuStyle StringToMultiGpuStyle(const std::string& style);
+
+ static MultiGpuCategory StringToMultiGpuCategory(
+ const std::string& category);
+
+ uint32 id_;
+ bool disabled_;
+ std::string description_;
+ std::vector<int> cr_bugs_;
+ std::vector<int> webkit_bugs_;
+ scoped_ptr<OsInfo> os_info_;
+ uint32 vendor_id_;
+ std::vector<uint32> device_id_list_;
+ MultiGpuStyle multi_gpu_style_;
+ MultiGpuCategory multi_gpu_category_;
+ scoped_ptr<StringInfo> driver_vendor_info_;
+ scoped_ptr<VersionInfo> driver_version_info_;
+ scoped_ptr<VersionInfo> driver_date_info_;
+ scoped_ptr<StringInfo> gl_vendor_info_;
+ scoped_ptr<StringInfo> gl_renderer_info_;
+ scoped_ptr<FloatInfo> perf_graphics_info_;
+ scoped_ptr<FloatInfo> perf_gaming_info_;
+ scoped_ptr<FloatInfo> perf_overall_info_;
+ content::GpuFeatureType feature_type_;
+ std::vector<ScopedGpuBlacklistEntry> exceptions_;
+ bool contains_unknown_fields_;
+ bool contains_unknown_features_;
+ };
+
+ // Gets the current OS type.
+ static OsType GetOsType();
+
+ bool LoadGpuBlacklist(const base::DictionaryValue& parsed_json,
+ OsFilter os_filter);
+
+ void Clear();
+
+ // Check if the entry is supported by the current version of browser.
+ // By default, if there is no browser version information in the entry,
+ // return kSupported;
+ BrowserVersionSupport IsEntrySupportedByCurrentBrowserVersion(
+ const base::DictionaryValue* value);
+
+ // Returns the number of entries. This is only for tests.
+ size_t num_entries() const;
+
+ // Check if any entries contain unknown fields. This is only for tests.
+ bool contains_unknown_fields() const { return contains_unknown_fields_; }
+
+ static NumericOp StringToNumericOp(const std::string& op);
+
+ scoped_ptr<Version> version_;
+ std::vector<ScopedGpuBlacklistEntry> blacklist_;
+
+ scoped_ptr<Version> browser_version_;
+
+ // This records all the blacklist entries that are appliable to the current
+ // user machine. It is updated everytime DetermineGpuFeatureType() is
+ // called and is used later by GetGpuFeatureTypeEntries().
+ std::vector<ScopedGpuBlacklistEntry> active_entries_;
+
+ uint32 max_entry_id_;
+
+ bool contains_unknown_fields_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuBlacklist);
+};
+
+#endif // CONTENT_BROWSER_GPU_GPU_BLACKLIST_H_
+
diff --git a/content/browser/gpu/gpu_blacklist_unittest.cc b/content/browser/gpu/gpu_blacklist_unittest.cc
new file mode 100644
index 0000000..6e921b8
--- /dev/null
+++ b/content/browser/gpu/gpu_blacklist_unittest.cc
@@ -0,0 +1,984 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "base/base_paths.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
+#include "base/version.h"
+#include "content/browser/gpu/gpu_blacklist.h"
+#include "content/public/common/gpu_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using content::GpuFeatureType;
+
+class GpuBlacklistTest : public testing::Test {
+ public:
+ GpuBlacklistTest() { }
+
+ virtual ~GpuBlacklistTest() { }
+
+ const content::GPUInfo& gpu_info() const {
+ return gpu_info_;
+ }
+
+ GpuBlacklist* Create() {
+ return new GpuBlacklist();
+ }
+
+ protected:
+ void SetUp() {
+ gpu_info_.gpu.vendor_id = 0x10de;
+ gpu_info_.gpu.device_id = 0x0640;
+ gpu_info_.driver_vendor = "NVIDIA";
+ gpu_info_.driver_version = "1.6.18";
+ gpu_info_.driver_date = "7-14-2009";
+ gpu_info_.gl_vendor = "NVIDIA Corporation";
+ gpu_info_.gl_renderer = "NVIDIA GeForce GT 120 OpenGL Engine";
+ gpu_info_.performance_stats.graphics = 5.0;
+ gpu_info_.performance_stats.gaming = 5.0;
+ gpu_info_.performance_stats.overall = 5.0;
+ }
+
+ void TearDown() {
+ }
+
+ private:
+ content::GPUInfo gpu_info_;
+};
+
+TEST_F(GpuBlacklistTest, CurrentBlacklistValidation) {
+ FilePath data_file;
+ ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &data_file));
+ data_file =
+ data_file.Append(FILE_PATH_LITERAL("chrome"))
+ .Append(FILE_PATH_LITERAL("browser"))
+ .Append(FILE_PATH_LITERAL("resources"))
+ .Append(FILE_PATH_LITERAL("software_rendering_list.json"));
+ ASSERT_TRUE(file_util::PathExists(data_file));
+ int64 data_file_size64 = 0;
+ ASSERT_TRUE(file_util::GetFileSize(data_file, &data_file_size64));
+ int data_file_size = static_cast<int>(data_file_size64);
+ scoped_array<char> data(new char[data_file_size]);
+ ASSERT_EQ(file_util::ReadFile(data_file, data.get(), data_file_size),
+ data_file_size);
+ std::string json_string(data.get(), data_file_size);
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ json_string, GpuBlacklist::kAllOs));
+ EXPECT_FALSE(blacklist->contains_unknown_fields());
+}
+
+TEST_F(GpuBlacklistTest, DefaultBlacklistSettings) {
+ Version os_version("10.6.4");
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ // Default blacklist settings: all feature are allowed.
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+}
+
+TEST_F(GpuBlacklistTest, EmptyBlacklist) {
+ // Empty list: all features are allowed.
+ const std::string empty_list_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"2.5\",\n"
+ " \"entries\": [\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ empty_list_json, GpuBlacklist::kAllOs));
+ EXPECT_EQ(blacklist->GetVersion(), std::string("2.5"));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+}
+
+TEST_F(GpuBlacklistTest, DetailedEntryAndInvalidJson) {
+ // Blacklist accelerated_compositing with exact setting.
+ const std::string exact_list_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 5,\n"
+ " \"os\": {\n"
+ " \"type\": \"macosx\",\n"
+ " \"version\": {\n"
+ " \"op\": \"=\",\n"
+ " \"number\": \"10.6.4\"\n"
+ " }\n"
+ " },\n"
+ " \"vendor_id\": \"0x10de\",\n"
+ " \"device_id\": [\"0x0640\"],\n"
+ " \"driver_version\": {\n"
+ " \"op\": \"=\",\n"
+ " \"number\": \"1.6.18\"\n"
+ " },\n"
+ " \"blacklist\": [\n"
+ " \"accelerated_compositing\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ exact_list_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING);
+
+ // Invalid json input should not change the current blacklist settings.
+ const std::string invalid_json = "invalid";
+
+ EXPECT_FALSE(blacklist->LoadGpuBlacklist(
+ invalid_json, GpuBlacklist::kAllOs));
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING);
+ std::vector<uint32> entries;
+ bool disabled = false;
+ blacklist->GetGpuFeatureTypeEntries(
+ content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING, entries, disabled);
+ EXPECT_EQ(entries.size(), 1u);
+ EXPECT_EQ(entries[0], 5u);
+ blacklist->GetGpuFeatureTypeEntries(
+ content::GPU_FEATURE_TYPE_ALL, entries, disabled);
+ EXPECT_EQ(entries.size(), 1u);
+ EXPECT_EQ(entries[0], 5u);
+ EXPECT_EQ(blacklist->max_entry_id(), 5u);
+}
+
+TEST_F(GpuBlacklistTest, VendorOnAllOsEntry) {
+ // Blacklist a vendor on all OS.
+ const std::string vendor_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"vendor_id\": \"0x10de\",\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+
+ // Blacklist entries won't be filtered to the current OS only upon loading.
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ vendor_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsLinux, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX) || \
+ defined(OS_OPENBSD)
+ // Blacklist entries will be filtered to the current OS only upon loading.
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ vendor_json, GpuBlacklist::kCurrentOsOnly));
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsLinux, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+#endif
+}
+
+TEST_F(GpuBlacklistTest, VendorOnLinuxEntry) {
+ // Blacklist a vendor on Linux only.
+ const std::string vendor_linux_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"os\": {\n"
+ " \"type\": \"linux\"\n"
+ " },\n"
+ " \"vendor_id\": \"0x10de\",\n"
+ " \"blacklist\": [\n"
+ " \"accelerated_2d_canvas\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ vendor_linux_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsLinux, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS);
+}
+
+TEST_F(GpuBlacklistTest, AllExceptNVidiaOnLinuxEntry) {
+ // Blacklist all cards in Linux except NVIDIA.
+ const std::string linux_except_nvidia_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"os\": {\n"
+ " \"type\": \"linux\"\n"
+ " },\n"
+ " \"exceptions\": [\n"
+ " {\n"
+ " \"vendor_id\": \"0x10de\"\n"
+ " }\n"
+ " ],\n"
+ " \"blacklist\": [\n"
+ " \"accelerated_2d_canvas\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ linux_except_nvidia_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsLinux, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+}
+
+TEST_F(GpuBlacklistTest, AllExceptIntelOnLinuxEntry) {
+ // Blacklist all cards in Linux except Intel.
+ const std::string linux_except_intel_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"os\": {\n"
+ " \"type\": \"linux\"\n"
+ " },\n"
+ " \"exceptions\": [\n"
+ " {\n"
+ " \"vendor_id\": \"0x8086\"\n"
+ " }\n"
+ " ],\n"
+ " \"blacklist\": [\n"
+ " \"accelerated_2d_canvas\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ linux_except_intel_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsLinux, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS);
+}
+
+TEST_F(GpuBlacklistTest, DateOnWindowsEntry) {
+ // Blacklist all drivers earlier than 2010-01 in Windows.
+ const std::string date_windows_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"os\": {\n"
+ " \"type\": \"win\"\n"
+ " },\n"
+ " \"driver_date\": {\n"
+ " \"op\": \"<\",\n"
+ " \"number\": \"2010.1\"\n"
+ " },\n"
+ " \"blacklist\": [\n"
+ " \"accelerated_2d_canvas\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ date_windows_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsLinux, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS);
+}
+
+TEST_F(GpuBlacklistTest, MultipleDevicesEntry) {
+ const std::string devices_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"vendor_id\": \"0x10de\",\n"
+ " \"device_id\": [\"0x1023\", \"0x0640\"],\n"
+ " \"blacklist\": [\n"
+ " \"multisampling\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ devices_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_MULTISAMPLING);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_MULTISAMPLING);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsLinux, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_MULTISAMPLING);
+}
+
+TEST_F(GpuBlacklistTest, ChromeOSEntry) {
+ const std::string devices_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"os\": {\n"
+ " \"type\": \"chromeos\"\n"
+ " },\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ devices_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsChromeOS, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsLinux, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+}
+
+TEST_F(GpuBlacklistTest, ChromeVersionEntry) {
+ const std::string browser_version_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"browser_version\": {\n"
+ " \"op\": \">=\",\n"
+ " \"number\": \"10\"\n"
+ " },\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+
+ scoped_ptr<GpuBlacklist> blacklist9(Create());
+ EXPECT_TRUE(blacklist9->LoadGpuBlacklist(
+ "9.0", browser_version_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist9->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+
+ scoped_ptr<GpuBlacklist> blacklist10(Create());
+ EXPECT_TRUE(blacklist10->LoadGpuBlacklist(
+ "10.0", browser_version_json, GpuBlacklist::kAllOs));
+ type = blacklist10->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+}
+
+TEST_F(GpuBlacklistTest, MalformedVendor) {
+ // vendor_id is defined as list instead of string.
+ const std::string malformed_vendor_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"vendor_id\": \"[0x10de]\",\n"
+ " \"blacklist\": [\n"
+ " \"accelerated_2d_canvas\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+
+ EXPECT_FALSE(blacklist->LoadGpuBlacklist(
+ malformed_vendor_json, GpuBlacklist::kAllOs));
+}
+
+TEST_F(GpuBlacklistTest, UnknownField) {
+ const std::string unknown_field_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"unknown_field\": 0,\n"
+ " \"blacklist\": [\n"
+ " \"accelerated_2d_canvas\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"id\": 2,\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ unknown_field_json, GpuBlacklist::kAllOs));
+ EXPECT_EQ(1u, blacklist->num_entries());
+ EXPECT_TRUE(blacklist->contains_unknown_fields());
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+}
+
+TEST_F(GpuBlacklistTest, UnknownExceptionField) {
+ const std::string unknown_exception_field_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"unknown_field\": 0,\n"
+ " \"blacklist\": [\n"
+ " \"accelerated_compositing\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"id\": 2,\n"
+ " \"exceptions\": [\n"
+ " {\n"
+ " \"unknown_field\": 0\n"
+ " }\n"
+ " ],\n"
+ " \"blacklist\": [\n"
+ " \"accelerated_2d_canvas\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"id\": 3,\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ unknown_exception_field_json, GpuBlacklist::kAllOs));
+ EXPECT_EQ(1u, blacklist->num_entries());
+ EXPECT_TRUE(blacklist->contains_unknown_fields());
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+}
+
+TEST_F(GpuBlacklistTest, UnknownFeature) {
+ const std::string unknown_feature_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"blacklist\": [\n"
+ " \"accelerated_something\",\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ unknown_feature_json, GpuBlacklist::kAllOs));
+ EXPECT_EQ(1u, blacklist->num_entries());
+ EXPECT_TRUE(blacklist->contains_unknown_fields());
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+}
+
+TEST_F(GpuBlacklistTest, GlVendor) {
+ const std::string gl_vendor_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"gl_vendor\": {\n"
+ " \"op\": \"beginwith\",\n"
+ " \"value\": \"NVIDIA\"\n"
+ " },\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ gl_vendor_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+}
+
+TEST_F(GpuBlacklistTest, GlRenderer) {
+ const std::string gl_renderer_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"gl_renderer\": {\n"
+ " \"op\": \"contains\",\n"
+ " \"value\": \"GeForce\"\n"
+ " },\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ gl_renderer_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+}
+
+TEST_F(GpuBlacklistTest, PerfGraphics) {
+ const std::string json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"perf_graphics\": {\n"
+ " \"op\": \"<\",\n"
+ " \"value\": \"6.0\"\n"
+ " },\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+}
+
+TEST_F(GpuBlacklistTest, PerfGaming) {
+ const std::string json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"perf_gaming\": {\n"
+ " \"op\": \"<=\",\n"
+ " \"value\": \"4.0\"\n"
+ " },\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+}
+
+TEST_F(GpuBlacklistTest, PerfOverall) {
+ const std::string json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"perf_overall\": {\n"
+ " \"op\": \"between\",\n"
+ " \"value\": \"1.0\",\n"
+ " \"value2\": \"9.0\"\n"
+ " },\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+}
+
+TEST_F(GpuBlacklistTest, DisabledEntry) {
+ const std::string disabled_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"disabled\": true,\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ disabled_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsWin, &os_version, gpu_info());
+ EXPECT_EQ(type, 0);
+ std::vector<uint32> flag_entries;
+ bool disabled = false;
+ blacklist->GetGpuFeatureTypeEntries(
+ content::GPU_FEATURE_TYPE_ALL, flag_entries, disabled);
+ EXPECT_EQ(flag_entries.size(), 0u);
+ disabled = true;
+ blacklist->GetGpuFeatureTypeEntries(
+ content::GPU_FEATURE_TYPE_ALL, flag_entries, disabled);
+ EXPECT_EQ(flag_entries.size(), 1u);
+}
+
+TEST_F(GpuBlacklistTest, Optimus) {
+ const std::string optimus_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"os\": {\n"
+ " \"type\": \"linux\"\n"
+ " },\n"
+ " \"multi_gpu_style\": \"optimus\",\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+
+ content::GPUInfo gpu_info;
+ gpu_info.optimus = true;
+
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ optimus_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsLinux, &os_version, gpu_info);
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+}
+
+TEST_F(GpuBlacklistTest, AMDSwitchable) {
+ const std::string amd_switchable_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"os\": {\n"
+ " \"type\": \"macosx\"\n"
+ " },\n"
+ " \"multi_gpu_style\": \"amd_switchable\",\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+
+ content::GPUInfo gpu_info;
+ gpu_info.amd_switchable = true;
+
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ amd_switchable_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info);
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+}
+
+TEST_F(GpuBlacklistTest, LexicalDriverVersion) {
+ const std::string lexical_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"os\": {\n"
+ " \"type\": \"linux\"\n"
+ " },\n"
+ " \"vendor_id\": \"0x1002\",\n"
+ " \"driver_version\": {\n"
+ " \"op\": \"<\",\n"
+ " \"style\": \"lexical\",\n"
+ " \"number\": \"8.201\"\n"
+ " },\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+
+ content::GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x1002;
+
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ lexical_json, GpuBlacklist::kAllOs));
+
+ gpu_info.driver_version = "8.109";
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsLinux, &os_version, gpu_info);
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+
+ gpu_info.driver_version = "8.2";
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsLinux, &os_version, gpu_info);
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+
+ gpu_info.driver_version = "8.21";
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsLinux, &os_version, gpu_info);
+ EXPECT_EQ(type, 0);
+
+ gpu_info.driver_version = "8.2010";
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsLinux, &os_version, gpu_info);
+ EXPECT_EQ(type, 0);
+}
+
+TEST_F(GpuBlacklistTest, MultipleGPUsAny) {
+ const std::string multi_gpu_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"os\": {\n"
+ " \"type\": \"macosx\"\n"
+ " },\n"
+ " \"vendor_id\": \"0x8086\",\n"
+ " \"device_id\": [\"0x0166\"],\n"
+ " \"multi_gpu_category\": \"any\",\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+
+ content::GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x10de;
+ gpu_info.gpu.device_id = 0x0fd5;
+
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ multi_gpu_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info);
+ EXPECT_EQ(type, 0);
+
+ content::GPUInfo::GPUDevice gpu_device;
+ gpu_device.vendor_id = 0x8086;
+ gpu_device.device_id = 0x0166;
+ gpu_info.secondary_gpus.push_back(gpu_device);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info);
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+}
+
+TEST_F(GpuBlacklistTest, MultipleGPUsSecondary) {
+ const std::string multi_gpu_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"os\": {\n"
+ " \"type\": \"macosx\"\n"
+ " },\n"
+ " \"vendor_id\": \"0x8086\",\n"
+ " \"device_id\": [\"0x0166\"],\n"
+ " \"multi_gpu_category\": \"secondary\",\n"
+ " \"blacklist\": [\n"
+ " \"webgl\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+
+ content::GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x10de;
+ gpu_info.gpu.device_id = 0x0fd5;
+
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ multi_gpu_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info);
+ EXPECT_EQ(type, 0);
+
+ content::GPUInfo::GPUDevice gpu_device;
+ gpu_device.vendor_id = 0x8086;
+ gpu_device.device_id = 0x0166;
+ gpu_info.secondary_gpus.push_back(gpu_device);
+ type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info);
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_WEBGL);
+}
+
+TEST_F(GpuBlacklistTest, VideoDecode) {
+ const std::string video_decode_json =
+ "{\n"
+ " \"name\": \"gpu blacklist\",\n"
+ " \"version\": \"0.1\",\n"
+ " \"entries\": [\n"
+ " {\n"
+ " \"id\": 1,\n"
+ " \"os\": {\n"
+ " \"type\": \"macosx\"\n"
+ " },\n"
+ " \"vendor_id\": \"0x10de\",\n"
+ " \"device_id\": [\"0x0640\"],\n"
+ " \"blacklist\": [\n"
+ " \"accelerated_video_decode\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}";
+ Version os_version("10.6.4");
+
+ scoped_ptr<GpuBlacklist> blacklist(Create());
+ EXPECT_TRUE(blacklist->LoadGpuBlacklist(
+ video_decode_json, GpuBlacklist::kAllOs));
+ GpuFeatureType type = blacklist->DetermineGpuFeatureType(
+ GpuBlacklist::kOsMacosx, &os_version, gpu_info());
+ EXPECT_EQ(type, content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE);
+}
+
diff --git a/content/browser/gpu/gpu_data_manager_impl.cc b/content/browser/gpu/gpu_data_manager_impl.cc
index 44dfe6a..d1aef13 100644
--- a/content/browser/gpu/gpu_data_manager_impl.cc
+++ b/content/browser/gpu/gpu_data_manager_impl.cc
@@ -13,6 +13,7 @@
#include "base/values.h"
#include "base/version.h"
#include "content/browser/gpu/gpu_process_host.h"
+#include "content/browser/gpu/gpu_util.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/gpu/gpu_info_collector.h"
#include "content/public/browser/browser_thread.h"
@@ -58,14 +59,24 @@ GpuDataManagerImpl::GpuDataManagerImpl()
BlacklistCard();
}
-void GpuDataManagerImpl::InitializeGpuInfo() {
+void GpuDataManagerImpl::Initialize(
+ const std::string& browser_version_string,
+ const std::string& gpu_blacklist_json) {
content::GPUInfo gpu_info;
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSkipGpuDataLoading))
- gpu_info_collector::CollectPreliminaryGraphicsInfo(&gpu_info);
- else
- gpu_info.finalized = true;
+ gpu_info_collector::CollectPreliminaryGraphicsInfo(&gpu_info);
+
+ if (!gpu_blacklist_json.empty()) {
+ CHECK(!browser_version_string.empty());
+ gpu_blacklist_.reset(new GpuBlacklist());
+ bool succeed = gpu_blacklist_->LoadGpuBlacklist(
+ browser_version_string,
+ gpu_blacklist_json,
+ GpuBlacklist::kCurrentOsOnly);
+ CHECK(succeed);
+ }
+
UpdateGpuInfo(gpu_info);
+ UpdatePreliminaryBlacklistedFeatures();
}
GpuDataManagerImpl::~GpuDataManagerImpl() {
@@ -92,6 +103,15 @@ void GpuDataManagerImpl::UpdateGpuInfo(const content::GPUInfo& gpu_info) {
content::GetContentClient()->SetGpuInfo(gpu_info);
+ if (gpu_blacklist_.get()) {
+ GpuFeatureType feature_type = gpu_blacklist_->DetermineGpuFeatureType(
+ GpuBlacklist::kOsAny,
+ NULL,
+ GpuDataManager::GetInstance()->GetGPUInfo());
+ gpu_util::UpdateStats(gpu_blacklist_.get(), feature_type);
+ UpdateBlacklistedFeatures(feature_type);
+ }
+
{
base::AutoLock auto_lock(gpu_info_lock_);
gpu_info_ = gpu_info;
@@ -142,6 +162,12 @@ base::ListValue* GpuDataManagerImpl::GetLogMessages() const {
return value;
}
+std::string GpuDataManagerImpl::GetBlacklistVersion() const {
+ if (gpu_blacklist_.get())
+ return gpu_blacklist_->GetVersion();
+ return "0";
+}
+
GpuFeatureType GpuDataManagerImpl::GetBlacklistedFeatures() const {
if (software_rendering_) {
GpuFeatureType flags;
@@ -155,6 +181,13 @@ GpuFeatureType GpuDataManagerImpl::GetBlacklistedFeatures() const {
return gpu_feature_type_;
}
+base::ListValue* GpuDataManagerImpl::GetBlacklistReasons() const {
+ ListValue* reasons = new ListValue();
+ if (gpu_blacklist_.get())
+ gpu_blacklist_->GetBlacklistReasons(reasons);
+ return reasons;
+}
+
bool GpuDataManagerImpl::GpuAccessAllowed() const {
if (software_rendering_)
return true;
@@ -308,9 +341,7 @@ void GpuDataManagerImpl::AppendPluginCommandLine(
#endif
}
-void GpuDataManagerImpl::SetPreliminaryBlacklistedFeatures(
- GpuFeatureType feature_type) {
- UpdateBlacklistedFeatures(feature_type);
+void GpuDataManagerImpl::UpdatePreliminaryBlacklistedFeatures() {
preliminary_gpu_feature_type_ = gpu_feature_type_;
}
diff --git a/content/browser/gpu/gpu_data_manager_impl.h b/content/browser/gpu/gpu_data_manager_impl.h
index f7f0989..7015bc9 100644
--- a/content/browser/gpu/gpu_data_manager_impl.h
+++ b/content/browser/gpu/gpu_data_manager_impl.h
@@ -16,6 +16,7 @@
#include "base/observer_list_threadsafe.h"
#include "base/synchronization/lock.h"
#include "base/values.h"
+#include "content/browser/gpu/gpu_blacklist.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/gpu_info.h"
#include "content/public/common/gpu_memory_stats.h"
@@ -29,10 +30,12 @@ class CONTENT_EXPORT GpuDataManagerImpl
static GpuDataManagerImpl* GetInstance();
// GpuDataManager implementation.
- virtual void InitializeGpuInfo() OVERRIDE;
+ virtual void Initialize(
+ const std::string& browser_version_string,
+ const std::string& gpu_blacklist_json) OVERRIDE;
virtual content::GpuFeatureType GetBlacklistedFeatures() const OVERRIDE;
- virtual void SetPreliminaryBlacklistedFeatures(
- content::GpuFeatureType features) OVERRIDE;
+ virtual base::ListValue* GetBlacklistReasons() const OVERRIDE;
+ virtual std::string GetBlacklistVersion() const OVERRIDE;
virtual content::GPUInfo GetGPUInfo() const OVERRIDE;
virtual bool GpuAccessAllowed() const OVERRIDE;
virtual void RequestCompleteGpuInfoIfNeeded() OVERRIDE;
@@ -47,7 +50,8 @@ class CONTENT_EXPORT GpuDataManagerImpl
virtual void RemoveObserver(
content::GpuDataManagerObserver* observer) OVERRIDE;
- // Only update if the current GPUInfo is not finalized.
+ // Only update if the current GPUInfo is not finalized. If blacklist is
+ // loaded, run through blacklist and update blacklisted features.
void UpdateGpuInfo(const content::GPUInfo& gpu_info);
void UpdateVideoMemoryUsageStats(
@@ -91,16 +95,21 @@ class CONTENT_EXPORT GpuDataManagerImpl
GpuDataManagerImpl();
virtual ~GpuDataManagerImpl();
- // If flags hasn't been set and GPUInfo is available, run through blacklist
- // and compute the flags.
void UpdateBlacklistedFeatures(content::GpuFeatureType features);
+ // This should only be called once at initialization time, when preliminary
+ // gpu info is collected.
+ void UpdatePreliminaryBlacklistedFeatures();
+
// Notify all observers whenever there is a GPU info update.
void NotifyGpuInfoUpdate();
// Try to switch to software rendering, if possible and necessary.
void EnableSoftwareRenderingIfNecessary();
+ // Send UMA histograms about the disabled/enabled features.
+ void UpdateStats();
+
bool complete_gpu_info_already_requested_;
content::GpuFeatureType gpu_feature_type_;
@@ -109,6 +118,8 @@ class CONTENT_EXPORT GpuDataManagerImpl
content::GPUInfo gpu_info_;
mutable base::Lock gpu_info_lock_;
+ scoped_ptr<GpuBlacklist> gpu_blacklist_;
+
const scoped_refptr<GpuDataManagerObserverList> observer_list_;
ListValue log_messages_;
diff --git a/content/browser/gpu/gpu_data_manager_impl_unittest.cc b/content/browser/gpu/gpu_data_manager_impl_unittest.cc
index ea3d216..29b37c3 100644
--- a/content/browser/gpu/gpu_data_manager_impl_unittest.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_unittest.cc
@@ -69,8 +69,9 @@ TEST_F(GpuDataManagerImplTest, GpuSideBlacklisting) {
EXPECT_EQ(0, manager->GetBlacklistedFeatures());
EXPECT_TRUE(manager->GpuAccessAllowed());
- manager->SetPreliminaryBlacklistedFeatures(
+ manager->UpdateBlacklistedFeatures(
content::GPU_FEATURE_TYPE_WEBGL);
+ manager->UpdatePreliminaryBlacklistedFeatures();
EXPECT_TRUE(manager->GpuAccessAllowed());
EXPECT_EQ(content::GPU_FEATURE_TYPE_WEBGL,
manager->GetBlacklistedFeatures());
diff --git a/content/browser/gpu/gpu_util.cc b/content/browser/gpu/gpu_util.cc
new file mode 100644
index 0000000..267b2b4
--- /dev/null
+++ b/content/browser/gpu/gpu_util.cc
@@ -0,0 +1,223 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/gpu/gpu_util.h"
+
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/metrics/histogram.h"
+#include "base/string_util.h"
+#include "base/sys_info.h"
+#include "base/version.h"
+#include "content/browser/gpu/gpu_blacklist.h"
+#include "content/public/common/content_switches.h"
+
+using content::GpuFeatureType;
+
+namespace {
+
+const char kGpuFeatureNameAccelerated2dCanvas[] = "accelerated_2d_canvas";
+const char kGpuFeatureNameAcceleratedCompositing[] = "accelerated_compositing";
+const char kGpuFeatureNameWebgl[] = "webgl";
+const char kGpuFeatureNameMultisampling[] = "multisampling";
+const char kGpuFeatureNameFlash3d[] = "flash_3d";
+const char kGpuFeatureNameFlashStage3d[] = "flash_stage3d";
+const char kGpuFeatureNameTextureSharing[] = "texture_sharing";
+const char kGpuFeatureNameAcceleratedVideoDecode[] = "accelerated_video_decode";
+const char kGpuFeatureNameAll[] = "all";
+const char kGpuFeatureNameUnknown[] = "unknown";
+
+enum GpuFeatureStatus {
+ kGpuFeatureEnabled = 0,
+ kGpuFeatureBlacklisted = 1,
+ kGpuFeatureDisabled = 2, // disabled by user but not blacklisted
+ kGpuFeatureNumStatus
+};
+
+#if defined(OS_WIN)
+
+enum WinSubVersion {
+ kWinOthers = 0,
+ kWinXP,
+ kWinVista,
+ kWin7,
+ kNumWinSubVersions
+};
+
+int GetGpuBlacklistHistogramValueWin(GpuFeatureStatus status) {
+ static WinSubVersion sub_version = kNumWinSubVersions;
+ if (sub_version == kNumWinSubVersions) {
+ sub_version = kWinOthers;
+ std::string version_str = base::SysInfo::OperatingSystemVersion();
+ size_t pos = version_str.find_first_not_of("0123456789.");
+ if (pos != std::string::npos)
+ version_str = version_str.substr(0, pos);
+ Version os_version(version_str);
+ if (os_version.IsValid() && os_version.components().size() >= 2) {
+ const std::vector<uint16>& version_numbers = os_version.components();
+ if (version_numbers[0] == 5)
+ sub_version = kWinXP;
+ else if (version_numbers[0] == 6 && version_numbers[1] == 0)
+ sub_version = kWinVista;
+ else if (version_numbers[0] == 6 && version_numbers[1] == 1)
+ sub_version = kWin7;
+ }
+ }
+ int entry_index = static_cast<int>(sub_version) * kGpuFeatureNumStatus;
+ switch (status) {
+ case kGpuFeatureEnabled:
+ break;
+ case kGpuFeatureBlacklisted:
+ entry_index++;
+ break;
+ case kGpuFeatureDisabled:
+ entry_index += 2;
+ break;
+ }
+ return entry_index;
+}
+#endif // OS_WIN
+
+} // namespace
+
+namespace gpu_util {
+
+GpuFeatureType StringToGpuFeatureType(const std::string& feature_string) {
+ if (feature_string == kGpuFeatureNameAccelerated2dCanvas)
+ return content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS;
+ else if (feature_string == kGpuFeatureNameAcceleratedCompositing)
+ return content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING;
+ else if (feature_string == kGpuFeatureNameWebgl)
+ return content::GPU_FEATURE_TYPE_WEBGL;
+ else if (feature_string == kGpuFeatureNameMultisampling)
+ return content::GPU_FEATURE_TYPE_MULTISAMPLING;
+ else if (feature_string == kGpuFeatureNameFlash3d)
+ return content::GPU_FEATURE_TYPE_FLASH3D;
+ else if (feature_string == kGpuFeatureNameFlashStage3d)
+ return content::GPU_FEATURE_TYPE_FLASH_STAGE3D;
+ else if (feature_string == kGpuFeatureNameTextureSharing)
+ return content::GPU_FEATURE_TYPE_TEXTURE_SHARING;
+ else if (feature_string == kGpuFeatureNameAcceleratedVideoDecode)
+ return content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE;
+ else if (feature_string == kGpuFeatureNameAll)
+ return content::GPU_FEATURE_TYPE_ALL;
+ return content::GPU_FEATURE_TYPE_UNKNOWN;
+}
+
+std::string GpuFeatureTypeToString(GpuFeatureType type) {
+ std::vector<std::string> matches;
+ if (type == content::GPU_FEATURE_TYPE_ALL) {
+ matches.push_back(kGpuFeatureNameAll);
+ } else {
+ if (type & content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)
+ matches.push_back(kGpuFeatureNameAccelerated2dCanvas);
+ if (type & content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING)
+ matches.push_back(kGpuFeatureNameAcceleratedCompositing);
+ if (type & content::GPU_FEATURE_TYPE_WEBGL)
+ matches.push_back(kGpuFeatureNameWebgl);
+ if (type & content::GPU_FEATURE_TYPE_MULTISAMPLING)
+ matches.push_back(kGpuFeatureNameMultisampling);
+ if (type & content::GPU_FEATURE_TYPE_FLASH3D)
+ matches.push_back(kGpuFeatureNameFlash3d);
+ if (type & content::GPU_FEATURE_TYPE_FLASH_STAGE3D)
+ matches.push_back(kGpuFeatureNameFlashStage3d);
+ if (type & content::GPU_FEATURE_TYPE_TEXTURE_SHARING)
+ matches.push_back(kGpuFeatureNameTextureSharing);
+ if (type & content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE)
+ matches.push_back(kGpuFeatureNameAcceleratedVideoDecode);
+ if (!matches.size())
+ matches.push_back(kGpuFeatureNameUnknown);
+ }
+ return JoinString(matches, ',');
+}
+
+void UpdateStats(const GpuBlacklist* blacklist,
+ uint32 blacklisted_features) {
+ uint32 max_entry_id = blacklist->max_entry_id();
+ if (max_entry_id == 0) {
+ // GPU Blacklist was not loaded. No need to go further.
+ return;
+ }
+
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ bool disabled = false;
+ if (blacklisted_features == 0) {
+ UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
+ 0, max_entry_id + 1);
+ } else {
+ std::vector<uint32> flag_entries;
+ blacklist->GetGpuFeatureTypeEntries(
+ content::GPU_FEATURE_TYPE_ALL, flag_entries, disabled);
+ DCHECK_GT(flag_entries.size(), 0u);
+ for (size_t i = 0; i < flag_entries.size(); ++i) {
+ UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
+ flag_entries[i], max_entry_id + 1);
+ }
+ }
+
+ // This counts how many users are affected by a disabled entry - this allows
+ // us to understand the impact of an entry before enable it.
+ std::vector<uint32> flag_disabled_entries;
+ disabled = true;
+ blacklist->GetGpuFeatureTypeEntries(
+ content::GPU_FEATURE_TYPE_ALL, flag_disabled_entries, disabled);
+ for (size_t i = 0; i < flag_disabled_entries.size(); ++i) {
+ UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerDisabledEntry",
+ flag_disabled_entries[i], max_entry_id + 1);
+ }
+
+ const content::GpuFeatureType kGpuFeatures[] = {
+ content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS,
+ content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING,
+ content::GPU_FEATURE_TYPE_WEBGL
+ };
+ const std::string kGpuBlacklistFeatureHistogramNames[] = {
+ "GPU.BlacklistFeatureTestResults.Accelerated2dCanvas",
+ "GPU.BlacklistFeatureTestResults.AcceleratedCompositing",
+ "GPU.BlacklistFeatureTestResults.Webgl"
+ };
+ const bool kGpuFeatureUserFlags[] = {
+ command_line.HasSwitch(switches::kDisableAccelerated2dCanvas),
+ command_line.HasSwitch(switches::kDisableAcceleratedCompositing),
+#if defined(OS_ANDROID)
+ !command_line.HasSwitch(switches::kEnableExperimentalWebGL)
+#else
+ command_line.HasSwitch(switches::kDisableExperimentalWebGL)
+#endif
+ };
+#if defined(OS_WIN)
+ const std::string kGpuBlacklistFeatureHistogramNamesWin[] = {
+ "GPU.BlacklistFeatureTestResultsWindows.Accelerated2dCanvas",
+ "GPU.BlacklistFeatureTestResultsWindows.AcceleratedCompositing",
+ "GPU.BlacklistFeatureTestResultsWindows.Webgl"
+ };
+#endif
+ const size_t kNumFeatures =
+ sizeof(kGpuFeatures) / sizeof(content::GpuFeatureType);
+ for (size_t i = 0; i < kNumFeatures; ++i) {
+ // We can't use UMA_HISTOGRAM_ENUMERATION here because the same name is
+ // expected if the macro is used within a loop.
+ GpuFeatureStatus value = kGpuFeatureEnabled;
+ if (blacklisted_features & kGpuFeatures[i])
+ value = kGpuFeatureBlacklisted;
+ else if (kGpuFeatureUserFlags[i])
+ value = kGpuFeatureDisabled;
+ base::Histogram* histogram_pointer = base::LinearHistogram::FactoryGet(
+ kGpuBlacklistFeatureHistogramNames[i],
+ 1, kGpuFeatureNumStatus, kGpuFeatureNumStatus + 1,
+ base::Histogram::kUmaTargetedHistogramFlag);
+ histogram_pointer->Add(value);
+#if defined(OS_WIN)
+ histogram_pointer = base::LinearHistogram::FactoryGet(
+ kGpuBlacklistFeatureHistogramNamesWin[i],
+ 1, kNumWinSubVersions * kGpuFeatureNumStatus,
+ kNumWinSubVersions * kGpuFeatureNumStatus + 1,
+ base::Histogram::kUmaTargetedHistogramFlag);
+ histogram_pointer->Add(GetGpuBlacklistHistogramValueWin(value));
+#endif
+ }
+}
+
+} // namespace gpu_util;
diff --git a/content/browser/gpu/gpu_util.h b/content/browser/gpu/gpu_util.h
new file mode 100644
index 0000000..f8245c7
--- /dev/null
+++ b/content/browser/gpu/gpu_util.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_GPU_GPU_UTIL_H_
+#define CONTENT_BROWSER_GPU_GPU_UTIL_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "build/build_config.h"
+#include "content/common/content_export.h"
+#include "content/public/common/gpu_feature_type.h"
+
+class GpuBlacklist;
+
+namespace gpu_util {
+
+// Maps string to GpuFeatureType; returns GPU_FEATURE_TYPE_UNKNOWN if none of
+// the following is input (case-sensitive):
+// "accelerated_2d_canvas"
+// "accelerated_compositing"
+// "webgl"
+// "multisampling"
+CONTENT_EXPORT content::GpuFeatureType StringToGpuFeatureType(
+ const std::string& feature_string);
+
+// Gets a string version of a feature type for use in about:gpu. Will yield
+// strings from StringToGpuFeatureType, e.g.
+// GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS becomes "accelerated_2d_canvas"
+CONTENT_EXPORT std::string GpuFeatureTypeToString(
+ content::GpuFeatureType feature);
+
+// Send UMA histograms about the enabled features.
+CONTENT_EXPORT void UpdateStats(
+ const GpuBlacklist* blacklist, uint32 blacklisted_features);
+
+} // namespace gpu_util
+
+#endif // CONTENT_BROWSER_GPU_GPU_UTIL_H_
+
diff --git a/content/browser/gpu/gpu_util_unittest.cc b/content/browser/gpu/gpu_util_unittest.cc
new file mode 100644
index 0000000..b92b5f8
--- /dev/null
+++ b/content/browser/gpu/gpu_util_unittest.cc
@@ -0,0 +1,87 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/gpu/gpu_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using content::GpuFeatureType;
+
+TEST(GpuUtilsTest, GpuFeatureTypFromString) {
+ // Test StringToGpuFeatureType.
+ EXPECT_EQ(gpu_util::StringToGpuFeatureType("accelerated_2d_canvas"),
+ content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS);
+ EXPECT_EQ(gpu_util::StringToGpuFeatureType("accelerated_compositing"),
+ content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING);
+ EXPECT_EQ(gpu_util::StringToGpuFeatureType("webgl"),
+ content::GPU_FEATURE_TYPE_WEBGL);
+ EXPECT_EQ(gpu_util::StringToGpuFeatureType("multisampling"),
+ content::GPU_FEATURE_TYPE_MULTISAMPLING);
+ EXPECT_EQ(gpu_util::StringToGpuFeatureType("flash_3d"),
+ content::GPU_FEATURE_TYPE_FLASH3D);
+ EXPECT_EQ(gpu_util::StringToGpuFeatureType("flash_stage3d"),
+ content::GPU_FEATURE_TYPE_FLASH_STAGE3D);
+ EXPECT_EQ(gpu_util::StringToGpuFeatureType("texture_sharing"),
+ content::GPU_FEATURE_TYPE_TEXTURE_SHARING);
+ EXPECT_EQ(gpu_util::StringToGpuFeatureType("accelerated_video_decode"),
+ content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE);
+ EXPECT_EQ(gpu_util::StringToGpuFeatureType("all"),
+ content::GPU_FEATURE_TYPE_ALL);
+ EXPECT_EQ(gpu_util::StringToGpuFeatureType("xxx"),
+ content::GPU_FEATURE_TYPE_UNKNOWN);
+}
+
+TEST(GpuUtilsTest, GpuFeatureTypeToString) {
+ // Test GpuFeatureTypeToString for single-bit enums using the all enum
+ EXPECT_STREQ(
+ gpu_util::GpuFeatureTypeToString(
+ content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING).c_str(),
+ "accelerated_compositing");
+ EXPECT_STREQ(
+ gpu_util::GpuFeatureTypeToString(
+ content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS).c_str(),
+ "accelerated_2d_canvas");
+ EXPECT_STREQ(
+ gpu_util::GpuFeatureTypeToString(
+ content::GPU_FEATURE_TYPE_WEBGL).c_str(),
+ "webgl");
+ EXPECT_STREQ(
+ gpu_util::GpuFeatureTypeToString(
+ content::GPU_FEATURE_TYPE_MULTISAMPLING).c_str(),
+ "multisampling");
+ EXPECT_STREQ(
+ gpu_util::GpuFeatureTypeToString(
+ content::GPU_FEATURE_TYPE_FLASH3D).c_str(),
+ "flash_3d");
+ EXPECT_STREQ(
+ gpu_util::GpuFeatureTypeToString(
+ content::GPU_FEATURE_TYPE_FLASH_STAGE3D).c_str(),
+ "flash_stage3d");
+ EXPECT_STREQ(
+ gpu_util::GpuFeatureTypeToString(
+ content::GPU_FEATURE_TYPE_TEXTURE_SHARING).c_str(),
+ "texture_sharing");
+ EXPECT_STREQ(
+ gpu_util::GpuFeatureTypeToString(
+ content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE).c_str(),
+ "accelerated_video_decode");
+ EXPECT_STREQ(
+ gpu_util::GpuFeatureTypeToString(
+ content::GPU_FEATURE_TYPE_ALL).c_str(),
+ "all");
+ EXPECT_STREQ(gpu_util::GpuFeatureTypeToString(
+ content::GPU_FEATURE_TYPE_UNKNOWN).c_str(),
+ "unknown");
+ EXPECT_STREQ(
+ gpu_util::GpuFeatureTypeToString(
+ static_cast<content::GpuFeatureType>(
+ content::GPU_FEATURE_TYPE_WEBGL |
+ content::GPU_FEATURE_TYPE_MULTISAMPLING)).c_str(),
+ "webgl,multisampling");
+ EXPECT_STREQ(
+ gpu_util::GpuFeatureTypeToString(
+ static_cast<content::GpuFeatureType>(
+ content::GPU_FEATURE_TYPE_WEBGL |
+ content::GPU_FEATURE_TYPE_ALL)).c_str(),
+ "all");
+}
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 223ec18..5ed5da3 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -421,6 +421,8 @@
'browser/geolocation/win7_location_provider_win.h',
'browser/gpu/browser_gpu_channel_host_factory.cc',
'browser/gpu/browser_gpu_channel_host_factory.h',
+ 'browser/gpu/gpu_blacklist.cc',
+ 'browser/gpu/gpu_blacklist.h',
'browser/gpu/gpu_data_manager_impl.cc',
'browser/gpu/gpu_data_manager_impl.h',
'browser/gpu/gpu_process_host.cc',
@@ -429,6 +431,8 @@
'browser/gpu/gpu_process_host_ui_shim.h',
'browser/gpu/gpu_surface_tracker.cc',
'browser/gpu/gpu_surface_tracker.h',
+ 'browser/gpu/gpu_util.cc',
+ 'browser/gpu/gpu_util.h',
'browser/histogram_controller.cc',
'browser/histogram_controller.h',
'browser/histogram_internals_request_job.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index fcb9051..d29b03b 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -271,7 +271,9 @@
'browser/geolocation/wifi_data_provider_unittest_win.cc',
'browser/geolocation/win7_location_api_unittest_win.cc',
'browser/geolocation/win7_location_provider_unittest_win.cc',
+ 'browser/gpu/gpu_blacklist_unittest.cc',
'browser/gpu/gpu_data_manager_impl_unittest.cc',
+ 'browser/gpu/gpu_util_unittest.cc',
'browser/host_zoom_map_impl_unittest.cc',
'browser/hyphenator/hyphenator_message_filter_unittest.cc',
'browser/in_process_webkit/indexed_db_quota_client_unittest.cc',
diff --git a/content/public/browser/gpu_data_manager.h b/content/public/browser/gpu_data_manager.h
index d1dfafc..efab8d2 100644
--- a/content/public/browser/gpu_data_manager.h
+++ b/content/public/browser/gpu_data_manager.h
@@ -27,17 +27,21 @@ class GpuDataManager {
// Getter for the singleton.
CONTENT_EXPORT static GpuDataManager* GetInstance();
- // This collects preliminary GPU info; it should only be called at
- // browser startup time in UI thread before the IO restriction is turned
- // on.
- virtual void InitializeGpuInfo() = 0;
+ // This collects preliminary GPU info, load GpuBlacklist, and compute the
+ // preliminary blacklisted features; it should only be called at browser
+ // startup time in UI thread before the IO restriction is turned on.
+ virtual void Initialize(const std::string& browser_version_string,
+ const std::string& gpu_blacklist_json) = 0;
+
+ virtual std::string GetBlacklistVersion() const = 0;
- // Can be called on any thread.
virtual GpuFeatureType GetBlacklistedFeatures() const = 0;
- // Sets the blacklisted feature flags due to preliminary GPU info.
- virtual void SetPreliminaryBlacklistedFeatures(
- GpuFeatureType feature_type) = 0;
+ // Returns the reasons for the latest run of blacklisting decisions.
+ // For the structure of returned value, see documentation for
+ // GpuBlacklist::GetBlacklistedReasons().
+ // Caller is responsible to release the returned value.
+ virtual base::ListValue* GetBlacklistReasons() const = 0;
virtual GPUInfo GetGPUInfo() const = 0;