summaryrefslogtreecommitdiffstats
path: root/widget
diff options
context:
space:
mode:
Diffstat (limited to 'widget')
-rw-r--r--widget/GfxInfoBase.cpp29
-rw-r--r--widget/GfxInfoBase.h2
-rw-r--r--widget/LSBUtils.cpp73
-rw-r--r--widget/android/GfxInfo.cpp7
-rw-r--r--widget/cocoa/nsChildView.mm8
-rw-r--r--widget/cocoa/nsCursorManager.h3
-rw-r--r--widget/cocoa/nsCursorManager.mm9
-rw-r--r--widget/gtk/GfxInfo.cpp23
-rw-r--r--widget/gtk/nsWindow.cpp5
-rw-r--r--widget/nsBaseWidget.cpp8
-rw-r--r--widget/nsBaseWidget.h5
-rw-r--r--widget/nsIWidget.h2
-rw-r--r--widget/windows/GfxInfo.cpp47
-rw-r--r--widget/windows/nsWindow.cpp5
14 files changed, 179 insertions, 47 deletions
diff --git a/widget/GfxInfoBase.cpp b/widget/GfxInfoBase.cpp
index 66dd10da8a..f33702ae85 100644
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -30,6 +30,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/StaticPrefs_gfx.h"
#include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/BuildConstants.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/gfxVars.h"
@@ -1297,8 +1298,12 @@ nsresult GfxInfoBase::GetFeatureStatusImpl(
if (NS_FAILED(GetAdapterVendorID(adapterVendorID)) ||
NS_FAILED(GetAdapterDeviceID(adapterDeviceID)) ||
NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString))) {
- aFailureId = "FEATURE_FAILURE_CANT_RESOLVE_ADAPTER";
- *aStatus = FEATURE_BLOCKED_DEVICE;
+ if (OnlyAllowFeatureOnKnownConfig(aFeature)) {
+ aFailureId = "FEATURE_FAILURE_CANT_RESOLVE_ADAPTER";
+ *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
+ } else {
+ *aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
+ }
return NS_OK;
}
@@ -1512,6 +1517,26 @@ const nsCString& GfxInfoBase::GetApplicationVersion() {
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:
+ return false;
+ default:
+ return true;
+ }
+}
+
void GfxInfoBase::AddCollector(GfxInfoCollectorBase* collector) {
InitCollectors();
sCollectors->AppendElement(collector);
diff --git a/widget/GfxInfoBase.h b/widget/GfxInfoBase.h
index f38746af19..73eb318f3c 100644
--- a/widget/GfxInfoBase.h
+++ b/widget/GfxInfoBase.h
@@ -111,6 +111,8 @@ class GfxInfoBase : public nsIGfxInfo,
static void SetFeatureStatus(
nsTArray<mozilla::gfx::GfxInfoFeatureStatus>&& aFS);
+ static bool OnlyAllowFeatureOnKnownConfig(int32_t aFeature);
+
protected:
virtual ~GfxInfoBase();
diff --git a/widget/LSBUtils.cpp b/widget/LSBUtils.cpp
index bcadddef12..520d50e5cc 100644
--- a/widget/LSBUtils.cpp
+++ b/widget/LSBUtils.cpp
@@ -6,6 +6,9 @@
#include "LSBUtils.h"
+#include <fstream>
+#include <string>
+#include <string_view>
#include <unistd.h>
#include "base/process_util.h"
#include "mozilla/FileUtils.h"
@@ -15,10 +18,78 @@
namespace mozilla::widget::lsb {
-static const char* gLsbReleasePath = "/usr/bin/lsb_release";
+static const char gLsbReleasePath[] = "/usr/bin/lsb_release";
+static const char gEtcOsReleasePath[] = "/etc/os-release";
+static const char gUsrOsReleasePath[] = "/usr/lib/os-release";
+
+// See https://www.freedesktop.org/software/systemd/man/latest/os-release.html
+bool ExtractAndSetValue(nsACString& aContainer, std::string_view& aValue) {
+ // We assume the value is well formed and doesn't contain escape characters.
+ if (aValue.size() > 1 && (aValue.front() == '"' || aValue.front() == '\'')) {
+ // We assume the quote is properly balanced.
+ aValue = aValue.substr(1, aValue.size() - 2);
+ }
+ aContainer.Assign(aValue.data(), aValue.size());
+ return !aValue.empty();
+}
+
+bool GetOSRelease(nsACString& aDistributor, nsACString& aDescription,
+ nsACString& aRelease, nsACString& aCodename) {
+ std::ifstream stream(gEtcOsReleasePath);
+ if (stream.fail()) {
+ stream.open(gUsrOsReleasePath);
+ if (stream.fail()) {
+ return false;
+ }
+ }
+ bool seen_id = false, seen_pretty_name = false, seen_version_id = false;
+ std::string rawline;
+ nsAutoCString name;
+ while (std::getline(stream, rawline)) {
+ std::string_view line(rawline);
+ size_t pos = line.find('=');
+ if (pos != std::string_view::npos) {
+ auto key = line.substr(0, pos);
+ auto value = line.substr(pos + 1);
+ if (key == "ID") {
+ if (ExtractAndSetValue(aDistributor, value)) {
+ // Capitalize the first letter of the id. This mimics what
+ // lsb_release does on Debian and derivatives. On RH derivatives,
+ // ID tends to be capitalized already.
+ char* c = aDistributor.BeginWriting();
+ if (*c >= 'a' && *c <= 'z') {
+ *c -= ('a' - 'A');
+ }
+ seen_id = true;
+ }
+ } else if (key == "NAME") {
+ ExtractAndSetValue(name, value);
+ } else if (key == "PRETTY_NAME") {
+ if (ExtractAndSetValue(aDescription, value)) seen_pretty_name = true;
+ } else if (key == "VERSION_ID") {
+ if (ExtractAndSetValue(aRelease, value)) seen_version_id = true;
+ } else if (key == "VERSION_CODENAME") {
+ ExtractAndSetValue(aCodename, value);
+ }
+ }
+ }
+ // If NAME is set and only differs from ID in case, use NAME.
+ if (seen_id && !name.IsEmpty() && name.EqualsIgnoreCase(aDistributor)) {
+ aDistributor = name;
+ }
+ // Only consider our work done if we've seen at least ID, PRETTY_NAME and
+ // VERSION_ID.
+ return seen_id && seen_pretty_name && seen_version_id;
+}
bool GetLSBRelease(nsACString& aDistributor, nsACString& aDescription,
nsACString& aRelease, nsACString& aCodename) {
+ // Nowadays, /etc/os-release is more likely to be available than
+ // /usr/bin/lsb_release. Relying on the former also avoids forking.
+ if (GetOSRelease(aDistributor, aDescription, aRelease, aCodename)) {
+ return true;
+ }
+
if (access(gLsbReleasePath, R_OK) != 0) return false;
int pipefd[2];
diff --git a/widget/android/GfxInfo.cpp b/widget/android/GfxInfo.cpp
index e4f8d5d88b..4f42256e0d 100644
--- a/widget/android/GfxInfo.cpp
+++ b/widget/android/GfxInfo.cpp
@@ -398,7 +398,12 @@ nsresult GfxInfo::GetFeatureStatusImpl(
EnsureInitialized();
if (mGLStrings->Vendor().IsEmpty() || mGLStrings->Renderer().IsEmpty()) {
- *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
+ if (OnlyAllowFeatureOnKnownConfig(aFeature)) {
+ *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
+ aFailureId = "FEATURE_FAILURE_EMPTY_VENDOR_OR_RENDERER";
+ } else {
+ *aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
+ }
return NS_OK;
}
diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm
index 4f9e69f2b9..0968fc89eb 100644
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -617,8 +617,12 @@ void nsChildView::SetCursor(const Cursor& aCursor) {
nsBaseWidget::SetCursor(aCursor);
- if (NS_SUCCEEDED([[nsCursorManager sharedInstance] setCustomCursor:aCursor
- widgetScaleFactor:BackingScaleFactor()])) {
+ bool forceUpdate = mUpdateCursor;
+ mUpdateCursor = false;
+ if (mCustomCursorAllowed && NS_SUCCEEDED([[nsCursorManager sharedInstance]
+ setCustomCursor:aCursor
+ widgetScaleFactor:BackingScaleFactor()
+ forceUpdate:forceUpdate])) {
return;
}
diff --git a/widget/cocoa/nsCursorManager.h b/widget/cocoa/nsCursorManager.h
index c36d8962fb..f3acbb68e9 100644
--- a/widget/cocoa/nsCursorManager.h
+++ b/widget/cocoa/nsCursorManager.h
@@ -35,7 +35,8 @@
// As above, but returns an error if the cursor isn't custom or we couldn't set
// it for some reason.
- (nsresult)setCustomCursor:(const nsIWidget::Cursor&)aCursor
- widgetScaleFactor:(CGFloat)aWidgetScaleFactor;
+ widgetScaleFactor:(CGFloat)aWidgetScaleFactor
+ forceUpdate:(bool)aForceUpdate;
/*! @method sharedInstance
@abstract Get the Singleton instance of the cursor manager.
diff --git a/widget/cocoa/nsCursorManager.mm b/widget/cocoa/nsCursorManager.mm
index 6596df25a3..e480f48da6 100644
--- a/widget/cocoa/nsCursorManager.mm
+++ b/widget/cocoa/nsCursorManager.mm
@@ -238,11 +238,14 @@ static constexpr nsCursor kCustomCursor = eCursorCount;
}
- (nsresult)setCustomCursor:(const nsIWidget::Cursor&)aCursor
- widgetScaleFactor:(CGFloat)scaleFactor {
+ widgetScaleFactor:(CGFloat)scaleFactor
+ forceUpdate:(bool)aForceUpdate {
NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
- // As the user moves the mouse, this gets called repeatedly with the same aCursorImage
- if (sCurrentCursor == aCursor && sCurrentCursorScaleFactor == scaleFactor && mCurrentMacCursor) {
+ // As the user moves the mouse, this gets called repeatedly with the same
+ // aCursorImage
+ if (!aForceUpdate && sCurrentCursor == aCursor &&
+ sCurrentCursorScaleFactor == scaleFactor && mCurrentMacCursor) {
// Native dragging can unset our cursor apparently (see bug 1739352).
if (MOZ_UNLIKELY(![mCurrentMacCursor isSet])) {
[mCurrentMacCursor set];
diff --git a/widget/gtk/GfxInfo.cpp b/widget/gtk/GfxInfo.cpp
index 7382b066d1..0c1c544b8f 100644
--- a/widget/gtk/GfxInfo.cpp
+++ b/widget/gtk/GfxInfo.cpp
@@ -1102,15 +1102,14 @@ nsresult GfxInfo::GetFeatureStatusImpl(
GetData();
- if (aFeature == nsIGfxInfo::FEATURE_BACKDROP_FILTER) {
- *aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
- return NS_OK;
- }
-
if (mGlxTestError) {
- // If glxtest failed, block all features by default.
- *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
- aFailureId = "FEATURE_FAILURE_GLXTEST_FAILED";
+ // If glxtest failed, block most features by default.
+ if (OnlyAllowFeatureOnKnownConfig(aFeature)) {
+ *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
+ aFailureId = "FEATURE_FAILURE_GLXTEST_FAILED";
+ } else {
+ *aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
+ }
return NS_OK;
}
@@ -1118,8 +1117,12 @@ nsresult GfxInfo::GetFeatureStatusImpl(
// We're on OpenGL 1. In most cases that indicates really old hardware.
// We better block them, rather than rely on them to fail gracefully,
// because they don't! see bug 696636
- *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
- aFailureId = "FEATURE_FAILURE_OPENGL_1";
+ if (OnlyAllowFeatureOnKnownConfig(aFeature)) {
+ *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
+ aFailureId = "FEATURE_FAILURE_OPENGL_1";
+ } else {
+ *aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
+ }
return NS_OK;
}
diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
index 8ed12c734d..149e3716e1 100644
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -3352,7 +3352,10 @@ void nsWindow::SetCursor(const Cursor& aCursor) {
// Try to set the cursor image first, and fall back to the numeric cursor.
bool fromImage = true;
- GdkCursor* newCursor = GetCursorForImage(aCursor, GdkCeiledScaleFactor());
+ GdkCursor* newCursor = nullptr;
+ if (mCustomCursorAllowed) {
+ newCursor = GetCursorForImage(aCursor, GdkCeiledScaleFactor());
+ }
if (!newCursor) {
fromImage = false;
newCursor = get_gtk_cursor(aCursor.mDefaultCursor);
diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp
index 7af67a1523..ef102467f6 100644
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -703,6 +703,14 @@ void nsBaseWidget::MoveToWorkspace(const nsAString& workspaceID) {
void nsBaseWidget::SetCursor(const Cursor& aCursor) { mCursor = aCursor; }
+void nsBaseWidget::SetCustomCursorAllowed(bool aIsAllowed) {
+ if (aIsAllowed != mCustomCursorAllowed) {
+ mCustomCursorAllowed = aIsAllowed;
+ mUpdateCursor = true;
+ SetCursor(mCursor);
+ }
+}
+
//-------------------------------------------------------------------------
//
// Window transparency methods
diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h
index 0ac102f71d..72863cf166 100644
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -187,6 +187,7 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
bool IsFullyOccluded() const override { return mIsFullyOccluded; }
void SetCursor(const Cursor&) override;
+ void SetCustomCursorAllowed(bool) override;
void ClearCachedCursor() final {
mCursor = {};
mUpdateCursor = true;
@@ -217,7 +218,8 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
// resources and possibly schedule another paint.
//
// A reference to the session object is held until this function has
- // returned.
+ // returned. Callers should hold a reference to the widget, since this
+ // function could deallocate the widget if it is unparented.
virtual void NotifyCompositorSessionLost(
mozilla::layers::CompositorSession* aSession);
@@ -693,6 +695,7 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
RefPtr<mozilla::SwipeTracker> mSwipeTracker;
mozilla::UniquePtr<mozilla::SwipeEventQueue> mSwipeEventQueue;
Cursor mCursor;
+ bool mCustomCursorAllowed = true;
BorderStyle mBorderStyle;
LayoutDeviceIntRect mBounds;
bool mIsTiled;
diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h
index 3433da8dae..40752e07dd 100644
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -1009,6 +1009,8 @@ class nsIWidget : public nsISupports {
*/
virtual void SetCursor(const Cursor&) = 0;
+ virtual void SetCustomCursorAllowed(bool) = 0;
+
static nsIntSize CustomCursorSize(const Cursor&);
/**
diff --git a/widget/windows/GfxInfo.cpp b/widget/windows/GfxInfo.cpp
index ae66e5feaa..633ed88921 100644
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -1173,25 +1173,6 @@ static OperatingSystem WindowsVersionToOperatingSystem(
}
}
-static bool OnlyAllowFeatureOnWhitelistedVendor(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:
- // 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:
- return false;
- default:
- return true;
- }
-}
-
// Return true if the CPU supports AVX, but the operating system does not.
#if defined(_M_X64)
static inline bool DetectBrokenAVX() {
@@ -1920,12 +1901,16 @@ nsresult GfxInfo::GetFeatureStatusImpl(
if (NS_FAILED(GetAdapterVendorID(adapterVendorID)) ||
NS_FAILED(GetAdapterDeviceID(adapterDeviceID)) ||
NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString))) {
- aFailureId = "FEATURE_FAILURE_GET_ADAPTER";
- *aStatus = FEATURE_BLOCKED_DEVICE;
+ if (OnlyAllowFeatureOnKnownConfig(aFeature)) {
+ aFailureId = "FEATURE_FAILURE_GET_ADAPTER";
+ *aStatus = FEATURE_BLOCKED_DEVICE;
+ } else {
+ *aStatus = FEATURE_STATUS_OK;
+ }
return NS_OK;
}
- if (OnlyAllowFeatureOnWhitelistedVendor(aFeature) &&
+ if (OnlyAllowFeatureOnKnownConfig(aFeature) &&
!adapterVendorID.Equals(
GfxDriverInfo::GetDeviceVendor(DeviceVendor::Intel),
nsCaseInsensitiveStringComparator) &&
@@ -1974,10 +1959,24 @@ nsresult GfxInfo::GetFeatureStatusImpl(
return NS_OK;
}
+ if (adapterDriverVersionString.Length() == 0) {
+ if (OnlyAllowFeatureOnKnownConfig(aFeature)) {
+ aFailureId = "FEATURE_FAILURE_EMPTY_DRIVER_VERSION";
+ *aStatus = FEATURE_BLOCKED_DRIVER_VERSION;
+ } else {
+ *aStatus = FEATURE_STATUS_OK;
+ }
+ return NS_OK;
+ }
+
uint64_t driverVersion;
if (!ParseDriverVersion(adapterDriverVersionString, &driverVersion)) {
- aFailureId = "FEATURE_FAILURE_PARSE_DRIVER";
- *aStatus = FEATURE_BLOCKED_DRIVER_VERSION;
+ if (OnlyAllowFeatureOnKnownConfig(aFeature)) {
+ aFailureId = "FEATURE_FAILURE_PARSE_DRIVER";
+ *aStatus = FEATURE_BLOCKED_DRIVER_VERSION;
+ } else {
+ *aStatus = FEATURE_STATUS_OK;
+ }
return NS_OK;
}
}
diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp
index 7f925a6ef8..e4b733486b 100644
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -3279,7 +3279,10 @@ void nsWindow::SetCursor(const Cursor& aCursor) {
sCurrentHCursorIsCustom = false;
sCurrentCursor = aCursor;
- HCURSOR cursor = CursorForImage(aCursor, GetDefaultScale());
+ HCURSOR cursor = nullptr;
+ if (mCustomCursorAllowed) {
+ cursor = CursorForImage(aCursor, GetDefaultScale());
+ }
bool custom = false;
if (cursor) {
custom = true;