This patch adds static asserts to prevent allowlist statuses to be used with non-allowlist features, as well as prevent retired features from being used. It also removes the name/ID split for most features where they are the same. Differential Revision: https://phabricator.services.mozilla.com/D296378
591 lines
22 KiB
C++
591 lines
22 KiB
C++
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef _mozilla_widget_GfxDriverInfo_h_
|
|
#define _mozilla_widget_GfxDriverInfo_h_
|
|
|
|
#include "nsString.h"
|
|
#include "nsTArray.h"
|
|
|
|
// Macros for adding a blocklist item to the static list. _EXT variants
|
|
// allow one to specify all available parameters, including those available
|
|
// only on specific platforms (e.g. desktop environment and driver vendor
|
|
// for Linux.)
|
|
|
|
#define APPEND_TO_DRIVER_BLOCKLIST_EXT( \
|
|
os, screen, battery, windowProtocol, driverVendor, devices, feature, \
|
|
featureStatus, driverComparator, driverVersion, ruleId, suggestedVersion) \
|
|
static_assert(!GfxInfoBase::IsFeatureRetired(feature), \
|
|
"Feature is retired, see GfxInfoFeatureDefs.inc!"); \
|
|
static_assert(GfxInfoBase::IsFeatureStatusAllowed(feature, featureStatus), \
|
|
"Feature status not allowed, see GfxInfoFeatureDefs.inc!"); \
|
|
sDriverInfo->AppendElement(MakeAndAddRef<GfxDriverInfo>( \
|
|
os, screen, battery, \
|
|
(nsAString&)GfxDriverInfo::GetWindowProtocol(windowProtocol), \
|
|
(nsAString&)GfxDriverInfo::GetDeviceVendor(devices), \
|
|
(nsAString&)GfxDriverInfo::GetDriverVendor(driverVendor), \
|
|
GfxDriverInfo::GetDeviceFamily(devices), feature, featureStatus, \
|
|
driverComparator, driverVersion, ruleId, suggestedVersion))
|
|
|
|
#define APPEND_TO_DRIVER_BLOCKLIST(os, devices, feature, featureStatus, \
|
|
driverComparator, driverVersion, ruleId, \
|
|
suggestedVersion) \
|
|
APPEND_TO_DRIVER_BLOCKLIST_EXT( \
|
|
os, ScreenSizeStatus::All, BatteryStatus::All, WindowProtocol::All, \
|
|
DriverVendor::All, devices, feature, featureStatus, driverComparator, \
|
|
driverVersion, ruleId, suggestedVersion)
|
|
|
|
#define APPEND_TO_DRIVER_BLOCKLIST2_EXT( \
|
|
os, screen, battery, windowProtocol, driverVendor, devices, feature, \
|
|
featureStatus, driverComparator, driverVersion, ruleId) \
|
|
static_assert(!GfxInfoBase::IsFeatureRetired(feature), \
|
|
"Feature is retired, see GfxInfoFeatureDefs.inc!"); \
|
|
static_assert(GfxInfoBase::IsFeatureStatusAllowed(feature, featureStatus), \
|
|
"Feature status not allowed, see GfxInfoFeatureDefs.inc!"); \
|
|
sDriverInfo->AppendElement(MakeAndAddRef<GfxDriverInfo>( \
|
|
os, screen, battery, \
|
|
(nsAString&)GfxDriverInfo::GetWindowProtocol(windowProtocol), \
|
|
(nsAString&)GfxDriverInfo::GetDeviceVendor(devices), \
|
|
(nsAString&)GfxDriverInfo::GetDriverVendor(driverVendor), \
|
|
GfxDriverInfo::GetDeviceFamily(devices), feature, featureStatus, \
|
|
driverComparator, driverVersion, ruleId))
|
|
|
|
#define APPEND_TO_DRIVER_BLOCKLIST2(os, devices, feature, featureStatus, \
|
|
driverComparator, driverVersion, ruleId) \
|
|
APPEND_TO_DRIVER_BLOCKLIST2_EXT( \
|
|
os, ScreenSizeStatus::All, BatteryStatus::All, WindowProtocol::All, \
|
|
DriverVendor::All, devices, feature, featureStatus, driverComparator, \
|
|
driverVersion, ruleId)
|
|
|
|
#define APPEND_TO_DRIVER_BLOCKLIST_REFRESH_RATE( \
|
|
os, devices, feature, featureStatus, refreshRateStatus, \
|
|
minRefreshRateComparator, minRefreshRate, minRefreshRateMax, \
|
|
maxRefreshRateComparator, maxRefreshRate, maxRefreshRateMax, ruleId, \
|
|
suggestedVersion) \
|
|
static_assert(!GfxInfoBase::IsFeatureRetired(feature), \
|
|
"Feature is retired, see GfxInfoFeatureDefs.inc!"); \
|
|
static_assert(GfxInfoBase::IsFeatureStatusAllowed(feature, featureStatus), \
|
|
"Feature status not allowed, see GfxInfoFeatureDefs.inc!"); \
|
|
sDriverInfo->AppendElement(MakeAndAddRef<GfxDriverInfo>( \
|
|
os, (nsAString&)GfxDriverInfo::GetDeviceVendor(devices), \
|
|
GfxDriverInfo::GetDeviceFamily(devices), feature, featureStatus, \
|
|
refreshRateStatus, minRefreshRateComparator, minRefreshRate, \
|
|
minRefreshRateMax, maxRefreshRateComparator, maxRefreshRate, \
|
|
maxRefreshRateMax, ruleId, suggestedVersion))
|
|
|
|
#define APPEND_TO_DRIVER_BLOCKLIST_RANGE_EXT( \
|
|
os, screen, battery, windowProtocol, driverVendor, devices, feature, \
|
|
featureStatus, driverComparator, driverVersion, driverVersionMax, ruleId, \
|
|
suggestedVersion) \
|
|
static_assert(!GfxInfoBase::IsFeatureRetired(feature), \
|
|
"Feature is retired, see GfxInfoFeatureDefs.inc!"); \
|
|
static_assert(GfxInfoBase::IsFeatureStatusAllowed(feature, featureStatus), \
|
|
"Feature status not allowed, see GfxInfoFeatureDefs.inc!"); \
|
|
static_assert((driverComparator) == DRIVER_BETWEEN_EXCLUSIVE || \
|
|
(driverComparator) == DRIVER_BETWEEN_INCLUSIVE || \
|
|
(driverComparator) == DRIVER_BETWEEN_INCLUSIVE_START); \
|
|
do { \
|
|
auto info = MakeRefPtr<GfxDriverInfo>( \
|
|
os, screen, battery, \
|
|
(nsAString&)GfxDriverInfo::GetWindowProtocol(windowProtocol), \
|
|
(nsAString&)GfxDriverInfo::GetDeviceVendor(devices), \
|
|
(nsAString&)GfxDriverInfo::GetDriverVendor(driverVendor), \
|
|
GfxDriverInfo::GetDeviceFamily(devices), feature, featureStatus, \
|
|
driverComparator, driverVersion, ruleId, suggestedVersion); \
|
|
info->mDriverVersionMax = driverVersionMax; \
|
|
sDriverInfo->AppendElement(info.forget()); \
|
|
} while (false)
|
|
|
|
#define APPEND_TO_DRIVER_BLOCKLIST_RANGE( \
|
|
os, devices, feature, featureStatus, driverComparator, driverVersion, \
|
|
driverVersionMax, ruleId, suggestedVersion) \
|
|
APPEND_TO_DRIVER_BLOCKLIST_RANGE_EXT( \
|
|
os, ScreenSizeStatus::All, BatteryStatus::All, WindowProtocol::All, \
|
|
DriverVendor::All, devices, feature, featureStatus, driverComparator, \
|
|
driverVersion, driverVersionMax, ruleId, suggestedVersion)
|
|
|
|
#define APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2_EXT( \
|
|
os, screen, battery, windowProtocol, driverVendor, devices, feature, \
|
|
featureStatus, driverComparator, driverVersion, driverVersionMax, ruleId, \
|
|
suggestedVersion) \
|
|
static_assert(!GfxInfoBase::IsFeatureRetired(feature), \
|
|
"Feature is retired, see GfxInfoFeatureDefs.inc!"); \
|
|
static_assert(GfxInfoBase::IsFeatureStatusAllowed(feature, featureStatus), \
|
|
"Feature status not allowed, see GfxInfoFeatureDefs.inc!"); \
|
|
static_assert((driverComparator) == DRIVER_BETWEEN_EXCLUSIVE || \
|
|
(driverComparator) == DRIVER_BETWEEN_INCLUSIVE || \
|
|
(driverComparator) == DRIVER_BETWEEN_INCLUSIVE_START); \
|
|
do { \
|
|
auto info = MakeRefPtr<GfxDriverInfo>( \
|
|
os, screen, battery, \
|
|
(nsAString&)GfxDriverInfo::GetWindowProtocol(windowProtocol), \
|
|
(nsAString&)GfxDriverInfo::GetDeviceVendor(devices), \
|
|
(nsAString&)GfxDriverInfo::GetDriverVendor(driverVendor), \
|
|
GfxDriverInfo::GetDeviceFamily(devices), feature, featureStatus, \
|
|
driverComparator, driverVersion, ruleId, suggestedVersion, false, \
|
|
true); \
|
|
info->mDriverVersionMax = driverVersionMax; \
|
|
sDriverInfo->AppendElement(info.forget()); \
|
|
} while (false)
|
|
|
|
#define APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2( \
|
|
os, devices, feature, featureStatus, driverComparator, driverVersion, \
|
|
driverVersionMax, ruleId, suggestedVersion) \
|
|
APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2_EXT( \
|
|
os, ScreenSizeStatus::All, BatteryStatus::All, WindowProtocol::All, \
|
|
DriverVendor::All, devices, feature, featureStatus, driverComparator, \
|
|
driverVersion, driverVersionMax, ruleId, suggestedVersion)
|
|
|
|
namespace mozilla {
|
|
namespace widget {
|
|
|
|
enum class OperatingSystem : uint8_t {
|
|
Unknown,
|
|
#define GFXINFO_OS(id, name) id,
|
|
#include "mozilla/widget/GfxInfoOperatingSystemDefs.inc"
|
|
#undef GFXINFO_OS
|
|
Count
|
|
};
|
|
|
|
enum VersionComparisonOp {
|
|
#define GFXINFO_DRIVER_VERSION_CMP(id) DRIVER_##id,
|
|
#include "mozilla/widget/GfxInfoDriverVersionCmpDefs.inc"
|
|
#undef GFXINFO_DRIVER_VERSION_CMP
|
|
DRIVER_COUNT
|
|
};
|
|
|
|
enum class DeviceFamily : uint8_t {
|
|
All,
|
|
IntelAll,
|
|
NvidiaAll,
|
|
AtiAll,
|
|
MicrosoftAll,
|
|
ParallelsAll,
|
|
QualcommAll,
|
|
AppleAll,
|
|
AmazonAll,
|
|
IntelGMA500,
|
|
IntelGMA900,
|
|
IntelGMA950,
|
|
IntelGMA3150,
|
|
IntelGMAX3000,
|
|
IntelGMAX4500HD,
|
|
IntelHDGraphicsToIvyBridge,
|
|
IntelHDGraphicsToSandyBridge,
|
|
IntelHaswell,
|
|
IntelSandyBridge,
|
|
IntelGen7Baytrail,
|
|
IntelSkylake,
|
|
IntelKabyLake,
|
|
IntelHD520,
|
|
IntelMobileHDGraphics,
|
|
IntelMeteorLake,
|
|
IntelArrowlake,
|
|
IntelGen12,
|
|
NvidiaBlockD3D9Layers,
|
|
RadeonX1000,
|
|
RadeonCaicos,
|
|
RadeonBlockZeroVideoCopy,
|
|
Geforce7300GT,
|
|
Nvidia310M,
|
|
Nvidia8800GTS,
|
|
NvidiaPascal,
|
|
Bug1137716,
|
|
Bug1116812,
|
|
Bug1155608,
|
|
Bug1207665,
|
|
Bug1447141,
|
|
AmdR600,
|
|
IntelWebRenderBlocked,
|
|
NvidiaWebRenderBlocked,
|
|
|
|
Max
|
|
};
|
|
|
|
enum class DeviceVendor : uint8_t {
|
|
#define GFXINFO_DEVICE_VENDOR(id, name) id,
|
|
#include "mozilla/widget/GfxInfoDeviceVendorDefs.inc"
|
|
#undef GFXINFO_DEVICE_VENDOR
|
|
Max
|
|
};
|
|
|
|
enum DriverVendor : uint8_t {
|
|
#define GFXINFO_DRIVER_VENDOR(id, name) id,
|
|
#include "mozilla/widget/GfxInfoDriverVendorDefs.inc"
|
|
#undef GFXINFO_DRIVER_VENDOR
|
|
Max
|
|
};
|
|
|
|
enum class WindowProtocol : uint8_t {
|
|
#define GFXINFO_WINDOW_PROTOCOL(id, name) id,
|
|
#include "mozilla/widget/GfxInfoWindowProtocolDefs.inc"
|
|
#undef GFXINFO_WINDOW_PROTOCOL
|
|
Max
|
|
};
|
|
|
|
enum class RefreshRateStatus {
|
|
#define GFXINFO_REFRESH_RATE_STATUS(id, name) id,
|
|
#include "mozilla/widget/GfxInfoRefreshRateStatusDefs.inc"
|
|
#undef GFXINFO_REFRESH_RATE_STATUS
|
|
Unknown,
|
|
Count
|
|
};
|
|
|
|
enum class BatteryStatus : uint8_t { All, Present, None };
|
|
|
|
enum class ScreenSizeStatus : uint8_t {
|
|
All,
|
|
Small, // <= 1900x1200
|
|
SmallAndMedium, // <= 3440x1440
|
|
Medium, // <= 3440x1440 && > 1900x1200
|
|
MediumAndLarge, // >1900x1200
|
|
Large // > 3440x1440
|
|
};
|
|
|
|
class GfxVersionEx final {
|
|
static constexpr size_t MAX_PARTS = 4;
|
|
|
|
public:
|
|
GfxVersionEx() = default;
|
|
GfxVersionEx(const GfxVersionEx& aOther) = default;
|
|
GfxVersionEx(GfxVersionEx&& aOther) = default;
|
|
GfxVersionEx& operator=(const GfxVersionEx& aOther) = default;
|
|
GfxVersionEx& operator=(GfxVersionEx&& aOther) = default;
|
|
|
|
GfxVersionEx(uint32_t aMajor, uint32_t aMinor, uint32_t aBuild)
|
|
: mParts{aMajor, aMinor, aBuild} {}
|
|
|
|
GfxVersionEx(uint32_t aMajor, uint32_t aMinor, uint32_t aBuild,
|
|
uint32_t aRevision)
|
|
: mParts{aMajor, aMinor, aBuild, aRevision} {}
|
|
|
|
bool Parse(const nsACString& aVersion) {
|
|
size_t i = 0;
|
|
for (const auto& part : aVersion.Split('.')) {
|
|
nsresult rv;
|
|
mParts[i] = part.ToUnsignedInteger(&rv);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return false;
|
|
}
|
|
|
|
if (++i == MAX_PARTS) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
while (i < MAX_PARTS) {
|
|
mParts[i++] = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int32_t Compare(const GfxVersionEx& aOther) const {
|
|
for (size_t i = 0; i < MAX_PARTS; ++i) {
|
|
if (mParts[i] < aOther.mParts[i]) {
|
|
return -1;
|
|
}
|
|
if (mParts[i] > aOther.mParts[i]) {
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool Compare(const GfxVersionEx& aOther, const GfxVersionEx& aOtherMax,
|
|
VersionComparisonOp aCmp) const {
|
|
if (aCmp == DRIVER_COMPARISON_IGNORED) {
|
|
return true;
|
|
}
|
|
|
|
switch (aCmp) {
|
|
case DRIVER_LESS_THAN:
|
|
return Compare(aOther) < 0;
|
|
case DRIVER_LESS_THAN_OR_EQUAL:
|
|
return Compare(aOther) <= 0;
|
|
case DRIVER_GREATER_THAN:
|
|
return Compare(aOther) > 0;
|
|
case DRIVER_GREATER_THAN_OR_EQUAL:
|
|
return Compare(aOther) >= 0;
|
|
case DRIVER_EQUAL:
|
|
return Compare(aOther) == 0;
|
|
case DRIVER_NOT_EQUAL:
|
|
return Compare(aOther) != 0;
|
|
case DRIVER_BETWEEN_EXCLUSIVE:
|
|
return Compare(aOther) > 0 && Compare(aOtherMax) < 0;
|
|
case DRIVER_BETWEEN_INCLUSIVE:
|
|
return Compare(aOther) >= 0 && Compare(aOtherMax) <= 0;
|
|
case DRIVER_BETWEEN_INCLUSIVE_START:
|
|
return Compare(aOther) >= 0 && Compare(aOtherMax) < 0;
|
|
default:
|
|
NS_WARNING("Unsupported op in GfxDriverInfo");
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
uint32_t mParts[MAX_PARTS]{};
|
|
};
|
|
|
|
/* Array of devices to match, or an empty array for all devices */
|
|
class GfxDeviceFamily final {
|
|
public:
|
|
NS_INLINE_DECL_REFCOUNTING(GfxDeviceFamily);
|
|
|
|
GfxDeviceFamily() = default;
|
|
|
|
void Append(const nsAString& aDeviceId);
|
|
void AppendRange(int32_t aBeginDeviceId, int32_t aEndDeviceId);
|
|
|
|
bool IsEmpty() const { return mIds.IsEmpty() && mRanges.IsEmpty(); }
|
|
|
|
nsresult Contains(nsAString& aDeviceId) const;
|
|
|
|
private:
|
|
~GfxDeviceFamily() = default;
|
|
|
|
struct DeviceRange {
|
|
int32_t mBegin;
|
|
int32_t mEnd;
|
|
};
|
|
|
|
nsTArray<nsString> mIds;
|
|
nsTArray<DeviceRange> mRanges;
|
|
};
|
|
|
|
class GfxDriverInfo final {
|
|
public:
|
|
NS_INLINE_DECL_REFCOUNTING(GfxDriverInfo);
|
|
|
|
// If |ownDevices| is true, you are transferring ownership of the devices
|
|
// array, and it will be deleted when this GfxDriverInfo is destroyed.
|
|
GfxDriverInfo(OperatingSystem os, ScreenSizeStatus aScreen,
|
|
BatteryStatus aBattery, const nsAString& windowProtocol,
|
|
const nsAString& vendor, const nsAString& driverVendor,
|
|
already_AddRefed<const GfxDeviceFamily> devices,
|
|
int32_t feature, int32_t featureStatus, VersionComparisonOp op,
|
|
uint64_t driverVersion, const char* ruleId,
|
|
const char* suggestedVersion = nullptr, bool ownDevices = false,
|
|
bool gpu2 = false);
|
|
|
|
// For blocking on refresh rates rather than driver versions.
|
|
GfxDriverInfo(OperatingSystem os, const nsAString& vendor,
|
|
already_AddRefed<const GfxDeviceFamily> devices,
|
|
int32_t feature, int32_t featureStatus,
|
|
RefreshRateStatus refreshRateStatus,
|
|
VersionComparisonOp minRefreshRateOp, uint32_t minRefreshRate,
|
|
uint32_t minRefreshRateMax,
|
|
VersionComparisonOp maxRefreshRateOp, uint32_t maxRefreshRate,
|
|
uint32_t maxRefreshRateMax, const char* ruleId,
|
|
const char* suggestedVersion = nullptr);
|
|
|
|
GfxDriverInfo();
|
|
|
|
OperatingSystem mOperatingSystem = OperatingSystem::Unknown;
|
|
uint32_t mOperatingSystemVersion = 0;
|
|
|
|
GfxVersionEx mOperatingSystemVersionEx;
|
|
GfxVersionEx mOperatingSystemVersionExMax;
|
|
VersionComparisonOp mOperatingSystemVersionExComparisonOp =
|
|
DRIVER_COMPARISON_IGNORED;
|
|
|
|
uint32_t mMinRefreshRate = 0;
|
|
uint32_t mMinRefreshRateMax = 0;
|
|
VersionComparisonOp mMinRefreshRateComparisonOp = DRIVER_COMPARISON_IGNORED;
|
|
|
|
uint32_t mMaxRefreshRate = 0;
|
|
uint32_t mMaxRefreshRateMax = 0;
|
|
VersionComparisonOp mMaxRefreshRateComparisonOp = DRIVER_COMPARISON_IGNORED;
|
|
|
|
RefreshRateStatus mRefreshRateStatus = RefreshRateStatus::Any;
|
|
|
|
ScreenSizeStatus mScreen = ScreenSizeStatus::All;
|
|
BatteryStatus mBattery = BatteryStatus::All;
|
|
nsString mWindowProtocol;
|
|
|
|
nsString mAdapterVendor;
|
|
nsString mDriverVendor;
|
|
|
|
RefPtr<const GfxDeviceFamily> mDevices;
|
|
|
|
/* Block all features */
|
|
static constexpr int32_t allFeatures = -1;
|
|
/* Block all features not permitted by OnlyAllowFeatureOnKnownConfig */
|
|
static constexpr int32_t optionalFeatures = -2;
|
|
/* A feature from nsIGfxInfo, or a wildcard set of features */
|
|
int32_t mFeature = optionalFeatures;
|
|
|
|
/* A feature status from nsIGfxInfo */
|
|
int32_t mFeatureStatus;
|
|
|
|
VersionComparisonOp mComparisonOp = DRIVER_COMPARISON_IGNORED;
|
|
|
|
/* versions are assumed to be A.B.C.D packed as 0xAAAABBBBCCCCDDDD */
|
|
uint64_t mDriverVersion = 0;
|
|
uint64_t mDriverVersionMax = 0;
|
|
static constexpr uint64_t allDriverVersions = ~(uint64_t(0));
|
|
|
|
const char* mSuggestedVersion = nullptr;
|
|
nsCString mRuleId;
|
|
|
|
static already_AddRefed<const GfxDeviceFamily> GetDeviceFamily(
|
|
DeviceFamily id);
|
|
static RefPtr<GfxDeviceFamily>
|
|
sDeviceFamilies[static_cast<size_t>(DeviceFamily::Max)];
|
|
|
|
static const nsAString& GetWindowProtocol(WindowProtocol id);
|
|
static nsString* sWindowProtocol[static_cast<size_t>(WindowProtocol::Max)];
|
|
|
|
static const nsAString& GetDeviceVendor(DeviceVendor id);
|
|
static const nsAString& GetDeviceVendor(DeviceFamily id);
|
|
static nsString* sDeviceVendors[static_cast<size_t>(DeviceVendor::Max)];
|
|
|
|
static const nsAString& GetDriverVendor(DriverVendor id);
|
|
static nsString* sDriverVendors[static_cast<size_t>(DriverVendor::Max)];
|
|
|
|
nsString mModel, mHardware, mProduct, mManufacturer;
|
|
|
|
bool mGpu2 = false;
|
|
|
|
private:
|
|
~GfxDriverInfo() = default;
|
|
};
|
|
|
|
inline uint64_t DriverVersion(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
|
|
return (uint64_t(a) << 48) | (uint64_t(b) << 32) | (uint64_t(c) << 16) |
|
|
uint64_t(d);
|
|
}
|
|
|
|
inline uint64_t V(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
|
|
#ifdef XP_WIN
|
|
// We make sure every driver number is padded by 0s, this will allow us the
|
|
// easiest 'compare as if decimals' approach. See ParseDriverVersion for a
|
|
// more extensive explanation of this approach.
|
|
while (b > 0 && b < 1000) {
|
|
b *= 10;
|
|
}
|
|
while (c > 0 && c < 1000) {
|
|
c *= 10;
|
|
}
|
|
while (d > 0 && d < 1000) {
|
|
d *= 10;
|
|
}
|
|
#endif
|
|
return DriverVersion(a, b, c, d);
|
|
}
|
|
|
|
// All destination string storage needs to have at least 5 bytes available.
|
|
inline bool SplitDriverVersion(const char* aSource, char* aAStr, char* aBStr,
|
|
char* aCStr, char* aDStr) {
|
|
// sscanf doesn't do what we want here to we parse this manually.
|
|
int len = strlen(aSource);
|
|
|
|
// This "4" is hardcoded in a few places, including once as a 3.
|
|
char* dest[4] = {aAStr, aBStr, aCStr, aDStr};
|
|
unsigned destIdx = 0;
|
|
unsigned destPos = 0;
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
if (destIdx >= 4) {
|
|
// Invalid format found. Ensure we don't access dest beyond bounds.
|
|
return false;
|
|
}
|
|
|
|
if (aSource[i] == '.') {
|
|
MOZ_ASSERT(destIdx < 4 && destPos <= 4);
|
|
dest[destIdx++][destPos] = 0;
|
|
destPos = 0;
|
|
continue;
|
|
}
|
|
|
|
if (destPos > 3) {
|
|
// Ignore more than 4 chars. Ensure we never access dest[destIdx]
|
|
// beyond its bounds.
|
|
continue;
|
|
}
|
|
|
|
MOZ_ASSERT(destIdx < 4 && destPos < 4);
|
|
dest[destIdx][destPos++] = aSource[i];
|
|
}
|
|
|
|
// Take care of the trailing period
|
|
if (destIdx >= 4) {
|
|
return false;
|
|
}
|
|
|
|
// Add last terminator.
|
|
MOZ_ASSERT(destIdx < 4 && destPos <= 4);
|
|
dest[destIdx][destPos] = 0;
|
|
for (int unusedDestIdx = destIdx + 1; unusedDestIdx < 4; unusedDestIdx++) {
|
|
dest[unusedDestIdx][0] = 0;
|
|
}
|
|
|
|
if (destIdx != 3) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// This allows us to pad driver version 'substrings' with 0s, this
|
|
// effectively allows us to treat the version numbers as 'decimals'. This is
|
|
// a little strange but this method seems to do the right thing for all
|
|
// different vendor's driver strings. i.e. .98 will become 9800, which is
|
|
// larger than .978 which would become 9780.
|
|
inline void PadDriverDecimal(char* aString) {
|
|
for (int i = 0; i < 4; i++) {
|
|
if (!aString[i]) {
|
|
for (int c = i; c < 4; c++) {
|
|
aString[c] = '0';
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
aString[4] = 0;
|
|
}
|
|
|
|
inline bool ParseDriverVersion(const nsAString& aVersion,
|
|
uint64_t* aNumericVersion) {
|
|
*aNumericVersion = 0;
|
|
|
|
#ifndef ANDROID
|
|
int a, b, c, d;
|
|
char aStr[8], bStr[8], cStr[8], dStr[8];
|
|
/* honestly, why do I even bother */
|
|
if (!SplitDriverVersion(NS_LossyConvertUTF16toASCII(aVersion).get(), aStr,
|
|
bStr, cStr, dStr))
|
|
return false;
|
|
|
|
# ifdef XP_WIN
|
|
PadDriverDecimal(bStr);
|
|
PadDriverDecimal(cStr);
|
|
PadDriverDecimal(dStr);
|
|
# endif
|
|
|
|
a = atoi(aStr);
|
|
b = atoi(bStr);
|
|
c = atoi(cStr);
|
|
d = atoi(dStr);
|
|
|
|
if (a < 0 || a > 0xffff) return false;
|
|
if (b < 0 || b > 0xffff) return false;
|
|
if (c < 0 || c > 0xffff) return false;
|
|
if (d < 0 || d > 0xffff) return false;
|
|
|
|
*aNumericVersion = DriverVersion(a, b, c, d);
|
|
#else
|
|
// Can't use aVersion.ToInteger() because that's not compiled into our code
|
|
// unless we have XPCOM_GLUE_AVOID_NSPR disabled.
|
|
*aNumericVersion = atoi(NS_LossyConvertUTF16toASCII(aVersion).get());
|
|
#endif
|
|
MOZ_ASSERT(*aNumericVersion != GfxDriverInfo::allDriverVersions);
|
|
return true;
|
|
}
|
|
|
|
} // namespace widget
|
|
} // namespace mozilla
|
|
|
|
#endif /*_mozilla_widget_GfxDriverInfo_h_ */
|