Bug 1257547 - Remove coupling of gfx code to XML file blocklist.xml. r=milan

MozReview-Commit-ID: HDVVvsk077x

--HG--
extra : rebase_source : 86f2efb57b3a606e0233c0a86cdd8636be131f42
This commit is contained in:
Mathieu Leplatre 2016-05-04 16:12:19 +02:00
Родитель 3b9a380403
Коммит 5554aa9abe
5 изменённых файлов: 386 добавлений и 278 удалений

Просмотреть файл

@ -328,6 +328,7 @@ Blocklist.prototype = {
* (default = *)
*/
_addonEntries: null,
_gfxEntries: null,
_pluginEntries: null,
shutdown: function() {
@ -660,9 +661,12 @@ Blocklist.prototype = {
var oldAddonEntries = this._addonEntries;
var oldPluginEntries = this._pluginEntries;
this._addonEntries = [];
this._gfxEntries = [];
this._pluginEntries = [];
this._loadBlocklistFromString(request.responseText);
// We don't inform the users when the graphics blocklist changed at runtime.
// However addons and plugins blocking status is refreshed.
this._blocklistUpdated(oldAddonEntries, oldPluginEntries);
try {
@ -701,6 +705,7 @@ Blocklist.prototype = {
*/
_loadBlocklist: function() {
this._addonEntries = [];
this._gfxEntries = [];
this._pluginEntries = [];
var profFile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]);
if (profFile.exists()) {
@ -837,7 +842,7 @@ Blocklist.prototype = {
},
_isBlocklistLoaded: function() {
return this._addonEntries != null && this._pluginEntries != null;
return this._addonEntries != null && this._gfxEntries != null && this._pluginEntries != null;
},
_isBlocklistPreloaded: function() {
@ -847,6 +852,7 @@ Blocklist.prototype = {
/* Used for testing */
_clear: function() {
this._addonEntries = null;
this._gfxEntries = null;
this._pluginEntries = null;
this._preloadedBlocklistContent = null;
},
@ -912,12 +918,12 @@ Blocklist.prototype = {
case "emItems":
// Special case for b2g, since we don't use the addon manager.
if (AppConstants.MOZ_B2G) {
let extensions = this._processItemNodes(element.childNodes, "em",
let extensions = this._processItemNodes(element.childNodes, "emItem",
this._handleEmItemNode);
DOMApplicationRegistry.blockExtensions(extensions);
return;
}
this._addonEntries = this._processItemNodes(element.childNodes, "em",
this._addonEntries = this._processItemNodes(element.childNodes, "emItem",
this._handleEmItemNode);
break;
case "pluginItems":
@ -925,24 +931,30 @@ Blocklist.prototype = {
if (AppConstants.MOZ_B2G) {
return;
}
this._pluginEntries = this._processItemNodes(element.childNodes, "plugin",
this._pluginEntries = this._processItemNodes(element.childNodes, "pluginItem",
this._handlePluginItemNode);
break;
case "certItems":
if (populateCertBlocklist) {
this._processItemNodes(element.childNodes, "cert",
this._processItemNodes(element.childNodes, "certItem",
this._handleCertItemNode.bind(this));
}
break;
case "gfxItems":
// Parse as simple list of objects.
this._gfxEntries = this._processItemNodes(element.childNodes, "gfxBlacklistEntry",
this._handleGfxBlacklistNode);
break;
default:
Services.obs.notifyObservers(element,
"blocklist-data-" + element.localName,
null);
LOG("Blocklist::_loadBlocklistFromString: ignored entries " + element.localName);
}
}
if (populateCertBlocklist) {
gCertBlocklistService.saveEntries();
}
if (this._gfxEntries.length > 0) {
this._notifyObserversBlocklistGFX();
}
}
catch (e) {
LOG("Blocklist::_loadBlocklistFromFile: Error constructing blocklist " + e);
@ -950,9 +962,8 @@ Blocklist.prototype = {
}
},
_processItemNodes: function(itemNodes, prefix, handler) {
_processItemNodes: function(itemNodes, itemName, handler) {
var result = [];
var itemName = prefix + "Item";
for (var i = 0; i < itemNodes.length; ++i) {
var blocklistElement = itemNodes.item(i);
if (!(blocklistElement instanceof Ci.nsIDOMElement) ||
@ -1089,6 +1100,75 @@ Blocklist.prototype = {
result.push(blockEntry);
},
// <gfxBlacklistEntry blockID="g60">
// <os>WINNT 6.0</os>
// <osversion>14</osversion> currently only used for Android
// <versionRange minVersion="42.0" maxVersion="13.0b2"/>
// <vendor>0x8086</vendor>
// <devices>
// <device>0x2582</device>
// <device>0x2782</device>
// </devices>
// <feature> DIRECT3D_10_LAYERS </feature>
// <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus>
// <driverVersion> 8.52.322.2202 </driverVersion>
// <driverVersionMax> 8.52.322.2202 </driverVersionMax>
// <driverVersionComparator> LESS_THAN_OR_EQUAL </driverVersionComparator>
// <model>foo</model>
// <product>foo</product>
// <manufacturer>foo</manufacturer>
// <hardware>foo</hardware>
// </gfxBlacklistEntry>
_handleGfxBlacklistNode: function (blocklistElement, result) {
const blockEntry = {};
// The blockID attribute is always present in the actual data produced on server
// (see https://github.com/mozilla/addons-server/blob/2016.05.05/src/olympia/blocklist/templates/blocklist/blocklist.xml#L74)
// But it is sometimes missing in test fixtures.
if (blocklistElement.hasAttribute("blockID")) {
blockEntry.blockID = blocklistElement.getAttribute("blockID");
}
// Trim helper (spaces, tabs, no-break spaces..)
const trim = (s) => (s || '').replace(/(^[\s\uFEFF\xA0]+)|([\s\uFEFF\xA0]+$)/g, "");
for (let i = 0; i < blocklistElement.childNodes.length; ++i) {
var matchElement = blocklistElement.childNodes.item(i);
if (!(matchElement instanceof Ci.nsIDOMElement))
continue;
let value;
if (matchElement.localName == "devices") {
value = [];
for (let j = 0; j < matchElement.childNodes.length; j++) {
const childElement = matchElement.childNodes.item(j);
const childValue = trim(childElement.textContent);
// Make sure no empty value is added.
if (childValue) {
if (/,/.test(childValue)) {
// Devices can't contain comma.
// (c.f serialization in _notifyObserversBlocklistGFX)
const e = new Error(`Unsupported device name ${childValue}`);
Components.utils.reportError(e);
}
else {
value.push(childValue);
}
}
}
} else if (matchElement.localName == "versionRange") {
value = {minVersion: trim(matchElement.getAttribute("minVersion")) || "0",
maxVersion: trim(matchElement.getAttribute("maxVersion")) || "*"};
} else {
value = trim(matchElement.textContent);
}
if (value) {
blockEntry[matchElement.localName] = value;
}
}
result.push(blockEntry);
},
/* See nsIBlocklistService */
getPluginBlocklistState: function(plugin, appVersion, toolkitVersion) {
if (AppConstants.platform == "android" ||
@ -1231,6 +1311,24 @@ Blocklist.prototype = {
return blockEntry.infoURL;
},
_notifyObserversBlocklistGFX: function () {
// Notify `GfxInfoBase`, by passing a string serialization.
// This way we avoid spreading XML structure logics there.
const payload = this._gfxEntries.map((r) => {
return Object.keys(r).sort().filter((k) => !/id|last_modified/.test(k)).map((key) => {
let value = r[key];
if (Array.isArray(value)) {
value = value.join(",");
} else if (value.hasOwnProperty("minVersion")) {
// When XML is parsed, both minVersion and maxVersion are set.
value = `${value.minVersion},${value.maxVersion}`;
}
return `${key}:${value}`;
}).join("\t");
}).join("\n");
Services.obs.notifyObservers(null, "blocklist-data-gfxItems", payload);
},
_notifyObserversBlocklistUpdated: function() {
Services.obs.notifyObservers(this, "blocklist-updated", "");
Services.ppmm.broadcastAsyncMessage("Blocklist:blocklistInvalidated", {});

Просмотреть файл

@ -0,0 +1,157 @@
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const TEST_APP_ID = "xpcshell@tests.mozilla.org";
const EVENT_NAME = "blocklist-data-gfxItems";
const SAMPLE_GFX_RECORD = {
"driverVersionComparator": "LESS_THAN_OR_EQUAL",
"driverVersion": "8.17.12.5896",
"vendor": "0x10de",
"blockID": "g36",
"feature": "DIRECT3D_9_LAYERS",
"devices": ["0x0a6c", "geforce"],
"featureStatus": "BLOCKED_DRIVER_VERSION",
"last_modified": 1458035931837,
"os": "WINNT 6.1",
"id": "3f947f16-37c2-4e96-d356-78b26363729b",
"versionRange": {"minVersion": 0, "maxVersion": "*"}
};
function Blocklist() {
let blocklist = Cc["@mozilla.org/extensions/blocklist;1"].
getService().wrappedJSObject;
blocklist._clear();
return blocklist;
}
function run_test() {
run_next_test();
}
add_task(function* test_sends_serialized_data() {
const blocklist = Blocklist();
blocklist._gfxEntries = [SAMPLE_GFX_RECORD];
const expected = "blockID:g36\tdevices:0x0a6c,geforce\tdriverVersion:8.17.12.5896\t" +
"driverVersionComparator:LESS_THAN_OR_EQUAL\tfeature:DIRECT3D_9_LAYERS\t" +
"featureStatus:BLOCKED_DRIVER_VERSION\tos:WINNT 6.1\tvendor:0x10de\t" +
"versionRange:0,*";
let received;
const observe = (subject, topic, data) => { received = data };
Services.obs.addObserver(observe, EVENT_NAME, false);
blocklist._notifyObserversBlocklistGFX();
equal(received, expected);
Services.obs.removeObserver(observe, EVENT_NAME);
});
add_task(function* test_parsing_fails_if_devices_contains_comma() {
const input = "<blocklist xmlns=\"http://www.mozilla.org/2006/addons-blocklist\">" +
"<gfxItems>" +
" <gfxBlacklistEntry>" +
" <devices>" +
" <device>0x2,582</device>" +
" <device>0x2782</device>" +
" </devices>" +
" </gfxBlacklistEntry>" +
"</gfxItems>" +
"</blocklist>";
const blocklist = Blocklist();
blocklist._loadBlocklistFromString(input);
equal(blocklist._gfxEntries[0].devices.length, 1);
equal(blocklist._gfxEntries[0].devices[0], "0x2782");
});
add_task(function* test_empty_values_are_ignored() {
const input = "<blocklist xmlns=\"http://www.mozilla.org/2006/addons-blocklist\">" +
"<gfxItems>" +
" <gfxBlacklistEntry>" +
" <os></os>" +
" </gfxBlacklistEntry>" +
"</gfxItems>" +
"</blocklist>";
const blocklist = Blocklist();
let received;
const observe = (subject, topic, data) => { received = data };
Services.obs.addObserver(observe, EVENT_NAME, false);
blocklist._loadBlocklistFromString(input);
ok(received.indexOf("os" < 0));
Services.obs.removeObserver(observe, EVENT_NAME);
});
add_task(function* test_empty_devices_are_ignored() {
const input = "<blocklist xmlns=\"http://www.mozilla.org/2006/addons-blocklist\">" +
"<gfxItems>" +
" <gfxBlacklistEntry>" +
" <devices></devices>" +
" </gfxBlacklistEntry>" +
"</gfxItems>" +
"</blocklist>";
const blocklist = Blocklist();
let received;
const observe = (subject, topic, data) => { received = data };
Services.obs.addObserver(observe, EVENT_NAME, false);
blocklist._loadBlocklistFromString(input);
ok(received.indexOf("devices" < 0));
Services.obs.removeObserver(observe, EVENT_NAME);
});
add_task(function* test_version_range_default_values() {
const input = "<blocklist xmlns=\"http://www.mozilla.org/2006/addons-blocklist\">" +
"<gfxItems>" +
" <gfxBlacklistEntry>" +
" <versionRange minVersion=\"13.0b2\" maxVersion=\"42.0\"/>" +
" </gfxBlacklistEntry>" +
" <gfxBlacklistEntry>" +
" <versionRange maxVersion=\"2.0\"/>" +
" </gfxBlacklistEntry>" +
" <gfxBlacklistEntry>" +
" <versionRange minVersion=\"1.0\"/>" +
" </gfxBlacklistEntry>" +
" <gfxBlacklistEntry>" +
" <versionRange minVersion=\" \"/>" +
" </gfxBlacklistEntry>" +
" <gfxBlacklistEntry>" +
" <versionRange/>" +
" </gfxBlacklistEntry>" +
"</gfxItems>" +
"</blocklist>";
const blocklist = Blocklist();
blocklist._loadBlocklistFromString(input);
equal(blocklist._gfxEntries[0].versionRange.minVersion, "13.0b2");
equal(blocklist._gfxEntries[0].versionRange.maxVersion, "42.0");
equal(blocklist._gfxEntries[1].versionRange.minVersion, "0");
equal(blocklist._gfxEntries[1].versionRange.maxVersion, "2.0");
equal(blocklist._gfxEntries[2].versionRange.minVersion, "1.0");
equal(blocklist._gfxEntries[2].versionRange.maxVersion, "*");
equal(blocklist._gfxEntries[3].versionRange.minVersion, "0");
equal(blocklist._gfxEntries[3].versionRange.maxVersion, "*");
equal(blocklist._gfxEntries[4].versionRange.minVersion, "0");
equal(blocklist._gfxEntries[4].versionRange.maxVersion, "*");
});
add_task(function* test_blockid_attribute() {
const input = "<blocklist xmlns=\"http://www.mozilla.org/2006/addons-blocklist\">" +
"<gfxItems>" +
" <gfxBlacklistEntry blockID=\"g60\">" +
" <vendor> 0x10de </vendor>" +
" </gfxBlacklistEntry>" +
" <gfxBlacklistEntry>" +
" <feature> DIRECT3D_9_LAYERS </feature>" +
" </gfxBlacklistEntry>" +
"</gfxItems>" +
"</blocklist>";
const blocklist = Blocklist();
blocklist._loadBlocklistFromString(input);
equal(blocklist._gfxEntries[0].blockID, "g60");
ok(!blocklist._gfxEntries[1].hasOwnProperty("blockID"));
});

Просмотреть файл

@ -14,6 +14,7 @@ var gTestserver = new HttpServer();
gTestserver.start(-1);
gPort = gTestserver.identity.primaryPort;
mapFile("/data/test_gfxBlacklist.xml", gTestserver);
mapFile("/data/test_gfxBlacklist2.xml", gTestserver);
function get_platform() {
var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"]

Просмотреть файл

@ -11,6 +11,7 @@ support-files =
[test_addon_path_service.js]
[test_asyncBlocklistLoad.js]
[test_blocklist_gfx.js]
[test_cache_certdb.js]
run-if = addon_signing
[test_cacheflush.js]

Просмотреть файл

@ -238,42 +238,6 @@ RemovePrefForDriverVersion()
Preferences::ClearUser(SUGGESTED_VERSION_PREF);
}
// <foo>Hello</foo> - "Hello" is stored as a child text node of the foo node.
static bool
BlacklistNodeToTextValue(nsIDOMNode *aBlacklistNode, nsAString& aValue)
{
nsAutoString value;
if (NS_FAILED(aBlacklistNode->GetTextContent(value)))
return false;
value.Trim(" \t\r\n");
aValue = value;
return true;
}
// <foo attr=Hello/> finds "Hello" if the aAttrName is "attr".
static bool
BlacklistAttrToTextValue(nsIDOMNode *aBlacklistNode,
const nsAString& aAttrName,
nsAString& aValue)
{
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aBlacklistNode);
if (!element) {
return false;
}
nsAutoString value;
if (NS_FAILED(element->GetAttribute(aAttrName, value))) {
return false;
}
value.Trim(" \t\r\n");
aValue = value;
return true;
}
static OperatingSystem
BlacklistOSToOperatingSystem(const nsAString& os)
@ -317,26 +281,19 @@ BlacklistOSToOperatingSystem(const nsAString& os)
}
static GfxDeviceFamily*
BlacklistDevicesToDeviceFamily(nsIDOMHTMLCollection* aDevices)
BlacklistDevicesToDeviceFamily(nsTArray<nsCString>& devices)
{
uint32_t length;
if (NS_FAILED(aDevices->GetLength(&length)))
if (devices.Length() == 0)
return nullptr;
// For each <device>, get its device ID, and return a freshly-allocated
// For each device, get its device ID, and return a freshly-allocated
// GfxDeviceFamily with the contents of that array.
GfxDeviceFamily* deviceIds = new GfxDeviceFamily;
for (uint32_t i = 0; i < length; ++i) {
nsCOMPtr<nsIDOMNode> node;
if (NS_FAILED(aDevices->Item(i, getter_AddRefs(node))) || !node)
continue;
nsAutoString deviceValue;
if (!BlacklistNodeToTextValue(node, deviceValue))
continue;
deviceIds->AppendElement(deviceValue);
for (uint32_t i = 0; i < devices.Length(); ++i) {
// We make sure we don't add any "empty" device entries to the array, so
// we don't need to check if devices[i] is empty.
deviceIds->AppendElement(NS_ConvertUTF8toUTF16(devices[i]));
}
return deviceIds;
@ -432,60 +389,16 @@ BlacklistComparatorToComparisonOp(const nsAString& op)
return DRIVER_COMPARISON_IGNORED;
}
// Arbitrarily returns the first |tagname| child of |element|.
static bool
BlacklistNodeGetChildByName(nsIDOMElement *element,
const nsAString& tagname,
nsIDOMNode** firstchild)
{
nsCOMPtr<nsIDOMHTMLCollection> nodelist;
if (NS_FAILED(element->GetElementsByTagName(tagname,
getter_AddRefs(nodelist))) ||
!nodelist) {
return false;
}
nsCOMPtr<nsIDOMNode> node;
if (NS_FAILED(nodelist->Item(0, getter_AddRefs(node))) || !node)
return false;
node.forget(firstchild);
return true;
}
/*
<gfxBlacklistEntry>
<os>WINNT 6.0</os>
<vendor>0x8086</vendor>
<devices>
<device>0x2582</device>
<device>0x2782</device>
</devices>
<feature> DIRECT3D_10_LAYERS </feature>
<featureStatus> BLOCKED_DRIVER_VERSION </featureStatus>
<driverVersion> 8.52.322.2202 </driverVersion>
<driverVersionComparator> LESS_THAN_OR_EQUAL </driverVersionComparator>
</gfxBlacklistEntry>
Deserialize Blacklist entries from string.
e.g:
os:WINNT 6.0\tvendor:0x8086\tdevices:0x2582,0x2782\tfeature:DIRECT3D_10_LAYERS\tfeatureStatus:BLOCKED_DRIVER_VERSION\tdriverVersion:8.52.322.2202\tdriverVersionComparator:LESS_THAN_OR_EQUAL
*/
static bool
BlacklistEntryToDriverInfo(nsIDOMNode* aBlacklistEntry,
BlacklistEntryToDriverInfo(nsCString& aBlacklistEntry,
GfxDriverInfo& aDriverInfo)
{
nsAutoString nodename;
if (NS_FAILED(aBlacklistEntry->GetNodeName(nodename)) ||
nodename != NS_LITERAL_STRING(BLACKLIST_ENTRY_TAG_NAME)) {
return false;
}
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aBlacklistEntry);
if (!element)
return false;
nsCOMPtr<nsIDOMNode> dataNode;
nsAutoString dataValue;
// If we get an application version to be zero, something is not working
// and we are not going to bother checking the blocklist versions.
// See TestGfxWidgets.cpp for how version comparison works.
@ -494,70 +407,100 @@ BlacklistEntryToDriverInfo(nsIDOMNode* aBlacklistEntry,
static mozilla::Version appV(GfxInfoBase::GetApplicationVersion().get());
if (appV <= zeroV) {
gfxCriticalErrorOnce(gfxCriticalError::DefaultOptions(false)) << "Invalid application version " << GfxInfoBase::GetApplicationVersion().get();
} else if (BlacklistNodeGetChildByName(element,
NS_LITERAL_STRING("versionRange"),
getter_AddRefs(dataNode))) {
if (BlacklistAttrToTextValue(dataNode,
NS_LITERAL_STRING("minVersion"),
dataValue)) {
mozilla::Version minV(NS_ConvertUTF16toUTF8(dataValue).get());
if (minV > zeroV && appV < minV) {
}
nsTArray<nsCString> keyValues;
ParseString(aBlacklistEntry, '\t', keyValues);
aDriverInfo.mRuleId = NS_LITERAL_CSTRING("FEATURE_FAILURE_DL_BLACKLIST_NO_ID");
for (uint32_t i = 0; i < keyValues.Length(); ++i) {
nsCString keyValue = keyValues[i];
nsTArray<nsCString> splitted;
ParseString(keyValue, ':', splitted);
if (splitted.Length() != 2) {
// If we don't recognize the input data, we do not want to proceed.
gfxCriticalErrorOnce(CriticalLog::DefaultOptions(false)) << "Unrecognized data " << keyValue.get();
return false;
}
nsCString key = splitted[0];
nsCString value = splitted[1];
NS_ConvertUTF8toUTF16 dataValue(value);
if (value.Length() == 0) {
// Safety check for empty values.
gfxCriticalErrorOnce(CriticalLog::DefaultOptions(false)) << "Empty value for " << key.get();
return false;
}
if (key.EqualsLiteral("blockID")) {
nsCString blockIdStr = NS_LITERAL_CSTRING("FEATURE_FAILURE_DL_BLACKLIST_") + value;
aDriverInfo.mRuleId = blockIdStr.get();
} else if (key.EqualsLiteral("os")) {
aDriverInfo.mOperatingSystem = BlacklistOSToOperatingSystem(dataValue);
} else if (key.EqualsLiteral("osversion")) {
aDriverInfo.mOperatingSystemVersion = strtoul(value.get(), nullptr, 10);
} else if (key.EqualsLiteral("vendor")) {
aDriverInfo.mAdapterVendor = dataValue;
} else if (key.EqualsLiteral("feature")) {
aDriverInfo.mFeature = BlacklistFeatureToGfxFeature(dataValue);
if (aDriverInfo.mFeature < 0) {
// If we don't recognize the feature, we do not want to proceed.
gfxCriticalErrorOnce(CriticalLog::DefaultOptions(false)) << "Unrecognized feature " << value.get();
return false;
}
} else if (key.EqualsLiteral("featureStatus")) {
aDriverInfo.mFeatureStatus = BlacklistFeatureStatusToGfxFeatureStatus(dataValue);
} else if (key.EqualsLiteral("driverVersion")) {
uint64_t version;
if (ParseDriverVersion(dataValue, &version))
aDriverInfo.mDriverVersion = version;
} else if (key.EqualsLiteral("driverVersionMax")) {
uint64_t version;
if (ParseDriverVersion(dataValue, &version))
aDriverInfo.mDriverVersionMax = version;
} else if (key.EqualsLiteral("driverVersionMax")) {
uint64_t version;
if (ParseDriverVersion(dataValue, &version))
aDriverInfo.mDriverVersionMax = version;
} else if (key.EqualsLiteral("driverVersionComparator")) {
aDriverInfo.mComparisonOp = BlacklistComparatorToComparisonOp(dataValue);
} else if (key.EqualsLiteral("model")) {
aDriverInfo.mModel = dataValue;
} else if (key.EqualsLiteral("product")) {
aDriverInfo.mProduct = dataValue;
} else if (key.EqualsLiteral("manufacturer")) {
aDriverInfo.mManufacturer = dataValue;
} else if (key.EqualsLiteral("hardware")) {
aDriverInfo.mHardware = dataValue;
} else if (key.EqualsLiteral("versionRange")) {
nsTArray<nsCString> versionRange;
ParseString(value, ',', versionRange);
if (versionRange.Length() != 2) {
gfxCriticalErrorOnce(CriticalLog::DefaultOptions(false)) << "Unrecognized versionRange " << value.get();
return false;
}
nsCString minValue = versionRange[0];
nsCString maxValue = versionRange[1];
mozilla::Version minV(minValue.get());
mozilla::Version maxV(maxValue.get());
if (minV > zeroV && !(appV >= minV)) {
// The version of the application is less than the minimal version
// this blocklist entry applies to, so we can just ignore it by
// returning false and letting the caller deal with it.
return false;
}
}
if (BlacklistAttrToTextValue(dataNode,
NS_LITERAL_STRING("maxVersion"),
dataValue)) {
mozilla::Version maxV(NS_ConvertUTF16toUTF8(dataValue).get());
if (maxV > zeroV && appV > maxV) {
if (maxV > zeroV && !(appV <= maxV)) {
// The version of the application is more than the maximal version
// this blocklist entry applies to, so we can just ignore it by
// returning false and letting the caller deal with it.
return false;
}
}
}
// <os>WINNT 6.0</os>
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("os"),
getter_AddRefs(dataNode))) {
BlacklistNodeToTextValue(dataNode, dataValue);
aDriverInfo.mOperatingSystem = BlacklistOSToOperatingSystem(dataValue);
}
// <osversion>14</osversion> currently only used for Android
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("osversion"),
getter_AddRefs(dataNode))) {
BlacklistNodeToTextValue(dataNode, dataValue);
aDriverInfo.mOperatingSystemVersion = strtoul(NS_LossyConvertUTF16toASCII(dataValue).get(),
nullptr, 10);
}
// <vendor>0x8086</vendor>
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("vendor"),
getter_AddRefs(dataNode))) {
BlacklistNodeToTextValue(dataNode, dataValue);
aDriverInfo.mAdapterVendor = dataValue;
}
// <devices>
// <device>0x2582</device>
// <device>0x2782</device>
// </devices>
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("devices"),
getter_AddRefs(dataNode))) {
nsCOMPtr<nsIDOMElement> devicesElement = do_QueryInterface(dataNode);
if (devicesElement) {
// Get only the <device> nodes, because BlacklistDevicesToDeviceFamily
// assumes it is passed no other nodes.
nsCOMPtr<nsIDOMHTMLCollection> devices;
if (NS_SUCCEEDED(devicesElement->GetElementsByTagName(NS_LITERAL_STRING("device"),
getter_AddRefs(devices)))) {
} else if (key.EqualsLiteral("devices")) {
nsTArray<nsCString> devices;
ParseString(value, ',', devices);
GfxDeviceFamily* deviceIds = BlacklistDevicesToDeviceFamily(devices);
if (deviceIds) {
// Get GfxDriverInfo to adopt the devices array we created.
@ -565,107 +508,21 @@ BlacklistEntryToDriverInfo(nsIDOMNode* aBlacklistEntry,
aDriverInfo.mDevices = deviceIds;
}
}
}
}
// <feature> DIRECT3D_10_LAYERS </feature>
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("feature"),
getter_AddRefs(dataNode))) {
BlacklistNodeToTextValue(dataNode, dataValue);
aDriverInfo.mFeature = BlacklistFeatureToGfxFeature(dataValue);
if (aDriverInfo.mFeature < 0) {
// If we don't recognize the feature, we do not want to proceed.
gfxWarning() << "Unrecognized feature " << NS_ConvertUTF16toUTF8(dataValue).get();
return false;
}
}
// <featureStatus> BLOCKED_DRIVER_VERSION </featureStatus>
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("featureStatus"),
getter_AddRefs(dataNode))) {
BlacklistNodeToTextValue(dataNode, dataValue);
aDriverInfo.mFeatureStatus = BlacklistFeatureStatusToGfxFeatureStatus(dataValue);
}
// <driverVersion> 8.52.322.2202 </driverVersion>
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("driverVersion"),
getter_AddRefs(dataNode))) {
BlacklistNodeToTextValue(dataNode, dataValue);
uint64_t version;
if (ParseDriverVersion(dataValue, &version))
aDriverInfo.mDriverVersion = version;
}
// <driverVersionMax> 8.52.322.2202 </driverVersionMax>
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("driverVersionMax"),
getter_AddRefs(dataNode))) {
BlacklistNodeToTextValue(dataNode, dataValue);
uint64_t version;
if (ParseDriverVersion(dataValue, &version))
aDriverInfo.mDriverVersionMax = version;
}
// <driverVersionComparator> LESS_THAN_OR_EQUAL </driverVersionComparator>
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("driverVersionComparator"),
getter_AddRefs(dataNode))) {
BlacklistNodeToTextValue(dataNode, dataValue);
aDriverInfo.mComparisonOp = BlacklistComparatorToComparisonOp(dataValue);
}
// <model>foo</model>
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("model"),
getter_AddRefs(dataNode))) {
BlacklistNodeToTextValue(dataNode, dataValue);
aDriverInfo.mModel = dataValue;
}
// <product>foo</product>
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("product"),
getter_AddRefs(dataNode))) {
BlacklistNodeToTextValue(dataNode, dataValue);
aDriverInfo.mProduct = dataValue;
}
// <manufacturer>foo</manufacturer>
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("manufacturer"),
getter_AddRefs(dataNode))) {
BlacklistNodeToTextValue(dataNode, dataValue);
aDriverInfo.mManufacturer = dataValue;
}
// <hardware>foo</hardware>
if (BlacklistNodeGetChildByName(element, NS_LITERAL_STRING("hardware"),
getter_AddRefs(dataNode))) {
BlacklistNodeToTextValue(dataNode, dataValue);
aDriverInfo.mHardware = dataValue;
}
if (BlacklistAttrToTextValue(element,
NS_LITERAL_STRING("blockID"),
dataValue) && !dataValue.IsEmpty()) {
nsCString blockIdStr = NS_LITERAL_CSTRING("FEATURE_FAILURE_DL_BLACKLIST_") +
NS_ConvertUTF16toUTF8(dataValue);
aDriverInfo.mRuleId = blockIdStr.get();
} else {
aDriverInfo.mRuleId = NS_LITERAL_CSTRING("FEATURE_FAILURE_DL_BLACKLIST_NO_ID");
}
// We explicitly ignore unknown elements.
}
return true;
}
static void
BlacklistEntriesToDriverInfo(nsIDOMHTMLCollection* aBlacklistEntries,
BlacklistEntriesToDriverInfo(nsTArray<nsCString>& aBlacklistEntries,
nsTArray<GfxDriverInfo>& aDriverInfo)
{
uint32_t length;
if (NS_FAILED(aBlacklistEntries->GetLength(&length)))
return;
aDriverInfo.Clear();
aDriverInfo.SetLength(length);
for (uint32_t i = 0; i < length; ++i) {
nsCOMPtr<nsIDOMNode> blacklistEntry;
if (NS_SUCCEEDED(aBlacklistEntries->Item(i,
getter_AddRefs(blacklistEntry))) &&
blacklistEntry) {
aDriverInfo.SetLength(aBlacklistEntries.Length());
for (uint32_t i = 0; i < aBlacklistEntries.Length(); ++i) {
nsCString blacklistEntry = aBlacklistEntries[i];
GfxDriverInfo di;
if (BlacklistEntryToDriverInfo(blacklistEntry, di)) {
aDriverInfo[i] = di;
@ -673,7 +530,6 @@ BlacklistEntriesToDriverInfo(nsIDOMHTMLCollection* aBlacklistEntries,
di.mDeleteDevices = false;
}
}
}
}
NS_IMETHODIMP
@ -681,20 +537,15 @@ GfxInfoBase::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
{
if (strcmp(aTopic, "blocklist-data-gfxItems") == 0) {
nsCOMPtr<nsIDOMElement> gfxItems = do_QueryInterface(aSubject);
if (gfxItems) {
nsCOMPtr<nsIDOMHTMLCollection> blacklistEntries;
if (NS_SUCCEEDED(gfxItems->
GetElementsByTagName(NS_LITERAL_STRING(BLACKLIST_ENTRY_TAG_NAME),
getter_AddRefs(blacklistEntries))) &&
blacklistEntries)
{
nsTArray<GfxDriverInfo> driverInfo;
nsTArray<nsCString> blacklistEntries;
nsCString utf8Data = NS_ConvertUTF16toUTF8(aData);
if (utf8Data.Length() > 0) {
ParseString(utf8Data, '\n', blacklistEntries);
}
BlacklistEntriesToDriverInfo(blacklistEntries, driverInfo);
EvaluateDownloadedBlacklist(driverInfo);
}
}
}
return NS_OK;
}