diff options
Diffstat (limited to 'widget')
-rw-r--r-- | widget/GfxInfoBase.cpp | 29 | ||||
-rw-r--r-- | widget/GfxInfoBase.h | 2 | ||||
-rw-r--r-- | widget/LSBUtils.cpp | 73 | ||||
-rw-r--r-- | widget/android/GfxInfo.cpp | 7 | ||||
-rw-r--r-- | widget/cocoa/nsChildView.mm | 8 | ||||
-rw-r--r-- | widget/cocoa/nsCursorManager.h | 3 | ||||
-rw-r--r-- | widget/cocoa/nsCursorManager.mm | 9 | ||||
-rw-r--r-- | widget/gtk/GfxInfo.cpp | 23 | ||||
-rw-r--r-- | widget/gtk/nsWindow.cpp | 5 | ||||
-rw-r--r-- | widget/nsBaseWidget.cpp | 8 | ||||
-rw-r--r-- | widget/nsBaseWidget.h | 5 | ||||
-rw-r--r-- | widget/nsIWidget.h | 2 | ||||
-rw-r--r-- | widget/windows/GfxInfo.cpp | 47 | ||||
-rw-r--r-- | widget/windows/nsWindow.cpp | 5 |
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; |