diff options
author | sheckylin@chromium.org <sheckylin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-09 17:18:53 +0000 |
---|---|---|
committer | sheckylin@chromium.org <sheckylin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-09 17:18:53 +0000 |
commit | 02c4ff842393637f504ef84723341c159463fe02 (patch) | |
tree | 096be2c528b4e84eaf345285514a87f0f8b259f5 /ui/base | |
parent | db84656d0469020a9f7079a5436d95f83ab8fa9b (diff) | |
download | chromium_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.cc | 56 | ||||
-rw-r--r-- | ui/base/x/device_data_manager.h | 15 |
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_; |