1 // Copyright 2016 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/ozone/platform/wayland/test/test_wayland_server_thread.h"
6 
7 #include <stdlib.h>
8 #include <sys/socket.h>
9 #include <wayland-server.h>
10 #include <memory>
11 
12 #include "base/bind.h"
13 #include "base/files/file_util.h"
14 #include "base/files/scoped_file.h"
15 #include "base/run_loop.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/task_runner_util.h"
18 
19 namespace wl {
20 
operator ()(wl_display * display)21 void DisplayDeleter::operator()(wl_display* display) {
22   wl_display_destroy(display);
23 }
24 
TestWaylandServerThread()25 TestWaylandServerThread::TestWaylandServerThread()
26     : Thread("test_wayland_server"),
27       pause_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
28                    base::WaitableEvent::InitialState::NOT_SIGNALED),
29       resume_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
30                     base::WaitableEvent::InitialState::NOT_SIGNALED),
31       controller_(FROM_HERE) {}
32 
~TestWaylandServerThread()33 TestWaylandServerThread::~TestWaylandServerThread() {
34   if (client_)
35     wl_client_destroy(client_);
36 
37   Resume();
38   Stop();
39 }
40 
Start(uint32_t shell_version)41 bool TestWaylandServerThread::Start(uint32_t shell_version) {
42   display_.reset(wl_display_create());
43   if (!display_)
44     return false;
45   event_loop_ = wl_display_get_event_loop(display_.get());
46 
47   int fd[2];
48   if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fd) < 0)
49     return false;
50   base::ScopedFD server_fd(fd[0]);
51   base::ScopedFD client_fd(fd[1]);
52 
53   // If client has not specified rect before, user standard ones.
54   if (output_.GetRect().IsEmpty())
55     output_.SetRect(gfx::Rect(0, 0, 800, 600));
56 
57   if (wl_display_init_shm(display_.get()) < 0)
58     return false;
59   if (!compositor_.Initialize(display_.get()))
60     return false;
61   if (!sub_compositor_.Initialize(display_.get()))
62     return false;
63   if (!output_.Initialize(display_.get()))
64     return false;
65   if (!data_device_manager_.Initialize(display_.get()))
66     return false;
67   if (!seat_.Initialize(display_.get()))
68     return false;
69   if (shell_version == 6) {
70     if (!zxdg_shell_v6_.Initialize(display_.get()))
71       return false;
72   } else if (shell_version == 7) {
73     if (!xdg_shell_.Initialize(display_.get()))
74       return false;
75   } else {
76     NOTREACHED() << "Unsupported shell version: " << shell_version;
77   }
78   if (!zwp_text_input_manager_v1_.Initialize(display_.get()))
79     return false;
80   if (!zwp_linux_dmabuf_v1_.Initialize(display_.get()))
81     return false;
82 
83   client_ = wl_client_create(display_.get(), server_fd.release());
84   if (!client_)
85     return false;
86 
87   base::Thread::Options options;
88   options.message_pump_factory = base::BindRepeating(
89       &TestWaylandServerThread::CreateMessagePump, base::Unretained(this));
90   if (!base::Thread::StartWithOptions(options))
91     return false;
92 
93   setenv("WAYLAND_SOCKET", base::NumberToString(client_fd.release()).c_str(),
94          1);
95 
96   return true;
97 }
98 
Pause()99 void TestWaylandServerThread::Pause() {
100   task_runner()->PostTask(FROM_HERE,
101                           base::BindOnce(&TestWaylandServerThread::DoPause,
102                                          base::Unretained(this)));
103   pause_event_.Wait();
104 }
105 
Resume()106 void TestWaylandServerThread::Resume() {
107   if (display_)
108     wl_display_flush_clients(display_.get());
109   resume_event_.Signal();
110 }
111 
EnsureWpPresentation()112 MockWpPresentation* TestWaylandServerThread::EnsureWpPresentation() {
113   if (wp_presentation_.Initialize(display_.get()))
114     return &wp_presentation_;
115   return nullptr;
116 }
117 
DoPause()118 void TestWaylandServerThread::DoPause() {
119   base::RunLoop().RunUntilIdle();
120   pause_event_.Signal();
121   resume_event_.Wait();
122 }
123 
124 std::unique_ptr<base::MessagePump>
CreateMessagePump()125 TestWaylandServerThread::CreateMessagePump() {
126   auto pump = std::make_unique<base::MessagePumpLibevent>();
127   pump->WatchFileDescriptor(wl_event_loop_get_fd(event_loop_), true,
128                             base::MessagePumpLibevent::WATCH_READ, &controller_,
129                             this);
130   return std::move(pump);
131 }
132 
OnFileCanReadWithoutBlocking(int fd)133 void TestWaylandServerThread::OnFileCanReadWithoutBlocking(int fd) {
134   wl_event_loop_dispatch(event_loop_, 0);
135   wl_display_flush_clients(display_.get());
136 }
137 
OnFileCanWriteWithoutBlocking(int fd)138 void TestWaylandServerThread::OnFileCanWriteWithoutBlocking(int fd) {}
139 
140 }  // namespace wl
141