From 2ffbdaa800efa9b3bd001ac48319ac2bd747271c Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 2 Jan 2024 19:19:27 -0800 Subject: [PATCH 1/3] Check attribute types for safety --- accessibility/src/lib.rs | 21 ++++++++++++++++++++- accessibility/src/ui_element.rs | 13 +++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/accessibility/src/lib.rs b/accessibility/src/lib.rs index 47076e8..5ebc150 100644 --- a/accessibility/src/lib.rs +++ b/accessibility/src/lib.rs @@ -4,7 +4,12 @@ pub mod ui_element; mod util; use accessibility_sys::AXError; -use core_foundation::{array::CFArray, base::TCFType, string::CFString}; +use core_foundation::{ + array::CFArray, + base::CFTypeID, + base::{CFCopyTypeIDDescription, TCFType}, + string::CFString, +}; use std::{ cell::{Cell, RefCell}, thread, @@ -16,14 +21,28 @@ pub use action::*; pub use attribute::*; pub use ui_element::*; +#[non_exhaustive] #[derive(Debug, TError)] pub enum Error { #[error("element not found")] NotFound, + #[error( + "expected attribute type {} but got {}", + type_name(*expected), + type_name(*received), + )] + UnexpectedType { + expected: CFTypeID, + received: CFTypeID, + }, #[error("accessibility error {0:?}")] Ax(AXError), } +fn type_name(type_id: CFTypeID) -> CFString { + unsafe { CFString::wrap_under_create_rule(CFCopyTypeIDDescription(type_id)) } +} + pub trait TreeVisitor { fn enter_element(&self, element: &AXUIElement) -> TreeWalkerFlow; fn exit_element(&self, element: &AXUIElement); diff --git a/accessibility/src/ui_element.rs b/accessibility/src/ui_element.rs index f7a7690..3c1350b 100644 --- a/accessibility/src/ui_element.rs +++ b/accessibility/src/ui_element.rs @@ -14,7 +14,7 @@ use cocoa::{ }; use core_foundation::{ array::CFArray, - base::{TCFType, TCFTypeRef}, + base::{CFType, TCFType, TCFTypeRef}, declare_TCFType, impl_CFTypeDescription, impl_TCFType, string::CFString, }; @@ -92,7 +92,7 @@ impl AXUIElement { } pub fn attribute(&self, attribute: &AXAttribute) -> Result { - unsafe { + let res = unsafe { Ok(T::wrap_under_create_rule(T::Ref::from_void_ptr( ax_call(|x| { AXUIElementCopyAttributeValue( @@ -103,7 +103,16 @@ impl AXUIElement { }) .map_err(Error::Ax)?, ))) + }; + if let Ok(val) = &res { + if T::type_id() != CFType::type_id() && !val.instance_of::() { + return Err(Error::UnexpectedType { + expected: T::type_id(), + received: val.type_of(), + }); + } } + res } pub fn set_attribute( From 5e0abd9beb4f1b11675098f08cfcc117a737cdb5 Mon Sep 17 00:00:00 2001 From: Adrian Hupka Date: Wed, 4 May 2022 15:50:32 +0200 Subject: [PATCH 2/3] Added error_strings method --- accessibility-sys/src/error.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/accessibility-sys/src/error.rs b/accessibility-sys/src/error.rs index bb0a2cb..5f7212a 100644 --- a/accessibility-sys/src/error.rs +++ b/accessibility-sys/src/error.rs @@ -17,3 +17,25 @@ pub const kAXErrorAPIDisabled: i32 = -25211; pub const kAXErrorNoValue: i32 = -25212; pub const kAXErrorParameterizedAttributeUnsupported: i32 = -25213; pub const kAXErrorNotEnoughPrecision: i32 = -25214; + +pub fn error_string(error: AXError) -> &'static str { + match error { + kAXErrorSuccess => "kAXErrorSuccess", + kAXErrorFailure => "kAXErrorFailure", + kAXErrorIllegalArgument => "kAXErrorIllegalArgument", + kAXErrorInvalidUIElement => "kAXErrorInvalidUIElement", + kAXErrorInvalidUIElementObserver => "kAXErrorInvalidUIElementObserver", + kAXErrorCannotComplete => "kAXErrorCannotComplete", + kAXErrorAttributeUnsupported => "kAXErrorAttributeUnsupported", + kAXErrorActionUnsupported => "kAXErrorActionUnsupported", + kAXErrorNotificationUnsupported => "kAXErrorNotificationUnsupported", + kAXErrorNotImplemented => "kAXErrorNotImplemented", + kAXErrorNotificationAlreadyRegistered => "kAXErrorNotificationAlreadyRegistered", + kAXErrorNotificationNotRegistered => "kAXErrorNotificationNotRegistered", + kAXErrorAPIDisabled => "kAXErrorAPIDisabled", + kAXErrorNoValue => "kAXErrorNoValue", + kAXErrorParameterizedAttributeUnsupported => "kAXErrorParameterizedAttributeUnsupported", + kAXErrorNotEnoughPrecision => "kAXErrorNotEnoughPrecision", + _ => "unknown error", + } +} From a2ccee35ec8c918b618594f1319e73b3f0bd97b6 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 12 Jan 2024 20:32:32 -0800 Subject: [PATCH 3/3] Use error_string in Error impl --- accessibility/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accessibility/src/lib.rs b/accessibility/src/lib.rs index 5ebc150..5ae865a 100644 --- a/accessibility/src/lib.rs +++ b/accessibility/src/lib.rs @@ -3,7 +3,7 @@ pub mod attribute; pub mod ui_element; mod util; -use accessibility_sys::AXError; +use accessibility_sys::{error_string, AXError}; use core_foundation::{ array::CFArray, base::CFTypeID, @@ -35,7 +35,7 @@ pub enum Error { expected: CFTypeID, received: CFTypeID, }, - #[error("accessibility error {0:?}")] + #[error("accessibility error {}", error_string(*.0))] Ax(AXError), }