84158 changed files with 7491483 additions and 3833289 deletions
@ -0,0 +1,31 @@
|
||||
# .lldbinit file for debugging Mozilla |
||||
|
||||
# ----------------------------------------------------------------------------- |
||||
# For documentation on all of the commands and type summaries defined here |
||||
# and in the accompanying Python scripts, see python/lldbutils/README.txt. |
||||
# ----------------------------------------------------------------------------- |
||||
|
||||
# Import the module that defines complex Goanna debugging commands. This assumes |
||||
# you are either running lldb from the top level source directory, the objdir, |
||||
# or the dist/bin directory. (.lldbinit files in the objdir and dist/bin set |
||||
# topsrcdir appropriately.) |
||||
script topsrcdir = topsrcdir if locals().has_key("topsrcdir") else "."; sys.path.append(os.path.join(topsrcdir, "python/lldbutils")); import lldbutils; lldbutils.init() |
||||
|
||||
# Mozilla's use of UNIFIED_SOURCES to include multiple source files into a |
||||
# single compiled file breaks lldb breakpoint setting. This works around that. |
||||
# See http://lldb.llvm.org/troubleshooting.html for more info. |
||||
settings set target.inline-breakpoint-strategy always |
||||
|
||||
# Show the dynamic type of an object when using "expr". This, for example, |
||||
# will show a variable declared as "nsIFrame *" that points to an nsBlockFrame |
||||
# object as being of type "nsBlockFrame *" rather than "nsIFrame *". |
||||
settings set target.prefer-dynamic-value run-target |
||||
|
||||
# Show the string value in atoms. |
||||
type summary add nsIAtom --summary-string "${var.mString}" |
||||
|
||||
# Show the value of text nodes. |
||||
type summary add nsTextNode --summary-string "${var.mText}" |
||||
|
||||
# Dump the current JS stack. |
||||
command alias js expr DumpJSStack() |
@ -0,0 +1,27 @@
|
||||
# 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/. |
||||
|
||||
import imp |
||||
import os |
||||
from StringIO import StringIO |
||||
import shlex |
||||
|
||||
path = os.path.join(os.path.dirname(__file__), 'mach') |
||||
|
||||
if not os.path.exists(path): |
||||
path = os.path.join(os.path.dirname(__file__), 'config.status') |
||||
config = imp.load_module('_buildconfig', open(path), path, ('', 'r', imp.PY_SOURCE)) |
||||
path = os.path.join(config.topsrcdir, 'mach') |
||||
mach_module = imp.load_module('_mach', open(path), path, ('', 'r', imp.PY_SOURCE)) |
||||
|
||||
def FlagsForFile(filename): |
||||
mach = mach_module.get_mach() |
||||
out = StringIO() |
||||
out.encoding = None |
||||
mach.run(['compileflags', filename], stdout=out, stderr=out) |
||||
|
||||
return { |
||||
'flags': shlex.split(out.getvalue()), |
||||
'do_cache': True |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,106 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
||||
/* vim: set ts=2 et sw=2 tw=80: */ |
||||
/* 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/. */
|
||||
|
||||
#ifndef __NS_ACCESSIBLE_WRAP_H__ |
||||
#define __NS_ACCESSIBLE_WRAP_H__ |
||||
|
||||
#include "nsCOMPtr.h" |
||||
#include "Accessible.h" |
||||
|
||||
struct _AtkObject; |
||||
typedef struct _AtkObject AtkObject; |
||||
|
||||
enum AtkProperty { |
||||
PROP_0, // gobject convention
|
||||
PROP_NAME, |
||||
PROP_DESCRIPTION, |
||||
PROP_PARENT, // ancestry has changed
|
||||
PROP_ROLE, |
||||
PROP_LAYER, |
||||
PROP_MDI_ZORDER, |
||||
PROP_TABLE_CAPTION, |
||||
PROP_TABLE_COLUMN_DESCRIPTION, |
||||
PROP_TABLE_COLUMN_HEADER, |
||||
PROP_TABLE_ROW_DESCRIPTION, |
||||
PROP_TABLE_ROW_HEADER, |
||||
PROP_TABLE_SUMMARY, |
||||
PROP_LAST // gobject convention
|
||||
}; |
||||
|
||||
struct AtkPropertyChange { |
||||
int32_t type; // property type as listed above
|
||||
void *oldvalue; |
||||
void *newvalue; |
||||
}; |
||||
|
||||
namespace mozilla { |
||||
namespace a11y { |
||||
|
||||
class MaiHyperlink; |
||||
|
||||
/**
|
||||
* AccessibleWrap, and its descendents in atk directory provide the |
||||
* implementation of AtkObject. |
||||
*/ |
||||
class AccessibleWrap : public Accessible |
||||
{ |
||||
public: |
||||
AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc); |
||||
virtual ~AccessibleWrap(); |
||||
void ShutdownAtkObject(); |
||||
|
||||
virtual void Shutdown() override; |
||||
|
||||
// return the atk object for this AccessibleWrap
|
||||
virtual void GetNativeInterface(void** aOutAccessible) override; |
||||
virtual nsresult HandleAccEvent(AccEvent* aEvent) override; |
||||
|
||||
AtkObject * GetAtkObject(void); |
||||
static AtkObject* GetAtkObject(Accessible* aAccessible); |
||||
|
||||
bool IsValidObject(); |
||||
|
||||
// get/set the MaiHyperlink object for this AccessibleWrap
|
||||
MaiHyperlink* GetMaiHyperlink(bool aCreate = true); |
||||
void SetMaiHyperlink(MaiHyperlink* aMaiHyperlink); |
||||
|
||||
static const char * ReturnString(nsAString &aString) { |
||||
static nsCString returnedString; |
||||
returnedString = NS_ConvertUTF16toUTF8(aString); |
||||
return returnedString.get(); |
||||
} |
||||
|
||||
protected: |
||||
|
||||
nsresult FireAtkStateChangeEvent(AccEvent* aEvent, AtkObject *aObject); |
||||
nsresult FireAtkTextChangedEvent(AccEvent* aEvent, AtkObject *aObject); |
||||
nsresult FireAtkShowHideEvent(AccEvent* aEvent, AtkObject *aObject, |
||||
bool aIsAdded); |
||||
|
||||
AtkObject *mAtkObject; |
||||
|
||||
private: |
||||
|
||||
/*
|
||||
* do we have text-remove and text-insert signals if not we need to use |
||||
* text-changed see AccessibleWrap::FireAtkTextChangedEvent() and |
||||
* bug 619002 |
||||
*/ |
||||
enum EAvailableAtkSignals { |
||||
eUnknown, |
||||
eHaveNewAtkTextSignals, |
||||
eNoNewAtkSignals |
||||
}; |
||||
|
||||
static EAvailableAtkSignals gAvailableAtkSignals; |
||||
|
||||
uint16_t CreateMaiInterfaces(); |
||||
}; |
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* __NS_ACCESSIBLE_WRAP_H__ */ |
@ -0,0 +1,168 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
||||
/* vim: set ts=2 et sw=2 tw=80: */ |
||||
/* 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/. */
|
||||
|
||||
#include "ApplicationAccessibleWrap.h" |
||||
|
||||
#include "nsCOMPtr.h" |
||||
#include "nsMai.h" |
||||
#include "nsAutoPtr.h" |
||||
#include "nsAccessibilityService.h" |
||||
|
||||
#include <gtk/gtk.h> |
||||
#include <atk/atk.h> |
||||
|
||||
using namespace mozilla; |
||||
using namespace mozilla::a11y; |
||||
|
||||
|
||||
// ApplicationAccessibleWrap
|
||||
|
||||
ApplicationAccessibleWrap::ApplicationAccessibleWrap(): |
||||
ApplicationAccessible() |
||||
{ |
||||
} |
||||
|
||||
ApplicationAccessibleWrap::~ApplicationAccessibleWrap() |
||||
{ |
||||
AccessibleWrap::ShutdownAtkObject(); |
||||
} |
||||
|
||||
gboolean |
||||
toplevel_event_watcher(GSignalInvocationHint* ihint, |
||||
guint n_param_values, |
||||
const GValue* param_values, |
||||
gpointer data) |
||||
{ |
||||
static GQuark sQuark_goanna_acc_obj = 0; |
||||
|
||||
if (!sQuark_goanna_acc_obj) |
||||
sQuark_goanna_acc_obj = g_quark_from_static_string("GoannaAccObj"); |
||||
|
||||
if (nsAccessibilityService::IsShutdown()) |
||||
return TRUE; |
||||
|
||||
GObject* object = reinterpret_cast<GObject*>(g_value_get_object(param_values)); |
||||
if (!GTK_IS_WINDOW(object)) |
||||
return TRUE; |
||||
|
||||
AtkObject* child = gtk_widget_get_accessible(GTK_WIDGET(object)); |
||||
|
||||
// GTK native dialog
|
||||
if (!IS_MAI_OBJECT(child) && |
||||
(atk_object_get_role(child) == ATK_ROLE_DIALOG)) { |
||||
|
||||
if (data == reinterpret_cast<gpointer>(nsIAccessibleEvent::EVENT_SHOW)) { |
||||
|
||||
// Attach the dialog accessible to app accessible tree
|
||||
Accessible* windowAcc = GetAccService()->AddNativeRootAccessible(child); |
||||
g_object_set_qdata(G_OBJECT(child), sQuark_goanna_acc_obj, |
||||
reinterpret_cast<gpointer>(windowAcc)); |
||||
|
||||
} else { |
||||
|
||||
// Deattach the dialog accessible
|
||||
Accessible* windowAcc = |
||||
reinterpret_cast<Accessible*> |
||||
(g_object_get_qdata(G_OBJECT(child), sQuark_goanna_acc_obj)); |
||||
if (windowAcc) { |
||||
GetAccService()->RemoveNativeRootAccessible(windowAcc); |
||||
g_object_set_qdata(G_OBJECT(child), sQuark_goanna_acc_obj, nullptr); |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
ENameValueFlag |
||||
ApplicationAccessibleWrap::Name(nsString& aName) |
||||
{ |
||||
// ATK doesn't provide a way to obtain an application name (for example,
|
||||
// Firefox or Thunderbird) like IA2 does. Thus let's return an application
|
||||
// name as accessible name that was used to get a branding name (for example,
|
||||
// Minefield aka nightly Firefox or Daily aka nightly Thunderbird).
|
||||
AppName(aName); |
||||
return eNameOK; |
||||
} |
||||
|
||||
void |
||||
ApplicationAccessibleWrap::GetNativeInterface(void** aOutAccessible) |
||||
{ |
||||
*aOutAccessible = nullptr; |
||||
|
||||
if (!mAtkObject) { |
||||
mAtkObject = |
||||
reinterpret_cast<AtkObject*>(g_object_new(MAI_TYPE_ATK_OBJECT, nullptr)); |
||||
if (!mAtkObject) |
||||
return; |
||||
|
||||
atk_object_initialize(mAtkObject, this); |
||||
mAtkObject->role = ATK_ROLE_INVALID; |
||||
mAtkObject->layer = ATK_LAYER_INVALID; |
||||
} |
||||
|
||||
*aOutAccessible = mAtkObject; |
||||
} |
||||
|
||||
struct AtkRootAccessibleAddedEvent { |
||||
AtkObject *app_accessible; |
||||
AtkObject *root_accessible; |
||||
uint32_t index; |
||||
}; |
||||
|
||||
gboolean fireRootAccessibleAddedCB(gpointer data) |
||||
{ |
||||
AtkRootAccessibleAddedEvent* eventData = (AtkRootAccessibleAddedEvent*)data; |
||||
g_signal_emit_by_name(eventData->app_accessible, "children_changed::add", |
||||
eventData->index, eventData->root_accessible, nullptr); |
||||
g_object_unref(eventData->app_accessible); |
||||
g_object_unref(eventData->root_accessible); |
||||
free(data); |
||||
|
||||
return FALSE; |
||||
} |
||||
|
||||
bool |
||||
ApplicationAccessibleWrap::InsertChildAt(uint32_t aIdx, Accessible* aChild) |
||||
{ |
||||
if (!ApplicationAccessible::InsertChildAt(aIdx, aChild)) |
||||
return false; |
||||
|
||||
AtkObject* atkAccessible = AccessibleWrap::GetAtkObject(aChild); |
||||
atk_object_set_parent(atkAccessible, mAtkObject); |
||||
|
||||
uint32_t count = mChildren.Length(); |
||||
|
||||
// Emit children_changed::add in a timeout
|
||||
// to make sure aRootAccWrap is fully initialized.
|
||||
AtkRootAccessibleAddedEvent* eventData = (AtkRootAccessibleAddedEvent*) |
||||
malloc(sizeof(AtkRootAccessibleAddedEvent)); |
||||
if (eventData) { |
||||
eventData->app_accessible = mAtkObject; |
||||
eventData->root_accessible = atkAccessible; |
||||
eventData->index = count -1; |
||||
g_object_ref(mAtkObject); |
||||
g_object_ref(atkAccessible); |
||||
g_timeout_add(0, fireRootAccessibleAddedCB, eventData); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
bool |
||||
ApplicationAccessibleWrap::RemoveChild(Accessible* aChild) |
||||
{ |
||||
int32_t index = aChild->IndexInParent(); |
||||
|
||||
AtkObject* atkAccessible = AccessibleWrap::GetAtkObject(aChild); |
||||
atk_object_set_parent(atkAccessible, nullptr); |
||||
g_signal_emit_by_name(mAtkObject, "children_changed::remove", index, |
||||
atkAccessible, nullptr); |
||||
|
||||
return ApplicationAccessible::RemoveChild(aChild); |
||||
} |
||||
|
@ -0,0 +1,35 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
||||
/* vim: set ts=2 et sw=2 tw=80: */ |
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_a11y_ApplicationAccessibleWrap_h__ |
||||
#define mozilla_a11y_ApplicationAccessibleWrap_h__ |
||||
|
||||
#include "ApplicationAccessible.h" |
||||
|
||||
namespace mozilla { |
||||
namespace a11y { |
||||
|
||||
class ApplicationAccessibleWrap: public ApplicationAccessible |
||||
{ |
||||
public: |
||||
ApplicationAccessibleWrap(); |
||||
virtual ~ApplicationAccessibleWrap(); |
||||
|
||||
// Accessible
|
||||
virtual mozilla::a11y::ENameValueFlag Name(nsString& aName) override; |
||||
virtual bool InsertChildAt(uint32_t aIdx, Accessible* aChild) override; |
||||
virtual bool RemoveChild(Accessible* aChild) override; |
||||
|
||||
/**
|
||||
* Return the atk object for app root accessible. |
||||
*/ |
||||
virtual void GetNativeInterface(void** aOutAccessible) override; |
||||
}; |
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* __NS_APP_ROOT_ACCESSIBLE_H__ */ |
@ -0,0 +1,155 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
||||
/* vim: set ts=2 et sw=2 tw=80: */ |
||||
/* 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/. */
|
||||
|
||||
#include <atk/atk.h> |
||||
#include "AtkSocketAccessible.h" |
||||
|
||||
#include "InterfaceInitFuncs.h" |
||||
#include "nsMai.h" |
||||
#include "mozilla/Likely.h" |
||||
|
||||
using namespace mozilla::a11y; |
||||
|
||||
AtkSocketEmbedType AtkSocketAccessible::g_atk_socket_embed = nullptr; |
||||
GType AtkSocketAccessible::g_atk_socket_type = G_TYPE_INVALID; |
||||
const char* AtkSocketAccessible::sATKSocketEmbedSymbol = "atk_socket_embed"; |
||||
const char* AtkSocketAccessible::sATKSocketGetTypeSymbol = "atk_socket_get_type"; |
||||
|
||||
bool AtkSocketAccessible::gCanEmbed = FALSE; |
||||
|
||||
extern "C" void mai_atk_component_iface_init(AtkComponentIface* aIface); |
||||
extern "C" GType mai_atk_socket_get_type(void); |
||||
|
||||
/* MaiAtkSocket */ |
||||
|
||||
#define MAI_TYPE_ATK_SOCKET (mai_atk_socket_get_type ()) |
||||
#define MAI_ATK_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ |
||||
MAI_TYPE_ATK_SOCKET, MaiAtkSocket)) |
||||
#define MAI_IS_ATK_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ |
||||
MAI_TYPE_ATK_SOCKET)) |
||||
#define MAI_ATK_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\ |
||||
MAI_TYPE_ATK_SOCKET,\
|
||||
MaiAtkSocketClass)) |
||||
#define MAI_IS_ATK_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\ |
||||
MAI_TYPE_ATK_SOCKET)) |
||||
#define MAI_ATK_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\ |
||||
MAI_TYPE_ATK_SOCKET,\
|
||||
MaiAtkSocketClass)) |
||||
|
||||
typedef struct _MaiAtkSocket |
||||
{ |
||||
AtkSocket parent; |
||||
|
||||
AccessibleWrap* accWrap; |
||||
} MaiAtkSocket; |
||||
|
||||
typedef struct _MaiAtkSocketClass |
||||
{ |
||||
AtkSocketClass parent_class; |
||||
} MaiAtkSocketClass; |
||||
|
||||
G_DEFINE_TYPE_EXTENDED(MaiAtkSocket, mai_atk_socket, |
||||
AtkSocketAccessible::g_atk_socket_type, 0, |
||||
G_IMPLEMENT_INTERFACE(ATK_TYPE_COMPONENT, |
||||
mai_atk_component_iface_init)) |
||||
|
||||
void |
||||
mai_atk_socket_class_init(MaiAtkSocketClass* aAcc) |
||||
{ |
||||
} |
||||
|
||||
void |
||||
mai_atk_socket_init(MaiAtkSocket* aAcc) |
||||
{ |
||||
} |
||||
|
||||
static AtkObject* |
||||
mai_atk_socket_new(AccessibleWrap* aAccWrap) |
||||
{ |
||||
NS_ENSURE_TRUE(aAccWrap, nullptr); |
||||
|
||||
MaiAtkSocket* acc = nullptr; |
||||
acc = static_cast<MaiAtkSocket*>(g_object_new(MAI_TYPE_ATK_SOCKET, nullptr)); |
||||
NS_ENSURE_TRUE(acc, nullptr); |
||||
|
||||
acc->accWrap = aAccWrap; |
||||
return ATK_OBJECT(acc); |
||||
} |
||||
|
||||
extern "C" { |
||||
static AtkObject* |
||||
RefAccessibleAtPoint(AtkComponent* aComponent, gint aX, gint aY, |
||||
AtkCoordType aCoordType) |
||||
{ |
||||
NS_ENSURE_TRUE(MAI_IS_ATK_SOCKET(aComponent), nullptr); |
||||
|
||||
return refAccessibleAtPointHelper(MAI_ATK_SOCKET(aComponent)->accWrap, |
||||
aX, aY, aCoordType); |
||||
} |
||||
|
||||
static void |
||||
GetExtents(AtkComponent* aComponent, gint* aX, gint* aY, gint* aWidth, |
||||
gint* aHeight, AtkCoordType aCoordType) |
||||
{ |
||||
*aX = *aY = *aWidth = *aHeight = 0; |
||||
|
||||
if (!MAI_IS_ATK_SOCKET(aComponent)) |
||||
return; |
||||
|
||||
getExtentsHelper(MAI_ATK_SOCKET(aComponent)->accWrap, |
||||
aX, aY, aWidth, aHeight, aCoordType); |
||||
} |
||||
} |
||||
|
||||
void |
||||
mai_atk_component_iface_init(AtkComponentIface* aIface) |
||||
{ |
||||
NS_ASSERTION(aIface, "Invalid Interface"); |
||||
if (MOZ_UNLIKELY(!aIface)) |
||||
return; |
||||
|
||||
aIface->ref_accessible_at_point = RefAccessibleAtPoint; |
||||
aIface->get_extents = GetExtents; |
||||
} |
||||
|
||||
AtkSocketAccessible::AtkSocketAccessible(nsIContent* aContent, |
||||
DocAccessible* aDoc, |
||||
const nsCString& aPlugId) : |
||||
AccessibleWrap(aContent, aDoc) |
||||
{ |
||||
mAtkObject = mai_atk_socket_new(this); |
||||
if (!mAtkObject) |
||||
return; |
||||
|
||||
// Embeds the children of an AtkPlug, specified by plugId, as the children of
|
||||
// this socket.
|
||||
// Using G_TYPE macros instead of ATK_SOCKET macros to avoid undefined
|
||||
// symbols.
|
||||
if (gCanEmbed && G_TYPE_CHECK_INSTANCE_TYPE(mAtkObject, g_atk_socket_type) && |
||||
!aPlugId.IsVoid()) { |
||||
AtkSocket* accSocket = |
||||
G_TYPE_CHECK_INSTANCE_CAST(mAtkObject, g_atk_socket_type, AtkSocket); |
||||
g_atk_socket_embed(accSocket, (gchar*)aPlugId.get()); |
||||
} |
||||
} |
||||
|
||||
void |
||||
AtkSocketAccessible::GetNativeInterface(void** aOutAccessible) |
||||
{ |
||||
*aOutAccessible = mAtkObject; |
||||
} |
||||
|
||||
void |
||||
AtkSocketAccessible::Shutdown() |
||||
{ |
||||
if (mAtkObject) { |
||||
if (MAI_IS_ATK_SOCKET(mAtkObject)) |
||||
MAI_ATK_SOCKET(mAtkObject)->accWrap = nullptr; |
||||
g_object_unref(mAtkObject); |
||||
mAtkObject = nullptr; |
||||
} |
||||
AccessibleWrap::Shutdown(); |
||||
} |
@ -0,0 +1,56 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
||||
/* vim: set ts=2 et sw=2 tw=80: */ |
||||
/* 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/. */
|
||||
|
||||
#ifndef _AtkSocketAccessible_H_ |
||||
#define _AtkSocketAccessible_H_ |
||||
|
||||
#include "AccessibleWrap.h" |
||||
|
||||
// This file gets included by nsAccessibilityService.cpp, which can't include
|
||||
// atk.h (or glib.h), so we can't rely on it being included.
|
||||
#ifdef __ATK_H__ |
||||
extern "C" typedef void (*AtkSocketEmbedType) (AtkSocket*, gchar*); |
||||
#else |
||||
extern "C" typedef void (*AtkSocketEmbedType) (void*, void*); |
||||
#endif |
||||
|
||||
namespace mozilla { |
||||
namespace a11y { |
||||
|
||||
/**
|
||||
* Provides a AccessibleWrap wrapper around AtkSocket for out-of-process |
||||
* accessibles. |
||||
*/ |
||||
class AtkSocketAccessible : public AccessibleWrap |
||||
{ |
||||
public: |
||||
|
||||
// Soft references to AtkSocket
|
||||
static AtkSocketEmbedType g_atk_socket_embed; |
||||
#ifdef __ATK_H__ |
||||
static GType g_atk_socket_type; |
||||
#endif |
||||
static const char* sATKSocketEmbedSymbol; |
||||
static const char* sATKSocketGetTypeSymbol; |
||||
|
||||
/*
|
||||
* True if the current Atk version supports AtkSocket and it was correctly |
||||
* loaded. |
||||
*/ |
||||
static bool gCanEmbed; |
||||
|
||||
AtkSocketAccessible(nsIContent* aContent, DocAccessible* aDoc, |
||||
const nsCString& aPlugId); |
||||
|
||||
virtual void Shutdown() override; |
||||
|
||||
virtual void GetNativeInterface(void** aOutAccessible) override; |
||||
}; |
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif |
@ -0,0 +1,365 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
||||
/* vim: set ts=2 et sw=2 tw=80: */ |
||||
/* 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/. */
|
||||
|
||||
#include "Platform.h" |
||||
|
||||
#include "nsIAccessibleEvent.h" |
||||
#include "nsIGConfService.h" |
||||
#include "nsIServiceManager.h" |
||||
#include "nsMai.h" |
||||
#include "AtkSocketAccessible.h" |
||||
#include "prenv.h" |
||||
#include "prlink.h" |
||||
|
||||
#ifdef MOZ_ENABLE_DBUS |
||||
#include <dbus/dbus.h> |
||||
#endif |
||||
#include <gtk/gtk.h> |
||||
#if (MOZ_WIDGET_GTK == 3) |
||||
#include <atk-bridge.h> |
||||
#endif |
||||
|
||||
using namespace mozilla; |
||||
using namespace mozilla::a11y; |
||||
|
||||
int atkMajorVersion = 1, atkMinorVersion = 12; |
||||
|
||||
extern "C" { |
||||
typedef GType (* AtkGetTypeType) (void); |
||||
typedef void (*GnomeAccessibilityInit) (void); |
||||
typedef void (*GnomeAccessibilityShutdown) (void); |
||||
} |
||||
|
||||
static PRLibrary* sATKLib = nullptr; |
||||
static const char sATKLibName[] = "libatk-1.0.so.0"; |
||||
static const char sATKHyperlinkImplGetTypeSymbol[] = |
||||
"atk_hyperlink_impl_get_type"; |
||||
|
||||
gboolean toplevel_event_watcher(GSignalInvocationHint*, guint, const GValue*, |
||||
gpointer); |
||||
static bool sToplevel_event_hook_added = false; |
||||
static gulong sToplevel_show_hook = 0; |
||||
static gulong sToplevel_hide_hook = 0; |
||||
|
||||
GType g_atk_hyperlink_impl_type = G_TYPE_INVALID; |
||||
|
||||
#if (MOZ_WIDGET_GTK == 2) |
||||
struct GnomeAccessibilityModule |
||||
{ |
||||
const char *libName; |
||||
PRLibrary *lib; |
||||
const char *initName; |
||||
GnomeAccessibilityInit init; |
||||
const char *shutdownName; |
||||
GnomeAccessibilityShutdown shutdown; |
||||
}; |
||||
|
||||
static GnomeAccessibilityModule sAtkBridge = { |
||||
#ifdef AIX |
||||
"libatk-bridge.a(libatk-bridge.so.0)", nullptr, |
||||
#else |
||||
"libatk-bridge.so", nullptr, |
||||
#endif |
||||
"gnome_accessibility_module_init", nullptr, |
||||
"gnome_accessibility_module_shutdown", nullptr |
||||
}; |
||||
|
||||
static GnomeAccessibilityModule sGail = { |
||||
"libgail.so", nullptr, |
||||
"gnome_accessibility_module_init", nullptr, |
||||
"gnome_accessibility_module_shutdown", nullptr |
||||
}; |
||||
|
||||
static nsresult |
||||
LoadGtkModule(GnomeAccessibilityModule& aModule) |
||||
{ |
||||
NS_ENSURE_ARG(aModule.libName); |
||||
|
||||
if (!(aModule.lib = PR_LoadLibrary(aModule.libName))) { |
||||
//try to load the module with "gtk-2.0/modules" appended
|
||||
char *curLibPath = PR_GetLibraryPath(); |
||||
nsAutoCString libPath(curLibPath); |
||||
#if defined(LINUX) && defined(__x86_64__) |
||||
libPath.AppendLiteral(":/usr/lib64:/usr/lib"); |
||||
#else |
||||
libPath.AppendLiteral(":/usr/lib"); |
||||
#endif |
||||
PR_FreeLibraryName(curLibPath); |
||||
|
||||
int16_t loc1 = 0, loc2 = 0; |
||||
int16_t subLen = 0; |
||||
while (loc2 >= 0) { |
||||
loc2 = libPath.FindChar(':', loc1); |
||||
if (loc2 < 0) |
||||
subLen = libPath.Length() - loc1; |
||||
else |
||||
subLen = loc2 - loc1; |
||||
nsAutoCString sub(Substring(libPath, loc1, subLen)); |
||||
sub.AppendLiteral("/gtk-2.0/modules/"); |
||||
sub.Append(aModule.libName); |
||||
aModule.lib = PR_LoadLibrary(sub.get()); |
||||
if (aModule.lib) |
||||
break; |
||||
|
||||
loc1 = loc2+1; |
||||
} |
||||
if (!aModule.lib) |
||||
return NS_ERROR_FAILURE; |
||||
} |
||||
|
||||
//we have loaded the library, try to get the function ptrs
|
||||
if (!(aModule.init = PR_FindFunctionSymbol(aModule.lib, |
||||
aModule.initName)) || |
||||
!(aModule.shutdown = PR_FindFunctionSymbol(aModule.lib, |
||||
aModule.shutdownName))) { |
||||
|
||||
//fail, :(
|
||||
PR_UnloadLibrary(aModule.lib); |
||||
aModule.lib = nullptr; |
||||
return NS_ERROR_FAILURE; |
||||
} |
||||
return NS_OK; |
||||
} |
||||
#endif // (MOZ_WIDGET_GTK == 2)
|
||||
|
||||
void |
||||
a11y::PlatformInit() |
||||
{ |
||||
if (!ShouldA11yBeEnabled()) |
||||
return; |
||||
|
||||
sATKLib = PR_LoadLibrary(sATKLibName); |
||||
if (!sATKLib) |
||||
return; |
||||
|
||||
AtkGetTypeType pfn_atk_hyperlink_impl_get_type = |
||||
(AtkGetTypeType) PR_FindFunctionSymbol(sATKLib, sATKHyperlinkImplGetTypeSymbol); |
||||
if (pfn_atk_hyperlink_impl_get_type) |
||||
g_atk_hyperlink_impl_type = pfn_atk_hyperlink_impl_get_type(); |
||||
|
||||
AtkGetTypeType pfn_atk_socket_get_type = (AtkGetTypeType) |
||||
PR_FindFunctionSymbol(sATKLib, AtkSocketAccessible::sATKSocketGetTypeSymbol); |
||||
if (pfn_atk_socket_get_type) { |
||||
AtkSocketAccessible::g_atk_socket_type = pfn_atk_socket_get_type(); |
||||
AtkSocketAccessible::g_atk_socket_embed = (AtkSocketEmbedType) |
||||
PR_FindFunctionSymbol(sATKLib, AtkSocketAccessible ::sATKSocketEmbedSymbol); |
||||
AtkSocketAccessible::gCanEmbed = |
||||
AtkSocketAccessible::g_atk_socket_type != G_TYPE_INVALID && |
||||
AtkSocketAccessible::g_atk_socket_embed; |
||||
} |
||||
|
||||
const char* (*atkGetVersion)() = |
||||
(const char* (*)()) PR_FindFunctionSymbol(sATKLib, "atk_get_version"); |
||||
if (atkGetVersion) { |
||||
const char* version = atkGetVersion(); |
||||
if (version) { |
||||
char* endPtr = nullptr; |
||||
atkMajorVersion = strtol(version, &endPtr, 10); |
||||
if (*endPtr == '.') |
||||
atkMinorVersion = strtol(endPtr + 1, &endPtr, 10); |
||||
} |
||||
} |
||||
|
||||
#if (MOZ_WIDGET_GTK == 2) |
||||
// Load and initialize gail library.
|
||||
nsresult rv = LoadGtkModule(sGail); |
||||
if (NS_SUCCEEDED(rv)) |
||||
(*sGail.init)(); |
||||
#endif |
||||
|
||||
// Initialize the MAI Utility class, it will overwrite gail_util.
|
||||
g_type_class_unref(g_type_class_ref(mai_util_get_type())); |
||||
|
||||
// Init atk-bridge now
|
||||
PR_SetEnv("NO_AT_BRIDGE=0"); |
||||
#if (MOZ_WIDGET_GTK == 2) |
||||
rv = LoadGtkModule(sAtkBridge); |
||||
if (NS_SUCCEEDED(rv)) { |
||||
(*sAtkBridge.init)(); |
||||
} |
||||
#else |
||||
atk_bridge_adaptor_init(nullptr, nullptr); |
||||
#endif |
||||
|
||||
if (!sToplevel_event_hook_added) { |
||||
sToplevel_event_hook_added = true; |
||||
sToplevel_show_hook = |
||||
g_signal_add_emission_hook(g_signal_lookup("show", GTK_TYPE_WINDOW), |
||||
0, toplevel_event_watcher, |
||||
reinterpret_cast<gpointer>(nsIAccessibleEvent::EVENT_SHOW), |
||||
nullptr); |
||||
sToplevel_hide_hook = |
||||
g_signal_add_emission_hook(g_signal_lookup("hide", GTK_TYPE_WINDOW), 0, |
||||
toplevel_event_watcher, |
||||
reinterpret_cast<gpointer>(nsIAccessibleEvent::EVENT_HIDE), |
||||
nullptr); |
||||
} |
||||
} |
||||
|
||||
void |
||||
a11y::PlatformShutdown() |
||||
{ |
||||
if (sToplevel_event_hook_added) { |
||||
sToplevel_event_hook_added = false; |
||||
g_signal_remove_emission_hook(g_signal_lookup("show", GTK_TYPE_WINDOW), |
||||
sToplevel_show_hook); |
||||
g_signal_remove_emission_hook(g_signal_lookup("hide", GTK_TYPE_WINDOW), |
||||
sToplevel_hide_hook); |
||||
} |
||||
|
||||
#if (MOZ_WIDGET_GTK == 2) |
||||
if (sAtkBridge.lib) { |
||||
// Do not shutdown/unload atk-bridge,
|
||||
// an exit function registered will take care of it
|
||||
// if (sAtkBridge.shutdown)
|
||||
// (*sAtkBridge.shutdown)();
|
||||
// PR_UnloadLibrary(sAtkBridge.lib);
|
||||
sAtkBridge.lib = nullptr; |
||||
sAtkBridge.init = nullptr; |
||||
sAtkBridge.shutdown = nullptr; |
||||
} |
||||
if (sGail.lib) { |
||||
// Do not shutdown gail because
|
||||
// 1) Maybe it's not init-ed by us. e.g. GtkEmbed
|
||||
// 2) We need it to avoid assert in spi_atk_tidy_windows
|
||||
// if (sGail.shutdown)
|
||||
// (*sGail.shutdown)();
|
||||
// PR_UnloadLibrary(sGail.lib);
|
||||
sGail.lib = nullptr; |
||||
sGail.init = nullptr; |
||||
sGail.shutdown = nullptr; |
||||
} |
||||
#endif |
||||
// if (sATKLib) {
|
||||
// PR_UnloadLibrary(sATKLib);
|
||||
// sATKLib = nullptr;
|
||||
// }
|
||||
} |
||||
|
||||
static const char sAccEnv [] = "GNOME_ACCESSIBILITY"; |
||||
#ifdef MOZ_ENABLE_DBUS |
||||
static DBusPendingCall *sPendingCall = nullptr; |
||||
#endif |
||||
|
||||
void |
||||
a11y::PreInit() |
||||
{ |
||||
#ifdef MOZ_ENABLE_DBUS |
||||
static bool sChecked = FALSE; |
||||
if (sChecked) |
||||
return; |
||||
|
||||
sChecked = TRUE; |
||||
|
||||
// dbus is only checked if GNOME_ACCESSIBILITY is unset
|
||||
// also make sure that a session bus address is available to prevent dbus from
|
||||
// starting a new one. Dbus confuses the test harness when it creates a new
|
||||
// process (see bug 693343)
|
||||
if (PR_GetEnv(sAccEnv) || !PR_GetEnv("DBUS_SESSION_BUS_ADDRESS")) |
||||
return; |
||||
|
||||
DBusConnection* bus = dbus_bus_get(DBUS_BUS_SESSION, nullptr); |
||||
if (!bus) |
||||
return; |
||||
|
||||
dbus_connection_set_exit_on_disconnect(bus, FALSE); |
||||
|
||||
static const char* iface = "org.a11y.Status"; |
||||
static const char* member = "IsEnabled"; |
||||
DBusMessage *message; |
||||
message = dbus_message_new_method_call("org.a11y.Bus", "/org/a11y/bus", |
||||
"org.freedesktop.DBus.Properties", |
||||
"Get"); |
||||
if (!message) |
||||
goto dbus_done; |
||||
|
||||
dbus_message_append_args(message, DBUS_TYPE_STRING, &iface, |
||||
DBUS_TYPE_STRING, &member, DBUS_TYPE_INVALID); |
||||
dbus_connection_send_with_reply(bus, message, &sPendingCall, 1000); |
||||
dbus_message_unref(message); |
||||
|
||||
dbus_done: |
||||
dbus_connection_unref(bus); |
||||
#endif |
||||
} |
||||
|
||||
bool |
||||
a11y::ShouldA11yBeEnabled() |
||||
{ |
||||
static bool sChecked = false, sShouldEnable = false; |
||||
if (sChecked) |
||||
return sShouldEnable; |
||||
|
||||
sChecked = true; |
||||
|
||||
EPlatformDisabledState disabledState = PlatformDisabledState(); |
||||
if (disabledState == ePlatformIsDisabled) |
||||
return sShouldEnable = false; |
||||
|
||||
// check if accessibility enabled/disabled by environment variable
|
||||
const char* envValue = PR_GetEnv(sAccEnv); |
||||
if (envValue) |
||||
return sShouldEnable = !!atoi(envValue); |
||||
|
||||
#ifdef MOZ_ENABLE_DBUS |
||||
PreInit(); |
||||
bool dbusSuccess = false; |
||||
DBusMessage *reply = nullptr; |
||||
if (!sPendingCall) |
||||
goto dbus_done; |
||||
|
||||
dbus_pending_call_block(sPendingCall); |
||||
reply = dbus_pending_call_steal_reply(sPendingCall); |
||||
dbus_pending_call_unref(sPendingCall); |
||||
sPendingCall = nullptr; |
||||
if (!reply || |
||||
dbus_message_get_type(reply) != DBUS_MESSAGE_TYPE_METHOD_RETURN || |
||||
strcmp(dbus_message_get_signature (reply), DBUS_TYPE_VARIANT_AS_STRING)) |
||||
goto dbus_done; |
||||
|
||||
DBusMessageIter iter, iter_variant, iter_struct; |
||||
dbus_bool_t dResult; |
||||
dbus_message_iter_init(reply, &iter); |
||||
dbus_message_iter_recurse (&iter, &iter_variant); |
||||
switch (dbus_message_iter_get_arg_type(&iter_variant)) { |
||||
case DBUS_TYPE_STRUCT: |
||||
// at-spi2-core 2.2.0-2.2.1 had a bug where it returned a struct
|
||||
dbus_message_iter_recurse(&iter_variant, &iter_struct); |
||||
if (dbus_message_iter_get_arg_type(&iter_struct) == DBUS_TYPE_BOOLEAN) { |
||||
dbus_message_iter_get_basic(&iter_struct, &dResult); |
||||
sShouldEnable = dResult; |
||||
dbusSuccess = true; |
||||
} |
||||
|
||||
break; |
||||
case DBUS_TYPE_BOOLEAN: |
||||
dbus_message_iter_get_basic(&iter_variant, &dResult); |
||||
sShouldEnable = dResult; |
||||
dbusSuccess = true; |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
dbus_done: |
||||
if (reply) |
||||
dbus_message_unref(reply); |
||||
|
||||
if (dbusSuccess) |
||||
return sShouldEnable; |
||||
#endif |
||||
|
||||
//check gconf-2 setting
|
||||
static const char sGconfAccessibilityKey[] = |
||||
"/desktop/gnome/interface/accessibility"; |
||||
nsresult rv = NS_OK; |
||||
nsCOMPtr<nsIGConfService> gconf = |
||||
do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv); |
||||
if (NS_SUCCEEDED(rv) && gconf) |
||||
gconf->GetBool(NS_LITERAL_CSTRING(sGconfAccessibilityKey), &sShouldEnable); |
||||
|
||||
return sShouldEnable; |
||||
} |
@ -0,0 +1,34 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
||||
/* vim: set ts=2 et sw=2 tw=80: */ |
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_a11y_RootAccessibleWrap_h__ |
||||
#define mozilla_a11y_RootAccessibleWrap_h__ |
||||
|
||||
#include "BaseAccessibles.h" |
||||
#include "RootAccessible.h" |
||||
|
||||
namespace mozilla { |
||||
namespace a11y { |
||||
|
||||
typedef RootAccessible RootAc |