1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/gfx/x/connection.h"
6 
7 #include <xcb/xcb.h>
8 #include <xcb/xcbext.h>
9 
10 #include <algorithm>
11 
12 #include "base/auto_reset.h"
13 #include "base/command_line.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/memory/scoped_refptr.h"
16 #include "base/no_destructor.h"
17 #include "base/strings/string16.h"
18 #include "base/threading/thread_local.h"
19 #include "ui/gfx/x/bigreq.h"
20 #include "ui/gfx/x/event.h"
21 #include "ui/gfx/x/keyboard_state.h"
22 #include "ui/gfx/x/randr.h"
23 #include "ui/gfx/x/x11_switches.h"
24 #include "ui/gfx/x/xkb.h"
25 #include "ui/gfx/x/xproto.h"
26 #include "ui/gfx/x/xproto_internal.h"
27 #include "ui/gfx/x/xproto_types.h"
28 
29 namespace x11 {
30 
31 namespace {
32 
33 // On the wire, sequence IDs are 16 bits.  In xcb, they're usually extended to
34 // 32 and sometimes 64 bits.  In Xlib, they're extended to unsigned long, which
35 // may be 32 or 64 bits depending on the platform.  This function is intended to
36 // prevent bugs caused by comparing two differently sized sequences.  Also
37 // handles rollover.  To use, compare the result of this function with 0.  For
38 // example, to compare seq1 <= seq2, use CompareSequenceIds(seq1, seq2) <= 0.
39 template <typename T, typename U>
CompareSequenceIds(T t,U u)40 auto CompareSequenceIds(T t, U u) {
41   static_assert(std::is_unsigned<T>::value, "");
42   static_assert(std::is_unsigned<U>::value, "");
43   // Cast to the smaller of the two types so that comparisons will always work.
44   // If we casted to the larger type, then the smaller type will be zero-padded
45   // and may incorrectly compare less than the other value.
46   using SmallerType =
47       typename std::conditional<sizeof(T) <= sizeof(U), T, U>::type;
48   SmallerType t0 = static_cast<SmallerType>(t);
49   SmallerType u0 = static_cast<SmallerType>(u);
50   using SignedType = typename std::make_signed<SmallerType>::type;
51   return static_cast<SignedType>(t0 - u0);
52 }
53 
GetConnectionTLS()54 base::ThreadLocalOwnedPointer<Connection>& GetConnectionTLS() {
55   static base::NoDestructor<base::ThreadLocalOwnedPointer<Connection>> tls;
56   return *tls;
57 }
58 
DefaultErrorHandler(const x11::Error * error,const char * request_name)59 void DefaultErrorHandler(const x11::Error* error, const char* request_name) {
60   LOG(WARNING) << "X error received.  Request: x11::" << request_name
61                << "Request, Error: " << error->ToString();
62 }
63 
DefaultIOErrorHandler()64 void DefaultIOErrorHandler() {
65   LOG(ERROR) << "X connection error received.";
66 }
67 
68 class UnknownError : public Error {
69  public:
UnknownError(FutureBase::RawError error_bytes)70   explicit UnknownError(FutureBase::RawError error_bytes)
71       : error_bytes_(error_bytes) {}
72 
73   ~UnknownError() override = default;
74 
ToString() const75   std::string ToString() const override {
76     std::stringstream ss;
77     ss << "x11::UnknownError{";
78     // Errors are always a fixed 32 bytes.
79     for (size_t i = 0; i < 32; i++) {
80       char buf[3];
81       sprintf(buf, "%02x", error_bytes_->data()[i]);
82       ss << "0x" << buf;
83       if (i != 31)
84         ss << ", ";
85     }
86     ss << "}";
87     return ss.str();
88   }
89 
90  private:
91   FutureBase::RawError error_bytes_;
92 };
93 
94 }  // namespace
95 
96 // static
Get()97 Connection* Connection::Get() {
98   auto& tls = GetConnectionTLS();
99   if (Connection* connection = tls.Get())
100     return connection;
101   auto connection = std::make_unique<Connection>();
102   auto* p_connection = connection.get();
103   tls.Set(std::move(connection));
104   return p_connection;
105 }
106 
107 // static
Set(std::unique_ptr<x11::Connection> connection)108 void Connection::Set(std::unique_ptr<x11::Connection> connection) {
109   DCHECK_CALLED_ON_VALID_SEQUENCE(connection->sequence_checker_);
110   auto& tls = GetConnectionTLS();
111   DCHECK(!tls.Get());
112   tls.Set(std::move(connection));
113 }
114 
Connection(const std::string & address)115 Connection::Connection(const std::string& address)
116     : XProto(this),
117       display_string_(
118           address.empty()
119               ? base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
120                     switches::kX11Display)
121               : address),
122       error_handler_(base::BindRepeating(DefaultErrorHandler)),
123       io_error_handler_(base::BindOnce(DefaultIOErrorHandler)) {
124   connection_ =
125       xcb_connect(display_string_.empty() ? nullptr : display_string_.c_str(),
126                   &default_screen_id_);
127   DCHECK(connection_);
128   if (Ready()) {
129     auto buf = ReadBuffer(base::MakeRefCounted<UnretainedRefCountedMemory>(
130         xcb_get_setup(XcbConnection())));
131     setup_ = Read<Setup>(&buf);
132     default_screen_ = &setup_.roots[DefaultScreenId()];
133     InitRootDepthAndVisual();
134   } else {
135     // Default-initialize the setup data so we always have something to return.
136     setup_.roots.emplace_back();
137     default_screen_ = &setup_.roots[0];
138     default_screen_->allowed_depths.emplace_back();
139     default_root_depth_ = &default_screen_->allowed_depths[0];
140     default_root_depth_->visuals.emplace_back();
141     default_root_visual_ = &default_root_depth_->visuals[0];
142   }
143 
144   ExtensionManager::Init(this);
145   auto enable_bigreq = bigreq().Enable({});
146   // Xlib enables XKB on display creation, so we do that here to maintain
147   // compatibility.
148   xkb()
149       .UseExtension({x11::Xkb::major_version, x11::Xkb::minor_version})
150       .OnResponse(base::BindOnce([](x11::Xkb::UseExtensionResponse response) {
151         if (!response || !response->supported)
152           DVLOG(1) << "Xkb extension not available.";
153       }));
154   Flush();
155   if (auto response = enable_bigreq.Sync())
156     extended_max_request_length_ = response->maximum_request_length;
157 
158   const Format* formats[256];
159   memset(formats, 0, sizeof(formats));
160   for (const auto& format : setup_.pixmap_formats)
161     formats[format.depth] = &format;
162 
163   for (const auto& depth : default_screen().allowed_depths) {
164     const Format* format = formats[depth.depth];
165     for (const auto& visual : depth.visuals)
166       default_screen_visuals_[visual.visual_id] = VisualInfo{format, &visual};
167   }
168 
169   keyboard_state_ = CreateKeyboardState(this);
170 
171   InitErrorParsers();
172 }
173 
~Connection()174 Connection::~Connection() {
175   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
176 
177   platform_event_source.reset();
178   xcb_disconnect(connection_);
179 }
180 
XcbConnection()181 xcb_connection_t* Connection::XcbConnection() {
182   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
183   if (io_error_handler_ && xcb_connection_has_error(connection_))
184     std::move(io_error_handler_).Run();
185   return connection_;
186 }
187 
GetXlibDisplay(XlibDisplayType type)188 XlibDisplayWrapper Connection::GetXlibDisplay(XlibDisplayType type) {
189   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
190   if (!xlib_display_)
191     xlib_display_ = base::WrapUnique(new XlibDisplay(display_string_));
192   return XlibDisplayWrapper(xlib_display_->display_, type);
193 }
194 
Request(unsigned int sequence,FutureBase::ResponseCallback callback)195 Connection::Request::Request(unsigned int sequence,
196                              FutureBase::ResponseCallback callback)
197     : sequence(sequence), callback(std::move(callback)) {}
198 
Request(Request && other)199 Connection::Request::Request(Request&& other)
200     : sequence(other.sequence),
201       callback(std::move(other.callback)),
202       have_response(other.have_response),
203       reply(std::move(other.reply)),
204       error(std::move(other.error)) {}
205 
206 Connection::Request::~Request() = default;
207 
HasNextResponse()208 bool Connection::HasNextResponse() {
209   if (requests_.empty())
210     return false;
211   auto& request = requests_.front();
212   if (request.have_response)
213     return true;
214 
215   void* reply = nullptr;
216   xcb_generic_error_t* error = nullptr;
217   request.have_response =
218       xcb_poll_for_reply(XcbConnection(), request.sequence, &reply, &error);
219   if (reply)
220     request.reply = base::MakeRefCounted<MallocedRefCountedMemory>(reply);
221   if (error)
222     request.error = base::MakeRefCounted<MallocedRefCountedMemory>(error);
223   return request.have_response;
224 }
225 
HasNextEvent()226 bool Connection::HasNextEvent() {
227   while (!events_.empty()) {
228     if (events_.front().Initialized())
229       return true;
230     events_.pop_front();
231   }
232   return false;
233 }
234 
GetFd()235 int Connection::GetFd() {
236   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
237   return Ready() ? xcb_get_file_descriptor(XcbConnection()) : -1;
238 }
239 
DisplayString() const240 const std::string& Connection::DisplayString() const {
241   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
242   return display_string_;
243 }
244 
GetConnectionHostname() const245 std::string Connection::GetConnectionHostname() const {
246   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
247   char* host = nullptr;
248   int display_id = 0;
249   int screen = 0;
250   if (xcb_parse_display(display_string_.c_str(), &host, &display_id, &screen)) {
251     std::string name = host;
252     free(host);
253     return name;
254   }
255   return std::string();
256 }
257 
DefaultScreenId() const258 int Connection::DefaultScreenId() const {
259   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
260   // This is not part of the setup data as the server has no concept of a
261   // default screen. Instead, it's part of the display name. Eg in
262   // "localhost:0.0", the screen ID is the second "0".
263   return default_screen_id_;
264 }
265 
Ready() const266 bool Connection::Ready() const {
267   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
268   return !xcb_connection_has_error(connection_);
269 }
270 
Flush()271 void Connection::Flush() {
272   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
273   xcb_flush(connection_);
274 }
275 
Sync()276 void Connection::Sync() {
277   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
278   if (syncing_)
279     return;
280   {
281     base::AutoReset<bool> auto_reset(&syncing_, true);
282     GetInputFocus({}).Sync();
283   }
284 }
285 
SynchronizeForTest(bool synchronous)286 void Connection::SynchronizeForTest(bool synchronous) {
287   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
288   synchronous_ = synchronous;
289   if (synchronous_)
290     Sync();
291 }
292 
ReadResponses()293 void Connection::ReadResponses() {
294   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
295   while (auto* event = xcb_poll_for_event(XcbConnection())) {
296     events_.emplace_back(base::MakeRefCounted<MallocedRefCountedMemory>(event),
297                          this, true);
298   }
299 }
300 
WaitForNextEvent()301 Event Connection::WaitForNextEvent() {
302   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
303   if (HasNextEvent()) {
304     Event event = std::move(events_.front());
305     events_.pop_front();
306     return event;
307   }
308   if (auto* xcb_event = xcb_wait_for_event(XcbConnection())) {
309     return Event(base::MakeRefCounted<MallocedRefCountedMemory>(xcb_event),
310                  this, true);
311   }
312   return Event();
313 }
314 
HasPendingResponses()315 bool Connection::HasPendingResponses() {
316   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
317   return HasNextEvent() || HasNextResponse();
318 }
319 
GetVisualInfoFromId(VisualId id) const320 const Connection::VisualInfo* Connection::GetVisualInfoFromId(
321     VisualId id) const {
322   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
323   auto it = default_screen_visuals_.find(id);
324   if (it != default_screen_visuals_.end())
325     return &it->second;
326   return nullptr;
327 }
328 
KeysymToKeycode(uint32_t keysym) const329 KeyCode Connection::KeysymToKeycode(uint32_t keysym) const {
330   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
331   return keyboard_state_->KeysymToKeycode(keysym);
332 }
333 
KeycodeToKeysym(KeyCode keycode,uint32_t modifiers) const334 uint32_t Connection::KeycodeToKeysym(KeyCode keycode,
335                                      uint32_t modifiers) const {
336   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
337   return keyboard_state_->KeycodeToKeysym(keycode, modifiers);
338 }
339 
Clone() const340 std::unique_ptr<Connection> Connection::Clone() const {
341   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
342   return std::make_unique<Connection>(display_string_);
343 }
344 
DetachFromSequence()345 void Connection::DetachFromSequence() {
346   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
347   DETACH_FROM_SEQUENCE(sequence_checker_);
348 }
349 
Dispatch(Delegate * delegate)350 void Connection::Dispatch(Delegate* delegate) {
351   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
352 
353   auto process_next_response = [&] {
354     DCHECK(!requests_.empty());
355     DCHECK(requests_.front().have_response);
356 
357     Request request = std::move(requests_.front());
358     requests_.pop();
359     std::move(request.callback).Run(request.reply, request.error);
360   };
361 
362   auto process_next_event = [&] {
363     DCHECK(HasNextEvent());
364 
365     Event event = std::move(events_.front());
366     events_.pop_front();
367     PreDispatchEvent(event);
368     delegate->DispatchXEvent(&event);
369   };
370 
371   // Handle all pending events.
372   while (delegate->ShouldContinueStream()) {
373     Flush();
374     ReadResponses();
375 
376     if (HasNextResponse() && HasNextEvent()) {
377       if (!events_.front().sequence_valid()) {
378         process_next_event();
379         continue;
380       }
381 
382       auto next_response_sequence = requests_.front().sequence;
383       auto next_event_sequence = events_.front().sequence();
384 
385       // All events have the sequence number of the last processed request
386       // included in them.  So if a reply and an event have the same sequence,
387       // the reply must have been received first.
388       if (CompareSequenceIds(next_event_sequence, next_response_sequence) <= 0)
389         process_next_response();
390       else
391         process_next_event();
392     } else if (HasNextResponse()) {
393       process_next_response();
394     } else if (HasNextEvent()) {
395       process_next_event();
396     } else {
397       break;
398     }
399   }
400 }
401 
SetErrorHandler(ErrorHandler new_handler)402 Connection::ErrorHandler Connection::SetErrorHandler(ErrorHandler new_handler) {
403   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
404 
405   return std::exchange(error_handler_, new_handler);
406 }
407 
SetIOErrorHandler(IOErrorHandler new_handler)408 void Connection::SetIOErrorHandler(IOErrorHandler new_handler) {
409   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
410 
411   io_error_handler_ = std::move(new_handler);
412 }
413 
InitRootDepthAndVisual()414 void Connection::InitRootDepthAndVisual() {
415   for (auto& depth : default_screen_->allowed_depths) {
416     for (auto& visual : depth.visuals) {
417       if (visual.visual_id == default_screen_->root_visual) {
418         default_root_depth_ = &depth;
419         default_root_visual_ = &visual;
420         return;
421       }
422     }
423   }
424   NOTREACHED();
425 }
426 
AddRequest(unsigned int sequence,FutureBase::ResponseCallback callback)427 void Connection::AddRequest(unsigned int sequence,
428                             FutureBase::ResponseCallback callback) {
429   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
430   DCHECK(requests_.empty() ||
431          CompareSequenceIds(requests_.back().sequence, sequence) < 0);
432 
433   requests_.emplace(sequence, std::move(callback));
434 }
435 
PreDispatchEvent(const Event & event)436 void Connection::PreDispatchEvent(const Event& event) {
437   if (auto* mapping = event.As<MappingNotifyEvent>()) {
438     if (mapping->request == Mapping::Modifier ||
439         mapping->request == Mapping::Keyboard) {
440       setup_.min_keycode = mapping->first_keycode;
441       setup_.max_keycode = static_cast<x11::KeyCode>(
442           static_cast<int>(mapping->first_keycode) + mapping->count - 1);
443       keyboard_state_->UpdateMapping();
444     }
445   }
446   if (auto* notify = event.As<x11::Xkb::NewKeyboardNotifyEvent>()) {
447     setup_.min_keycode = notify->minKeyCode;
448     setup_.max_keycode = notify->maxKeyCode;
449     keyboard_state_->UpdateMapping();
450   }
451 
452   // This is adapted from XRRUpdateConfiguration.
453   if (auto* configure = event.As<ConfigureNotifyEvent>()) {
454     int index = ScreenIndexFromRootWindow(configure->window);
455     if (index != -1) {
456       setup_.roots[index].width_in_pixels = configure->width;
457       setup_.roots[index].height_in_pixels = configure->height;
458     }
459   } else if (auto* screen = event.As<RandR::ScreenChangeNotifyEvent>()) {
460     int index = ScreenIndexFromRootWindow(screen->root);
461     DCHECK_GE(index, 0);
462     bool portrait =
463         static_cast<bool>(screen->rotation & (RandR::Rotation::Rotate_90 |
464                                               RandR::Rotation::Rotate_270));
465     if (portrait) {
466       setup_.roots[index].width_in_pixels = screen->height;
467       setup_.roots[index].height_in_pixels = screen->width;
468       setup_.roots[index].width_in_millimeters = screen->mheight;
469       setup_.roots[index].height_in_millimeters = screen->mwidth;
470     } else {
471       setup_.roots[index].width_in_pixels = screen->width;
472       setup_.roots[index].height_in_pixels = screen->height;
473       setup_.roots[index].width_in_millimeters = screen->mwidth;
474       setup_.roots[index].height_in_millimeters = screen->mheight;
475     }
476   }
477 }
478 
ScreenIndexFromRootWindow(Window root) const479 int Connection::ScreenIndexFromRootWindow(Window root) const {
480   for (size_t i = 0; i < setup_.roots.size(); i++) {
481     if (setup_.roots[i].root == root)
482       return i;
483   }
484   return -1;
485 }
486 
ParseError(FutureBase::RawError error_bytes)487 std::unique_ptr<Error> Connection::ParseError(
488     FutureBase::RawError error_bytes) {
489   if (!error_bytes)
490     return nullptr;
491   struct ErrorHeader {
492     uint8_t response_type;
493     uint8_t error_code;
494     uint16_t sequence;
495   };
496   auto error_code = error_bytes->front_as<ErrorHeader>()->error_code;
497   if (auto parser = error_parsers_[error_code])
498     return parser(error_bytes);
499   return std::make_unique<UnknownError>(error_bytes);
500 }
501 
GenerateIdImpl()502 uint32_t Connection::GenerateIdImpl() {
503   return xcb_generate_id(connection_);
504 }
505 
506 }  // namespace x11
507