/* vim: se cin sw=2 ts=2 et : */ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * 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/. */
// Call this when setting sFeatureStatus to a non-null pointer to // ensure destruction even if the GfxInfo component is never instantiated. staticvoid InitFeatureStatus(nsTArray<gfx::GfxInfoFeatureStatus>* aPtr) { static std::once_flag sOnce;
std::call_once(sOnce, [] { ClearOnShutdown(&GfxInfoBase::sFeatureStatus); });
GfxInfoBase::sFeatureStatus = aPtr;
}
// Observes for shutdown so that the child GfxDriverInfo list is freed. class ShutdownObserver : public nsIObserver { virtual ~ShutdownObserver() = default;
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService(); if (!observerService) {
NS_WARNING("Could not get observer service!"); return;
}
ShutdownObserver* obs = new ShutdownObserver();
observerService->AddObserver(obs, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
}
// Returns the value of the pref for the relevant feature in aValue. // If the pref doesn't exist, aValue is not touched, and returns false. staticbool GetPrefValueForFeature(int32_t aFeature, int32_t& aValue,
nsACString& aFailureId) { constchar* prefname = GetPrefNameForFeature(aFeature); if (!prefname) returnfalse;
aValue = nsIGfxInfo::FEATURE_STATUS_UNKNOWN; if (!NS_SUCCEEDED(Preferences::GetInt(prefname, &aValue))) { returnfalse;
}
if (aValue == nsIGfxInfo::FEATURE_DENIED) { // We should never see the DENIED status with the downloadable blocklist. returnfalse;
}
// 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 < 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->Append(NS_ConvertUTF8toUTF16(devices[i]));
}
// If we don't recognize the feature, it may be new, and something // this version doesn't understand. So, nothing to do. This is // different from feature not being specified at all, in which case // this method should not get called and we should continue with the // "optional features" blocklisting. return nsIGfxInfo::FEATURE_INVALID;
}
// The default is to ignore it. return DRIVER_COMPARISON_IGNORED;
}
/* Deserialize Blocklist 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
*/ staticbool BlocklistEntryToDriverInfo(const nsACString& aBlocklistEntry,
GfxDriverInfo& aDriverInfo) { // 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. // <versionRange minVersion="42.0a1" maxVersion="45.0"></versionRange> static mozilla::Version zeroV("0"); static mozilla::Version appV(GfxInfoBase::GetApplicationVersion().get()); if (appV <= zeroV) {
gfxCriticalErrorOnce(gfxCriticalError::DefaultOptions(false))
<< "Invalid application version "
<< GfxInfoBase::GetApplicationVersion().get();
}
for (constauto& keyValue : aBlocklistEntry.Split('\t')) {
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 " << nsCString(keyValue).get(); returnfalse;
} const nsCString& key = splitted[0]; const 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(); returnfalse;
}
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. returnfalse;
} 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. returnfalse;
}
} elseif (key.EqualsLiteral("devices")) {
nsTArray<nsCString> devices;
ParseString(value, ',', devices);
GfxDeviceFamily* deviceIds = BlocklistDevicesToDeviceFamily(devices); if (deviceIds) { // Get GfxDriverInfo to adopt the devices array we created.
aDriverInfo.mDeleteDevices = true;
aDriverInfo.mDevices = deviceIds;
}
} // We explicitly ignore unknown elements.
}
for (constauto& blocklistEntry : utf8Data.Split('\n')) {
GfxDriverInfo di; if (BlocklistEntryToDriverInfo(blocklistEntry, di)) { // XXX Changing this to driverInfo.AppendElement(di) causes leaks. // Probably some non-standard semantics of the copy/move operations?
*driverInfo.AppendElement() = di; // Prevent di falling out of scope from destroying the devices.
di.mDeleteDevices = false;
} else {
driverInfo.AppendElement();
}
}
NS_IMETHODIMP
GfxInfoBase::GetFeatureStatus(int32_t aFeature, nsACString& aFailureId,
int32_t* aStatus) { // Ignore the gfx.blocklist.all pref on release and beta. #ifdefined(RELEASE_OR_BETA)
int32_t blocklistAll = 0; #else
int32_t blocklistAll = StaticPrefs::gfx_blocklist_all_AtStartup(); #endif if (blocklistAll > 0) {
gfxCriticalErrorOnce(gfxCriticalError::DefaultOptions(false))
<< "Forcing blocklisting all features";
*aStatus = FEATURE_BLOCKED_DEVICE;
aFailureId = "FEATURE_FAILURE_BLOCK_ALL"; return NS_OK;
}
if (blocklistAll < 0) {
gfxCriticalErrorOnce(gfxCriticalError::DefaultOptions(false))
<< "Ignoring any feature blocklisting.";
*aStatus = FEATURE_STATUS_OK; return NS_OK;
}
// This is how we evaluate the downloadable blocklist. If there is no pref, // then we will fallback to checking the static blocklist. if (GetPrefValueForFeature(aFeature, *aStatus, aFailureId)) { return NS_OK;
}
if (XRE_IsContentProcess() || XRE_IsGPUProcess()) { // Use the cached data received from the parent process.
MOZ_ASSERT(sFeatureStatus); bool success = false; for (constauto& fs : *sFeatureStatus) { if (fs.feature() == aFeature) {
aFailureId = fs.failureId();
*aStatus = fs.status();
success = true; break;
}
} return success ? NS_OK : NS_ERROR_FAILURE;
}
nsTArray<gfx::GfxInfoFeatureStatus> GfxInfoBase::GetAllFeatures() {
MOZ_RELEASE_ASSERT(XRE_IsParentProcess()); if (!sFeatureStatus) {
InitFeatureStatus(new nsTArray<gfx::GfxInfoFeatureStatus>()); for (int32_t i = nsIGfxInfo::FEATURE_START; i < nsIGfxInfo::FEATURE_COUNT;
++i) {
int32_t status = nsIGfxInfo::FEATURE_STATUS_INVALID;
nsAutoCString failureId;
GetFeatureStatus(i, failureId, &status);
gfx::GfxInfoFeatureStatus gfxFeatureStatus;
gfxFeatureStatus.feature() = i;
gfxFeatureStatus.status() = status;
gfxFeatureStatus.failureId() = failureId;
sFeatureStatus->AppendElement(gfxFeatureStatus);
}
}
nsTArray<gfx::GfxInfoFeatureStatus> features; for (constauto& status : *sFeatureStatus) {
gfx::GfxInfoFeatureStatus copy = status;
features.AppendElement(copy);
} return features;
}
inlinebool MatchingAllowStatus(int32_t aStatus) { switch (aStatus) { case nsIGfxInfo::FEATURE_ALLOW_ALWAYS: case nsIGfxInfo::FEATURE_ALLOW_QUALIFIED: returntrue; default: returnfalse;
}
}
// Matching OS go somewhat beyond the simple equality check because of the // "All Windows" and "All OS X" variations. // // aBlockedOS is describing the system(s) we are trying to block. // aSystemOS is describing the system we are running on. // // aSystemOS should not be "Windows" or "OSX" - it should be set to // a particular version instead. // However, it is valid for aBlockedOS to be one of those generic values, // as we could be blocking all of the versions. inlinebool MatchingOperatingSystems(OperatingSystem aBlockedOS,
OperatingSystem aSystemOS,
uint32_t aSystemOSBuild) {
MOZ_ASSERT(aSystemOS != OperatingSystem::Windows &&
aSystemOS != OperatingSystem::OSX);
// If the block entry OS is unknown, it doesn't match if (aBlockedOS == OperatingSystem::Unknown) { returnfalse;
}
#ifdefined(XP_WIN) if (aBlockedOS == OperatingSystem::Windows) { // We do want even "unknown" aSystemOS to fall under "all windows" returntrue;
}
constexpr uint32_t kMinWin10BuildNumber = 18362; if (aBlockedOS == OperatingSystem::RecentWindows10 &&
aSystemOS == OperatingSystem::Windows10) { // For allowlist purposes, we sometimes want to restrict to only recent // versions of Windows 10. This is a bit of a kludge but easier than adding // complicated blocklist infrastructure for build ID comparisons like driver // versions. return aSystemOSBuild >= kMinWin10BuildNumber;
}
// Some properties are not available on all platforms.
nsAutoString windowProtocol;
nsresult rv = GetWindowProtocol(windowProtocol); if (NS_FAILED(rv) && rv != NS_ERROR_NOT_IMPLEMENTED) { return 0;
}
// Get the adapters once then reuse below
nsAutoString adapterVendorID[2];
nsAutoString adapterDeviceID[2];
nsAutoString adapterDriverVendor[2];
nsAutoString adapterDriverVersionString[2]; bool adapterInfoFailed[2];
adapterInfoFailed[0] =
(NS_FAILED(GetAdapterVendorID(adapterVendorID[0])) ||
NS_FAILED(GetAdapterDeviceID(adapterDeviceID[0])) ||
NS_FAILED(GetAdapterDriverVendor(adapterDriverVendor[0])) ||
NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString[0])));
adapterInfoFailed[1] =
(NS_FAILED(GetAdapterVendorID2(adapterVendorID[1])) ||
NS_FAILED(GetAdapterDeviceID2(adapterDeviceID[1])) ||
NS_FAILED(GetAdapterDriverVendor2(adapterDriverVendor[1])) ||
NS_FAILED(GetAdapterDriverVersion2(adapterDriverVersionString[1]))); // No point in going on if we don't have adapter info if (adapterInfoFailed[0] && adapterInfoFailed[1]) { return 0;
}
uint32_t i = 0; for (; i < info.Length(); i++) { // If the status is FEATURE_ALLOW_*, then it is for the allowlist, not // blocklisting. Only consider entries for our search mode. if (MatchingAllowStatus(info[i].mFeatureStatus) != aForAllowing) { continue;
}
// If we don't have the info for this GPU, no need to check further. // It is unclear that we would ever have a mixture of 1st and 2nd // GPU, but leaving the code in for that possibility for now. // (Actually, currently mGpu2 will never be true, so this can // be optimized out.)
uint32_t infoIndex = info[i].mGpu2 ? 1 : 0; if (adapterInfoFailed[infoIndex]) { continue;
}
// Do the operating system check first, no point in getting the driver // info if we won't need to use it. if (!MatchingOperatingSystems(info[i].mOperatingSystem, os, osBuild)) { continue;
}
if (info[i].mOperatingSystemVersion &&
info[i].mOperatingSystemVersion != OperatingSystemVersion()) { continue;
}
if (!MatchingBattery(info[i].mBattery, hasBattery)) { continue;
}
if (!MatchingScreenSize(info[i].mScreen, mScreenPixels)) { continue;
}
if (!DoesWindowProtocolMatch(info[i].mWindowProtocol, windowProtocol)) { continue;
}
if (!DoesVendorMatch(info[i].mAdapterVendor, adapterVendorID[infoIndex])) { continue;
}
if (!DoesDriverVendorMatch(info[i].mDriverVendor,
adapterDriverVendor[infoIndex])) { continue;
}
if (info[i].mDevices && !info[i].mDevices->IsEmpty()) {
nsresult rv = info[i].mDevices->Contains(adapterDeviceID[infoIndex]); if (rv == NS_ERROR_NOT_AVAILABLE) { // Not found continue;
} if (rv != NS_OK) { // Failed to search, allowlist should not match, blocklist should match // for safety reasons if (aForAllowing) { continue;
} break;
}
}
bool match = false;
if (!info[i].mHardware.IsEmpty() && !info[i].mHardware.Equals(Hardware())) { continue;
} if (!info[i].mModel.IsEmpty() && !info[i].mModel.Equals(Model())) { continue;
} if (!info[i].mProduct.IsEmpty() && !info[i].mProduct.Equals(Product())) { continue;
} if (!info[i].mManufacturer.IsEmpty() &&
!info[i].mManufacturer.Equals(Manufacturer())) { continue;
}
#ifdefined(XP_WIN) || defined(ANDROID) || defined(MOZ_WIDGET_GTK) switch (info[i].mComparisonOp) { case DRIVER_LESS_THAN:
match = driverVersion[infoIndex] < info[i].mDriverVersion; break; case DRIVER_BUILD_ID_LESS_THAN:
match = (driverVersion[infoIndex] & 0xFFFF) < info[i].mDriverVersion; break; case DRIVER_LESS_THAN_OR_EQUAL:
match = driverVersion[infoIndex] <= info[i].mDriverVersion; break; case DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL:
match = (driverVersion[infoIndex] & 0xFFFF) <= info[i].mDriverVersion; break; case DRIVER_GREATER_THAN:
match = driverVersion[infoIndex] > info[i].mDriverVersion; break; case DRIVER_GREATER_THAN_OR_EQUAL:
match = driverVersion[infoIndex] >= info[i].mDriverVersion; break; case DRIVER_EQUAL:
match = driverVersion[infoIndex] == info[i].mDriverVersion; break; case DRIVER_NOT_EQUAL:
match = driverVersion[infoIndex] != info[i].mDriverVersion; break; case DRIVER_BETWEEN_EXCLUSIVE:
match = driverVersion[infoIndex] > info[i].mDriverVersion &&
driverVersion[infoIndex] < info[i].mDriverVersionMax; break; case DRIVER_BETWEEN_INCLUSIVE:
match = driverVersion[infoIndex] >= info[i].mDriverVersion &&
driverVersion[infoIndex] <= info[i].mDriverVersionMax; break; case DRIVER_BETWEEN_INCLUSIVE_START:
match = driverVersion[infoIndex] >= info[i].mDriverVersion &&
driverVersion[infoIndex] < info[i].mDriverVersionMax; break; case DRIVER_COMPARISON_IGNORED: // We don't have a comparison op, so we match everything.
match = true; break; default:
NS_WARNING("Bogus op in GfxDriverInfo"); break;
} #else // We don't care what driver version it was. We only check OS version and if // the device matches.
match = true; #endif
#ifdefined(XP_WIN) // As a very special case, we block D2D on machines with an NVidia 310M GPU // as either the primary or secondary adapter. D2D is also blocked when the // NV 310M is the primary adapter (using the standard blocklisting mechanism). // If the primary GPU already matched something in the blocklist then we // ignore this special rule. See bug 1008759. if (status == nsIGfxInfo::FEATURE_STATUS_UNKNOWN &&
(aFeature == nsIGfxInfo::FEATURE_DIRECT2D)) { if (!adapterInfoFailed[1]) {
nsAString& nvVendorID =
(nsAString&)GfxDriverInfo::GetDeviceVendor(DeviceVendor::NVIDIA); const nsString nv310mDeviceId = u"0x0A70"_ns; if (nvVendorID.Equals(adapterVendorID[1],
nsCaseInsensitiveStringComparator) &&
nv310mDeviceId.Equals(adapterDeviceID[1],
nsCaseInsensitiveStringComparator)) {
status = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
aFailureId = "FEATURE_FAILURE_D2D_NV310M_BLOCK";
}
}
}
// Depends on Windows driver versioning. We don't pass a GfxDriverInfo object // back to the Windows handler, so we must handle this here. if (status == FEATURE_BLOCKED_DRIVER_VERSION) { if (info[i].mSuggestedVersion) {
aSuggestedVersion.AppendPrintf("%s", info[i].mSuggestedVersion);
} elseif (info[i].mComparisonOp == DRIVER_LESS_THAN &&
info[i].mDriverVersion != GfxDriverInfo::allDriverVersions) {
aSuggestedVersion.AppendPrintf( "%lld.%lld.%lld.%lld",
(info[i].mDriverVersion & 0xffff000000000000) >> 48,
(info[i].mDriverVersion & 0x0000ffff00000000) >> 32,
(info[i].mDriverVersion & 0x00000000ffff0000) >> 16,
(info[i].mDriverVersion & 0x000000000000ffff));
}
} #endif
if (*aStatus != nsIGfxInfo::FEATURE_STATUS_UNKNOWN) { // Terminate now with the status determined by the derived type (OS-specific // code). return NS_OK;
}
if (sShutdownOccurred) { // This is futile; we've already commenced shutdown and our blocklists have // been deleted. We may want to look into resurrecting the blocklist instead // but for now, just don't even go there. return NS_OK;
}
// Ensure any additional initialization required is complete.
GetData();
// If an operating system was provided by the derived GetFeatureStatusImpl, // grab it here. Otherwise, the OS is unknown.
OperatingSystem os = (aOS ? *aOS : OperatingSystem::Unknown);
// We only check either the given blocklist, or the static list, as given.
int32_t status; if (aDriverInfo.Length()) {
status =
FindBlocklistedDeviceInList(aDriverInfo, aSuggestedVersion, aFeature,
aFailureId, os, /* aForAllowing */ false);
} else { if (!sDriverInfo) {
sDriverInfo = new nsTArray<GfxDriverInfo>();
}
status = FindBlocklistedDeviceInList(GetGfxDriverInfo(), aSuggestedVersion,
aFeature, aFailureId, os, /* aForAllowing */ false);
}
if (status == nsIGfxInfo::FEATURE_STATUS_UNKNOWN) { if (IsFeatureAllowlisted(aFeature)) { // This feature is actually using the allowlist; that means after we pass // the blocklist to prevent us explicitly from getting the feature, we now // need to check the allowlist to ensure we are allowed to get it in the // first place. if (aDriverInfo.Length()) {
status = FindBlocklistedDeviceInList(aDriverInfo, aSuggestedVersion,
aFeature, aFailureId, os, /* aForAllowing */ true);
} else {
status = FindBlocklistedDeviceInList(
GetGfxDriverInfo(), aSuggestedVersion, aFeature, aFailureId, os, /* aForAllowing */ true);
}
if (status == nsIGfxInfo::FEATURE_STATUS_UNKNOWN) {
status = nsIGfxInfo::FEATURE_DENIED;
}
} else { // It's now done being processed. It's safe to set the status to // STATUS_OK.
status = nsIGfxInfo::FEATURE_STATUS_OK;
}
}
void GfxInfoBase::EvaluateDownloadedBlocklist(
nsTArray<GfxDriverInfo>& aDriverInfo) { // If the list is empty, then we don't actually want to call // GetFeatureStatusImpl since we will use the static list instead. In that // case, all we want to do is make sure the pref is removed. if (aDriverInfo.IsEmpty()) {
gfxCriticalNoteOnce << "Evaluate empty downloaded blocklist"; return;
}
OperatingSystem os = GetOperatingSystem();
// For every feature we know about, we evaluate whether this blocklist has a // non-STATUS_OK status. If it does, we set the pref we evaluate in // GetFeatureStatus above, so we don't need to hold on to this blocklist // anywhere permanent. for (int feature = nsIGfxInfo::FEATURE_START;
feature < nsIGfxInfo::FEATURE_COUNT; ++feature) {
int32_t status = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
nsCString failureId;
nsAutoString suggestedVersion;
// Note that we are careful to call the base class method since we only want // to evaluate the downloadable blocklist for these prefs.
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(GfxInfoBase::GetFeatureStatusImpl(
feature, &status, suggestedVersion, aDriverInfo, failureId, &os)));
switch (status) { default:
MOZ_FALLTHROUGH_ASSERT("Unhandled feature status!"); case nsIGfxInfo::FEATURE_STATUS_UNKNOWN: // This may be returned during shutdown or for invalid features. case nsIGfxInfo::FEATURE_ALLOW_ALWAYS: case nsIGfxInfo::FEATURE_ALLOW_QUALIFIED: case nsIGfxInfo::FEATURE_DENIED: // We cannot use the downloadable blocklist to control the allowlist. // If a feature is allowlisted, then we should also ignore DENIED // statuses from GetFeatureStatusImpl because we don't check the // static list when and this is an expected value. If we wish to // override the allowlist, it is as simple as creating a normal // blocklist rule with a BLOCKED* status code. case nsIGfxInfo::FEATURE_STATUS_OK:
RemovePrefForFeature(feature); break;
case nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION: if (!suggestedVersion.IsEmpty()) {
SetPrefValueForDriverVersion(suggestedVersion);
} else {
RemovePrefForDriverVersion();
}
[[fallthrough]];
case nsIGfxInfo::FEATURE_BLOCKED_MISMATCHED_VERSION: case nsIGfxInfo::FEATURE_BLOCKED_DEVICE: case nsIGfxInfo::FEATURE_DISCOURAGED: case nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION: case nsIGfxInfo::FEATURE_BLOCKED_PLATFORM_TEST:
SetPrefValueForFeature(feature, status, failureId); break;
}
}
}
NS_IMETHODIMP_(void)
GfxInfoBase::LogFailure(const nsACString& failure) { // gfxCriticalError has a mutex lock of its own, so we may not actually // need this lock. ::GetFailures() accesses the data but the LogForwarder // will not return the copy of the logs unless it can get the same lock // that gfxCriticalError uses. Still, that is so much of an implementation // detail that it's nicer to just add an extra lock here and in // ::GetFailures()
MutexAutoLock lock(mMutex);
// By default, gfxCriticalError asserts; make it not assert in this case.
gfxCriticalError(CriticalLog::DefaultOptions(false))
<< "(LF) " << failure.BeginReading();
}
LogForwarder* logForwarder = Factory::GetLogForwarder(); if (!logForwarder) { return NS_ERROR_UNEXPECTED;
}
// There are two string copies in this method, starting with this one. We are // assuming this is not a big deal, as the size of the array should be small // and the strings in it should be small as well (the error messages in the // code.) The second copy happens with the AppendElement() calls. // Technically, we don't need the mutex lock after the StringVectorCopy() // call.
LoggingRecord loggedStrings = logForwarder->LoggingRecordCopy();
LoggingRecord::const_iterator it; for (it = loggedStrings.begin(); it != loggedStrings.end(); ++it) {
failures.AppendElement(nsDependentCSubstring(std::get<1>(*it).c_str(),
std::get<1>(*it).size()));
indices.AppendElement(std::get<0>(*it));
}
return NS_OK;
}
nsTArray<GfxInfoCollectorBase*>* sCollectors;
staticvoid InitCollectors() { if (!sCollectors) sCollectors = new nsTArray<GfxInfoCollectorBase*>;
}
for (uint32_t i = 0; i < sCollectors->Length(); i++) {
(*sCollectors)[i]->GetInfo(obj);
}
// Some example property definitions // obj.DefineProperty("wordCacheSize", gfxTextRunWordCache::Count()); // obj.DefineProperty("renderer", mRendererIDsString); // obj.DefineProperty("five", 5);
if (!obj.mOk) { return NS_ERROR_FAILURE;
}
aResult.setObject(*obj.mObj); return NS_OK;
}
MOZ_RUNINIT nsAutoCString gBaseAppVersion;
const nsCString& GfxInfoBase::GetApplicationVersion() { staticbool versionInitialized = false; if (!versionInitialized) { // If we fail to get the version, we will not try again.
versionInitialized = true;
// Get the version from xpcom/system/nsIXULAppInfo.idl
nsCOMPtr<nsIXULAppInfo> app = do_GetService("@mozilla.org/xre/app-info;1"); if (app) {
app->GetVersion(gBaseAppVersion);
}
} return gBaseAppVersion;
}
/* static */ bool GfxInfoBase::OnlyAllowFeatureOnKnownConfig(int32_t aFeature) { switch (aFeature) { // The GPU process doesn't need hardware acceleration and can run on // devices that we normally block from not being on our whitelist. case nsIGfxInfo::FEATURE_GPU_PROCESS: return kIsAndroid; // We can mostly assume that ANGLE will work case nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE: // Remote WebGL is needed for Win32k Lockdown, so it should be enabled // regardless of HW support or not case nsIGfxInfo::FEATURE_ALLOW_WEBGL_OUT_OF_PROCESS: // Backdrop filter should generally work, especially if we fall back to // Software WebRender because of an unknown vendor. case nsIGfxInfo::FEATURE_BACKDROP_FILTER: returnfalse; default: returntrue;
}
}
nsresult GfxInfoBase::FindMonitors(JSContext* aCx,
JS::Handle<JSObject*> aOutArray) {
int32_t index = 0; auto& sm = ScreenManager::GetSingleton(); for (auto& screen : sm.CurrentScreenList()) {
AppendMonitor(aCx, *screen, aOutArray, index++);
}
if (index == 0) { // Ensure we return at least one monitor, this is needed for xpcshell.
RefPtr<Screen> screen = sm.GetPrimaryScreen();
AppendMonitor(aCx, *screen, aOutArray, index++);
}
using Device = nsIGfxInfo::FontVisibilityDeviceDetermination; static StaticAutoPtr<std::pair<Device, nsString>> ret;
std::pair<Device, nsString>* GfxInfoBase::GetFontVisibilityDeterminationPair() { if (!ret) {
ret = new std::pair<Device, nsString>();
ret->first = Device::Unassigned;
ret->second = u""_ns;
ClearOnShutdown(&ret);
}
if (ret->first != Device::Unassigned) { return ret;
}
#ifdefined(MOZ_WIDGET_ANDROID) auto androidReleaseVersion = strtol(
java::sdk::Build::VERSION::RELEASE()->ToCString().get(), nullptr, 10);
auto androidManufacturer = java::sdk::Build::MANUFACTURER()->ToCString();
nsContentUtils::ASCIIToLower(androidManufacturer);
auto androidBrand = java::sdk::Build::BRAND()->ToCString();
nsContentUtils::ASCIIToLower(androidBrand);
auto androidModel = java::sdk::Build::MODEL()->ToCString();
nsContentUtils::ASCIIToLower(androidModel);
auto androidProduct = java::sdk::Build::PRODUCT()->ToCString();
nsContentUtils::ASCIIToLower(androidProduct);
auto androidProductIsChromebook = ProductIsChromebook(androidProduct);
if (androidReleaseVersion < 4 || androidReleaseVersion > 20) { // Something is screwy, oh well.
ret->second.AppendASCII("Unknown Release Version - ");
ret->first = Device::Android_Unknown_Release_Version;
} elseif (androidReleaseVersion <= 8) {
ret->second.AppendASCII("Android <9 - ");
ret->first = Device::Android_sub_9;
} elseif (androidReleaseVersion <= 11) {
ret->second.AppendASCII("Android 9-11 - ");
ret->first = Device::Android_9_11;
} elseif (androidReleaseVersion > 11) {
ret->second.AppendASCII("Android 12+ - ");
ret->first = Device::Android_12_plus;
} else {
MOZ_CRASH_UNSAFE_PRINTF( "Somehow wound up in GetFontVisibilityDeterminationPair with a release " "version of %li",
androidReleaseVersion);
}
if (androidManufacturer == "google" && androidModel == androidProduct &&
androidProductIsChromebook) { // Chromebook font set coming later
ret->second.AppendASCII("Chromebook - ");
ret->first = Device::Android_Chromebook;
} if (androidBrand == "amazon") { // Amazon Fire font set coming later
ret->second.AppendASCII("Amazon - ");
ret->first = Device::Android_Amazon;
} if (androidBrand == "peloton") { // We don't know how to categorize fonts on this system
ret->second.AppendASCII("Peloton - ");
ret->first = Device::Android_Unknown_Peloton;
} if (androidProduct == "vbox86p") {
ret->second.AppendASCII("vbox - "); // We can't categorize fonts when running in an emulator on a Desktop
ret->first = Device::Android_Unknown_vbox;
} if (androidModel.Find("mitv"_ns) != kNotFound && androidBrand == "xiaomi") { // We don't know how to categorize fonts on this system
ret->second.AppendASCII("mitv - ");
ret->first = Device::Android_Unknown_mitv;
}
NS_IMETHODIMP GfxInfoBase::KillGPUProcessForTests() {
GPUProcessManager* gpm = GPUProcessManager::Get(); if (!gpm) { // gfxPlatform has not been initialized. return NS_ERROR_NOT_INITIALIZED;
}
gpm->KillProcess(); return NS_OK;
}
NS_IMETHODIMP GfxInfoBase::CrashGPUProcessForTests() {
GPUProcessManager* gpm = GPUProcessManager::Get(); if (!gpm) { // gfxPlatform has not been initialized. return NS_ERROR_NOT_INITIALIZED;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.