1 // Copyright 2019 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 #ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_SERVER_OBJECT_H_
6 #define UI_OZONE_PLATFORM_WAYLAND_TEST_SERVER_OBJECT_H_
7 
8 #include <memory>
9 #include <type_traits>
10 #include <utility>
11 
12 #include "base/macros.h"
13 
14 #include <wayland-server-core.h>
15 
16 struct wl_client;
17 struct wl_resource;
18 
19 namespace wl {
20 
21 // Base class for managing the life cycle of server objects.
22 class ServerObject {
23  public:
24   explicit ServerObject(wl_resource* resource);
25   virtual ~ServerObject();
26 
resource()27   wl_resource* resource() const { return resource_; }
28 
29   static void OnResourceDestroyed(wl_resource* resource);
30 
31  private:
32   wl_resource* resource_;
33 
34   DISALLOW_COPY_AND_ASSIGN(ServerObject);
35 };
36 
37 template <class T>
GetUserDataAs(wl_resource * resource)38 T* GetUserDataAs(wl_resource* resource) {
39   return static_cast<T*>(wl_resource_get_user_data(resource));
40 }
41 
42 template <class T>
TakeUserDataAs(wl_resource * resource)43 std::unique_ptr<T> TakeUserDataAs(wl_resource* resource) {
44   std::unique_ptr<T> user_data(GetUserDataAs<T>(resource));
45   if (std::is_base_of<ServerObject, T>::value) {
46     // Make sure ServerObject doesn't try to destroy the resource twice.
47     ServerObject::OnResourceDestroyed(resource);
48   }
49   wl_resource_set_user_data(resource, nullptr);
50   return user_data;
51 }
52 
53 template <class T>
DestroyUserData(wl_resource * resource)54 void DestroyUserData(wl_resource* resource) {
55   TakeUserDataAs<T>(resource);
56 }
57 
58 template <class T>
SetImplementation(wl_resource * resource,const void * implementation,std::unique_ptr<T> user_data)59 void SetImplementation(wl_resource* resource,
60                        const void* implementation,
61                        std::unique_ptr<T> user_data) {
62   wl_resource_set_implementation(resource, implementation, user_data.release(),
63                                  DestroyUserData<T>);
64 }
65 
66 template <typename ImplClass, typename... ImplArgs>
CreateResourceWithImpl(wl_client * client,const struct wl_interface * interface,int version,const void * implementation,uint32_t id,ImplArgs &&...impl_args)67 wl_resource* CreateResourceWithImpl(wl_client* client,
68                                     const struct wl_interface* interface,
69                                     int version,
70                                     const void* implementation,
71                                     uint32_t id,
72                                     ImplArgs&&... impl_args) {
73   wl_resource* resource = wl_resource_create(client, interface, version, id);
74   if (!resource) {
75     wl_client_post_no_memory(client);
76     return nullptr;
77   }
78   SetImplementation(resource, implementation,
79                     std::make_unique<ImplClass>(
80                         resource, std::forward<ImplArgs&&>(impl_args)...));
81   return resource;
82 }
83 
84 // Does not transfer ownership of the user_data.  Use with caution.  The only
85 // legitimate purpose is setting more than one implementation to the same user
86 // data.
87 template <class T>
SetImplementationUnretained(wl_resource * resource,const void * implementation,T * user_data)88 void SetImplementationUnretained(wl_resource* resource,
89                                  const void* implementation,
90                                  T* user_data) {
91   static_assert(std::is_base_of<ServerObject, T>::value,
92                 "Only types derived from ServerObject are supported!");
93   wl_resource_set_implementation(resource, implementation, user_data,
94                                  &ServerObject::OnResourceDestroyed);
95 }
96 
97 bool ResourceHasImplementation(wl_resource* resource,
98                                const wl_interface* interface,
99                                const void* impl);
100 
101 void DestroyResource(wl_client* client, wl_resource* resource);
102 
103 }  // namespace wl
104 
105 #endif  // UI_OZONE_PLATFORM_WAYLAND_TEST_SERVER_OBJECT_H_
106