diff options
author | k.czech <k.czech@samsung.com> | 2015-05-06 16:21:48 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-06 23:22:20 +0000 |
commit | 16e2d5a386e3ddd5be818a0d27610b1e9ee9c08e (patch) | |
tree | 87f429d168a3122677326d5a8b5a284a0770917d /ui/accessibility | |
parent | f324f5095f912fba25ed1d79faaec98424f4c8fd (diff) | |
download | chromium_src-16e2d5a386e3ddd5be818a0d27610b1e9ee9c08e.zip chromium_src-16e2d5a386e3ddd5be818a0d27610b1e9ee9c08e.tar.gz chromium_src-16e2d5a386e3ddd5be818a0d27610b1e9ee9c08e.tar.bz2 |
Linux Aura accessibility is enabled only on GNOME desktops
Linux Aura accessibility is not enabled on desktops different than GNOME2.
GNOME3 has deprecated gconf in favor of gsettings and dconf.
AT-SPI (cross-platform framework that provides communication between AT
and application) bus launcher has a property called org.a11y.Bus.IsEnabled
that could be easily read by dbus call.
In generall this patch adds an additional check to enable accessibility.
When gconf is available use gnome's accessibility key otherwise
org.a11y.Bus.IsEnabled property.
BUG=472183,468989,468112
TBR=stevenjb@chromium.org,jochen@chromium.org
Review URL: https://codereview.chromium.org/1028553003
Cr-Commit-Position: refs/heads/master@{#328651}
Diffstat (limited to 'ui/accessibility')
-rw-r--r-- | ui/accessibility/DEPS | 1 | ||||
-rw-r--r-- | ui/accessibility/accessibility.gyp | 12 | ||||
-rw-r--r-- | ui/accessibility/platform/atk_util_auralinux.cc | 192 | ||||
-rw-r--r-- | ui/accessibility/platform/atk_util_auralinux.h | 8 |
4 files changed, 169 insertions, 44 deletions
diff --git a/ui/accessibility/DEPS b/ui/accessibility/DEPS index fd3b8f0..2b11d60 100644 --- a/ui/accessibility/DEPS +++ b/ui/accessibility/DEPS @@ -1,4 +1,5 @@ include_rules = [ + "+dbus", "+third_party/iaccessible2", "+ui/base/win", "+ui/gfx", diff --git a/ui/accessibility/accessibility.gyp b/ui/accessibility/accessibility.gyp index e417f10..aef0f10 100644 --- a/ui/accessibility/accessibility.gyp +++ b/ui/accessibility/accessibility.gyp @@ -63,10 +63,20 @@ '../../third_party/iaccessible2/iaccessible2.gyp:iaccessible2' ], }], + ['OS=="linux" and chromeos==0 and use_gconf==1',{ + 'dependencies': [ + '../../build/linux/system.gyp:gconf', + ], + }], + ['OS=="linux" and chromeos==0 and use_dbus==1', { + 'dependencies': [ + '../../build/linux/system.gyp:dbus', + '../../dbus/dbus.gyp:dbus', + ], + }], ['OS=="linux" and chromeos==0 and use_x11==1', { 'dependencies': [ '../../build/linux/system.gyp:atk', - '../../build/linux/system.gyp:gconf', '../../build/linux/system.gyp:glib', ], 'variables': { diff --git a/ui/accessibility/platform/atk_util_auralinux.cc b/ui/accessibility/platform/atk_util_auralinux.cc index 5d25c51..0f770c2 100644 --- a/ui/accessibility/platform/atk_util_auralinux.cc +++ b/ui/accessibility/platform/atk_util_auralinux.cc @@ -5,10 +5,17 @@ #include <atk/atk.h> #if defined(USE_GCONF) #include <gconf/gconf-client.h> +#elif defined(USE_DBUS) +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" #endif #include <glib-2.0/gmodule.h> +#include "base/bind.h" #include "base/files/file_path.h" +#include "base/location.h" #include "base/logging.h" #include "base/memory/singleton.h" #include "ui/accessibility/platform/atk_util_auralinux.h" @@ -16,41 +23,49 @@ namespace { -#if defined(USE_GCONF) +typedef void (*gnome_accessibility_module_init)(); -const char kGnomeAccessibilityEnabledKey[] = - "/desktop/gnome/interface/accessibility"; +const char kAccessibilityEnabled[] = "ACCESSIBILITY_ENABLED"; +const char kAtkBridgePath[] = "gtk-2.0/modules/libatk-bridge.so"; +const char kAtkBridgeSymbolName[] = "gnome_accessibility_module_init"; -bool ShouldEnableAccessibility() { - GConfClient* client = gconf_client_get_default(); - if (!client) { - LOG(ERROR) << "gconf_client_get_default failed"; +gnome_accessibility_module_init g_accessibility_module_init = nullptr; + +bool AccessibilityModuleInitOnFileThread() { + // Try to load libatk-bridge.so. + base::FilePath atk_bridge_path(ATK_LIB_DIR); + atk_bridge_path = atk_bridge_path.Append(kAtkBridgePath); + GModule* bridge = g_module_open(atk_bridge_path.value().c_str(), + static_cast<GModuleFlags>(0)); + if (!bridge) { + VLOG(1) << "Unable to open module " << atk_bridge_path.value(); return false; } - GError* error = nullptr; - gboolean value = gconf_client_get_bool(client, - kGnomeAccessibilityEnabledKey, - &error); - if (error) { - VLOG(1) << "gconf_client_get_bool failed"; - g_error_free(error); - g_object_unref(client); + if (!g_module_symbol(bridge, kAtkBridgeSymbolName, + (gpointer *)&g_accessibility_module_init)) { + VLOG(1) << "Unable to get symbol pointer from " << atk_bridge_path.value(); + // Just to make sure it's null; + g_accessibility_module_init = nullptr; return false; } - g_object_unref(client); - return value; + return true; } -#else // !defined(USE_GCONF) +#if defined(USE_GCONF) -bool ShouldEnableAccessibility() { - // TODO(k.czech): implement this for non-GNOME desktops. - return false; -} +const char kGnomeAccessibilityEnabledKey[] = + "/desktop/gnome/interface/accessibility"; -#endif // defined(USE_GCONF) +#elif defined(USE_DBUS) + +const char kServiceName[] = "org.a11y.Bus"; +const char kObjectPath[] = "/org/a11y/bus"; +const char kInterfaceName[] = "org.a11y.Status"; +const char kPropertyName[] = "IsEnabled"; + +#endif } // namespace @@ -139,44 +154,135 @@ AtkUtilAuraLinux* AtkUtilAuraLinux::GetInstance() { return Singleton<AtkUtilAuraLinux>::get(); } +#if defined(USE_GCONF) || defined(USE_DBUS) + +AtkUtilAuraLinux::AtkUtilAuraLinux() + : is_enabled_(false) { +} + +#else + AtkUtilAuraLinux::AtkUtilAuraLinux() { } +#endif + void AtkUtilAuraLinux::Initialize( scoped_refptr<base::TaskRunner> init_task_runner) { - // TODO(k.czech): use |init_task_runner| to post a task to do the - // initialization rather than doing it on this thread. - // http://crbug.com/468112 // Register our util class. g_type_class_unref(g_type_class_ref(ATK_UTIL_AURALINUX_TYPE)); - if (!ShouldEnableAccessibility()) { - VLOG(1) << "Will not enable ATK accessibility support."; - return; + init_task_runner->PostTaskAndReply( + FROM_HERE, + base::Bind( + &AtkUtilAuraLinux::CheckIfAccessibilityIsEnabledOnFileThread, + base::Unretained(this)), + base::Bind( + &AtkUtilAuraLinux::FinishAccessibilityInitOnUIThread, + base::Unretained(this))); +} + +AtkUtilAuraLinux::~AtkUtilAuraLinux() { +} + +void AtkUtilAuraLinux::CheckIfAccessibilityIsEnabledOnFileThread() { + char* enable_accessibility = getenv(kAccessibilityEnabled); + if ((enable_accessibility && atoi(enable_accessibility) == 1) || + CheckPlatformAccessibilitySupportOnFileThread()) + is_enabled_ = AccessibilityModuleInitOnFileThread(); +} + +#if defined(USE_GCONF) + +bool AtkUtilAuraLinux::CheckPlatformAccessibilitySupportOnFileThread() { + GConfClient* client = gconf_client_get_default(); + if (!client) { + LOG(ERROR) << "gconf_client_get_default failed"; + return false; } - VLOG(1) << "Enabling ATK accessibility support."; + GError* error = nullptr; + bool is_enabled = gconf_client_get_bool(client, + kGnomeAccessibilityEnabledKey, + &error); - // Try to load libatk-bridge.so. - base::FilePath atk_bridge_path(ATK_LIB_DIR); - atk_bridge_path = atk_bridge_path.Append("gtk-2.0/modules/libatk-bridge.so"); - GModule* bridge = g_module_open(atk_bridge_path.value().c_str(), - static_cast<GModuleFlags>(0)); - if (!bridge) { - VLOG(1) << "Unable to open module " << atk_bridge_path.value(); + g_object_unref(client); + + if (error) { + VLOG(1) << "gconf_client_get_bool failed"; + g_error_free(error); + return false; + } + + return is_enabled; +} + +#elif defined(USE_DBUS) + +bool AtkUtilAuraLinux::CheckPlatformAccessibilitySupportOnFileThread() { + dbus::Bus::Options options; + scoped_refptr<dbus::Bus> dbus(new dbus::Bus(options)); + dbus::ObjectProxy* object_proxy = dbus->GetObjectProxy( + kServiceName, dbus::ObjectPath(kObjectPath)); + + DCHECK(object_proxy); + + dbus::MethodCall method_call(DBUS_INTERFACE_PROPERTIES, "Get"); + dbus::MessageWriter message_writer(&method_call); + message_writer.AppendString(kInterfaceName); + message_writer.AppendString(kPropertyName); + + // TODO(k.czech) replace this with asynchronous call + scoped_ptr<dbus::Response> response( + object_proxy->CallMethodAndBlock(&method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); + + if (!response) { + LOG(ERROR) << "AtSpi: failed to get " << kPropertyName; + dbus->ShutdownAndBlock(); + return false; + } + + // TODO(k.czech) handle case for at-spi2-core version 2.2.0/2.2.2 + // org.a11y.Bus.Enabled returns variant struct with a bool instead of bool + bool is_enabled = false; + dbus::MessageReader reader(response.get()); + if (!reader.PopVariantOfBool(&is_enabled)) + LOG(ERROR) << "AtSpi: unexpected response"; + + dbus->ShutdownAndBlock(); + + return is_enabled; +} + +#else + +bool AtkUtilAuraLinux::CheckPlatformAccessibilitySupportOnFileThread() { + return false; +} + +#endif + +#if defined(USE_GCONF) || defined(USE_DBUS) + +void AtkUtilAuraLinux::FinishAccessibilityInitOnUIThread() { + if (!is_enabled_) { + VLOG(1) << "Will not enable ATK accessibility support."; return; } + VLOG(1) << "Enabling ATK accessibility support."; // Try to call gnome_accessibility_module_init from libatk-bridge.so. - void (*gnome_accessibility_module_init)(); - if (g_module_symbol(bridge, "gnome_accessibility_module_init", - (gpointer *)&gnome_accessibility_module_init)) { - (*gnome_accessibility_module_init)(); - } + DCHECK(g_accessibility_module_init); + g_accessibility_module_init(); } -AtkUtilAuraLinux::~AtkUtilAuraLinux() { +#else + +void AtkUtilAuraLinux::FinishAccessibilityInitOnUIThread() { } +#endif + } // namespace ui diff --git a/ui/accessibility/platform/atk_util_auralinux.h b/ui/accessibility/platform/atk_util_auralinux.h index 8ecb166..0895b42 100644 --- a/ui/accessibility/platform/atk_util_auralinux.h +++ b/ui/accessibility/platform/atk_util_auralinux.h @@ -29,6 +29,14 @@ class AtkUtilAuraLinux { private: friend struct DefaultSingletonTraits<AtkUtilAuraLinux>; + + void CheckIfAccessibilityIsEnabledOnFileThread(); + bool CheckPlatformAccessibilitySupportOnFileThread(); + void FinishAccessibilityInitOnUIThread(); + +#if defined(USE_GCONF) || defined(USE_DBUS) + bool is_enabled_; +#endif }; } // namespace ui |