mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
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:
parent
3b9a380403
commit
5554aa9abe
@ -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", {});
|
||||
|
157
toolkit/mozapps/extensions/test/xpcshell/test_blocklist_gfx.js
Normal file
157
toolkit/mozapps/extensions/test/xpcshell/test_blocklist_gfx.js
Normal file
@ -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,184 +407,127 @@ 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)))) {
|
||||
GfxDeviceFamily* deviceIds = BlacklistDevicesToDeviceFamily(devices);
|
||||
if (deviceIds) {
|
||||
// Get GfxDriverInfo to adopt the devices array we created.
|
||||
aDriverInfo.mDeleteDevices = true;
|
||||
aDriverInfo.mDevices = deviceIds;
|
||||
}
|
||||
} 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.
|
||||
aDriverInfo.mDeleteDevices = true;
|
||||
aDriverInfo.mDevices = deviceIds;
|
||||
}
|
||||
}
|
||||
// We explicitly ignore unknown elements.
|
||||
}
|
||||
|
||||
// <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) {
|
||||
GfxDriverInfo di;
|
||||
if (BlacklistEntryToDriverInfo(blacklistEntry, di)) {
|
||||
aDriverInfo[i] = di;
|
||||
// Prevent di falling out of scope from destroying the devices.
|
||||
di.mDeleteDevices = false;
|
||||
}
|
||||
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;
|
||||
// Prevent di falling out of scope from destroying the devices.
|
||||
di.mDeleteDevices = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -681,19 +537,14 @@ 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;
|
||||
BlacklistEntriesToDriverInfo(blacklistEntries, driverInfo);
|
||||
EvaluateDownloadedBlacklist(driverInfo);
|
||||
}
|
||||
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;
|
||||
@ -770,7 +621,7 @@ GfxInfoBase::FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& info,
|
||||
for (; i < info.Length(); i++) {
|
||||
// Do the operating system check first, no point in getting the driver
|
||||
// info if we won't need to use it. If the OS of the system we are running
|
||||
// on is unknown, we still let DRIVER_OS_ALL catch and disable it;
|
||||
// on is unknown, we still let DRIVER_OS_ALL catch and disable it;
|
||||
// if the OS of the downloadable entry is unknown, we skip the entry
|
||||
// as invalid.
|
||||
if (info[i].mOperatingSystem == DRIVER_OS_UNKNOWN ||
|
||||
|
Loading…
Reference in New Issue
Block a user