summaryrefslogtreecommitdiffstats
path: root/ui/base
diff options
context:
space:
mode:
authorsheckylin@chromium.org <sheckylin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-09 17:18:53 +0000
committersheckylin@chromium.org <sheckylin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-09 17:18:53 +0000
commit02c4ff842393637f504ef84723341c159463fe02 (patch)
tree096be2c528b4e84eaf345285514a87f0f8b259f5 /ui/base
parentdb84656d0469020a9f7079a5436d95f83ab8fa9b (diff)
downloadchromium_src-02c4ff842393637f504ef84723341c159463fe02.zip
chromium_src-02c4ff842393637f504ef84723341c159463fe02.tar.gz
chromium_src-02c4ff842393637f504ef84723341c159463fe02.tar.bz2
Check for XIDeviceEvent in DeviceUMA
The patch fixes the bug where DeviceUMA picks up XI events which are not actually input events (i.e. XIDeviceEvent). This may result in out-of-bound memory access on some platforms. Contributed by sheckylin@chromium.org BUG=256793, 258138 TEST=Tested on device. Change-Id: I036943c13f92f9eb8a3f00f70eaefb8a5c75e012 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=210397 Review URL: https://chromiumcodereview.appspot.com/18496012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@210588 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/base')
-rw-r--r--ui/base/x/device_data_manager.cc56
-rw-r--r--ui/base/x/device_data_manager.h15
2 files changed, 71 insertions, 0 deletions
diff --git a/ui/base/x/device_data_manager.cc b/ui/base/x/device_data_manager.cc
index 7707518..e5163ba 100644
--- a/ui/base/x/device_data_manager.cc
+++ b/ui/base/x/device_data_manager.cc
@@ -22,6 +22,14 @@
#define XIScrollClass 3
#endif
+// Multi-touch support was introduced in XI 2.2. Add XI event types here
+// for backward-compatibility with older versions of XInput.
+#if !defined(XI_TouchBegin)
+#define XI_TouchBegin 18
+#define XI_TouchUpdate 19
+#define XI_TouchEnd 20
+#endif
+
// Copied from xserver-properties.h
#define AXIS_LABEL_PROP_REL_HWHEEL "Rel Horiz Wheel"
#define AXIS_LABEL_PROP_REL_WHEEL "Rel Vert Wheel"
@@ -109,6 +117,8 @@ DeviceDataManager* DeviceDataManager::GetInstance() {
DeviceDataManager::DeviceDataManager()
: natural_scroll_enabled_(false),
atom_cache_(ui::GetXDisplay(), kCachedAtoms) {
+ InitializeXInputInternal();
+
// Make sure the sizes of enum and kCachedAtoms are aligned.
CHECK(arraysize(kCachedAtoms) == static_cast<size_t>(DT_LAST_ENTRY) + 1);
UpdateDeviceList(ui::GetXDisplay());
@@ -117,6 +127,44 @@ DeviceDataManager::DeviceDataManager()
DeviceDataManager::~DeviceDataManager() {
}
+bool DeviceDataManager::InitializeXInputInternal() {
+ // Check if XInput is available on the system.
+ xi_opcode_ = -1;
+ int opcode, event, error;
+ if (!XQueryExtension(
+ ui::GetXDisplay(), "XInputExtension", &opcode, &event, &error)) {
+ VLOG(1) << "X Input extension not available: error=" << error;
+ return false;
+ }
+ xi_opcode_ = opcode;
+
+ // Check the XInput version.
+#if defined(USE_XI2_MT)
+ int major = 2, minor = USE_XI2_MT;
+#else
+ int major = 2, minor = 0;
+#endif
+ if (XIQueryVersion(ui::GetXDisplay(), &major, &minor) == BadRequest) {
+ VLOG(1) << "XInput2 not supported in the server.";
+ return false;
+ }
+
+ // Possible XI event types for XIDeviceEvent. See the XI2 protocol
+ // specification.
+ xi_device_event_types_[XI_KeyPress] = true;
+ xi_device_event_types_[XI_KeyRelease] = true;
+ xi_device_event_types_[XI_ButtonPress] = true;
+ xi_device_event_types_[XI_ButtonRelease] = true;
+ xi_device_event_types_[XI_Motion] = true;
+ // Multi-touch support was introduced in XI 2.2.
+ if (minor >= 2) {
+ xi_device_event_types_[XI_TouchBegin] = true;
+ xi_device_event_types_[XI_TouchUpdate] = true;
+ xi_device_event_types_[XI_TouchEnd] = true;
+ }
+ return true;
+}
+
float DeviceDataManager::GetNaturalScrollFactor(int sourceid) const {
// Natural scroll is touchpad-only.
if (sourceid >= kMaxDeviceNum || !touchpads_[sourceid])
@@ -266,6 +314,14 @@ bool DeviceDataManager::GetEventData(const XEvent& xev,
return false;
}
+bool DeviceDataManager::IsXIDeviceEvent(
+ const base::NativeEvent& native_event) const {
+ if (native_event->type != GenericEvent ||
+ native_event->xcookie.extension != xi_opcode_)
+ return false;
+ return xi_device_event_types_[native_event->xcookie.evtype];
+}
+
bool DeviceDataManager::IsTouchpadXInputEvent(
const base::NativeEvent& native_event) const {
if (native_event->type != GenericEvent)
diff --git a/ui/base/x/device_data_manager.h b/ui/base/x/device_data_manager.h
index 950cca1..b8698d3 100644
--- a/ui/base/x/device_data_manager.h
+++ b/ui/base/x/device_data_manager.h
@@ -136,6 +136,11 @@ class UI_EXPORT DeviceDataManager {
// cached one (see the comment above last_seen_valuator_).
bool GetEventData(const XEvent& xev, const DataType type, double* value);
+ // Check if the event is an XI input event in the strict sense
+ // (i.e. XIDeviceEvent). This rules out things like hierarchy changes,
+ /// device changes, property changes and so on.
+ bool IsXIDeviceEvent(const base::NativeEvent& native_event) const;
+
// Check if the event comes from touchpad devices.
bool IsTouchpadXInputEvent(const base::NativeEvent& native_event) const;
@@ -210,12 +215,22 @@ class UI_EXPORT DeviceDataManager {
DeviceDataManager();
~DeviceDataManager();
+ // Initialize the XInput related system information.
+ bool InitializeXInputInternal();
+
// Check if an XI event contains data of the specified type.
bool HasEventData(const XIDeviceEvent* xiev, const DataType type) const;
static const int kMaxDeviceNum = 128;
+ static const int kMaxXIEventType = XI_LASTEVENT + 1;
bool natural_scroll_enabled_;
+ // Major opcode for the XInput extension. Used to identify XInput events.
+ int xi_opcode_;
+
+ // A quick lookup table for determining if the XI event is an XIDeviceEvent.
+ std::bitset<kMaxXIEventType> xi_device_event_types_;
+
// A quick lookup table for determining if events from the pointer device
// should be processed.
std::bitset<kMaxDeviceNum> cmt_devices_;