• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2009 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4 
5 #ifndef CEF_LIBCEF_DLL_CPPTOC_CPPTOC_REF_COUNTED_H_
6 #define CEF_LIBCEF_DLL_CPPTOC_CPPTOC_REF_COUNTED_H_
7 #pragma once
8 
9 #include "include/base/cef_logging.h"
10 #include "include/base/cef_macros.h"
11 #include "include/capi/cef_base_capi.h"
12 #include "include/cef_base.h"
13 #include "libcef_dll/wrapper_types.h"
14 
15 // Wrap a C++ class with a C structure.  This is used when the class
16 // implementation exists on this side of the DLL boundary but will have methods
17 // called from the other side of the DLL boundary.
18 template <class ClassName, class BaseName, class StructName>
19 class CefCppToCRefCounted : public CefBaseRefCounted {
20  public:
21   // Create a new wrapper instance and associated structure reference for
22   // passing an object instance the other side.
Wrap(CefRefPtr<BaseName> c)23   static StructName* Wrap(CefRefPtr<BaseName> c) {
24     if (!c.get())
25       return nullptr;
26 
27     // Wrap our object with the CefCppToCRefCounted class.
28     ClassName* wrapper = new ClassName();
29     wrapper->wrapper_struct_.object_ = c.get();
30     // Add a reference to our wrapper object that will be released once our
31     // structure arrives on the other side.
32     wrapper->AddRef();
33     // Return the structure pointer that can now be passed to the other side.
34     return wrapper->GetStruct();
35   }
36 
37   // Retrieve the underlying object instance for a structure reference passed
38   // back from the other side.
Unwrap(StructName * s)39   static CefRefPtr<BaseName> Unwrap(StructName* s) {
40     if (!s)
41       return nullptr;
42 
43     // Cast our structure to the wrapper structure type.
44     WrapperStruct* wrapperStruct = GetWrapperStruct(s);
45 
46     // If the type does not match this object then we need to unwrap as the
47     // derived type.
48     if (wrapperStruct->type_ != kWrapperType)
49       return UnwrapDerived(wrapperStruct->type_, s);
50 
51     // Add the underlying object instance to a smart pointer.
52     CefRefPtr<BaseName> objectPtr(wrapperStruct->object_);
53     // Release the reference to our wrapper object that was added before the
54     // structure was passed back to us.
55     wrapperStruct->wrapper_->Release();
56     // Return the underlying object instance.
57     return objectPtr;
58   }
59 
60   // Retrieve the underlying object instance from our own structure reference
61   // when the reference is passed as the required first parameter of a C API
62   // function call. No explicit reference counting is done in this case.
Get(StructName * s)63   static CefRefPtr<BaseName> Get(StructName* s) {
64     DCHECK(s);
65     WrapperStruct* wrapperStruct = GetWrapperStruct(s);
66     // Verify that the wrapper offset was calculated correctly.
67     DCHECK_EQ(kWrapperType, wrapperStruct->type_);
68     return wrapperStruct->object_;
69   }
70 
71   // If returning the structure across the DLL boundary you should call
72   // AddRef() on this CefCppToCRefCounted object. On the other side of the DLL
73   // boundary, call UnderlyingRelease() on the wrapping CefCToCpp object.
GetStruct()74   StructName* GetStruct() { return &wrapper_struct_.struct_; }
75 
76   // CefBaseRefCounted methods increment/decrement reference counts on both this
77   // object and the underlying wrapper class.
AddRef()78   void AddRef() const {
79     UnderlyingAddRef();
80     ref_count_.AddRef();
81   }
Release()82   bool Release() const {
83     UnderlyingRelease();
84     if (ref_count_.Release()) {
85       delete this;
86       return true;
87     }
88     return false;
89   }
HasOneRef()90   bool HasOneRef() const { return UnderlyingHasOneRef(); }
HasAtLeastOneRef()91   bool HasAtLeastOneRef() const { return UnderlyingHasAtLeastOneRef(); }
92 
93  protected:
CefCppToCRefCounted()94   CefCppToCRefCounted() {
95     wrapper_struct_.type_ = kWrapperType;
96     wrapper_struct_.wrapper_ = this;
97     memset(GetStruct(), 0, sizeof(StructName));
98 
99     cef_base_ref_counted_t* base =
100         reinterpret_cast<cef_base_ref_counted_t*>(GetStruct());
101     base->size = sizeof(StructName);
102     base->add_ref = struct_add_ref;
103     base->release = struct_release;
104     base->has_one_ref = struct_has_one_ref;
105     base->has_at_least_one_ref = struct_has_at_least_one_ref;
106   }
107 
~CefCppToCRefCounted()108   virtual ~CefCppToCRefCounted() {}
109 
110  private:
111   // Used to associate this wrapper object, the underlying object instance and
112   // the structure that will be passed to the other side.
113   struct WrapperStruct {
114     CefWrapperType type_;
115     BaseName* object_;
116     CefCppToCRefCounted<ClassName, BaseName, StructName>* wrapper_;
117     StructName struct_;
118   };
119 
GetWrapperStruct(StructName * s)120   static WrapperStruct* GetWrapperStruct(StructName* s) {
121     // Offset using the WrapperStruct size instead of individual member sizes
122     // to avoid problems due to platform/compiler differences in structure
123     // padding.
124     return reinterpret_cast<WrapperStruct*>(
125         reinterpret_cast<char*>(s) -
126         (sizeof(WrapperStruct) - sizeof(StructName)));
127   }
128 
129   // Unwrap as the derived type.
130   static CefRefPtr<BaseName> UnwrapDerived(CefWrapperType type, StructName* s);
131 
132   // Increment/decrement reference counts on only the underlying class.
UnderlyingAddRef()133   void UnderlyingAddRef() const { wrapper_struct_.object_->AddRef(); }
UnderlyingRelease()134   void UnderlyingRelease() const { wrapper_struct_.object_->Release(); }
UnderlyingHasOneRef()135   bool UnderlyingHasOneRef() const {
136     return wrapper_struct_.object_->HasOneRef();
137   }
UnderlyingHasAtLeastOneRef()138   bool UnderlyingHasAtLeastOneRef() const {
139     return wrapper_struct_.object_->HasAtLeastOneRef();
140   }
141 
struct_add_ref(cef_base_ref_counted_t * base)142   static void CEF_CALLBACK struct_add_ref(cef_base_ref_counted_t* base) {
143     DCHECK(base);
144     if (!base)
145       return;
146 
147     WrapperStruct* wrapperStruct =
148         GetWrapperStruct(reinterpret_cast<StructName*>(base));
149     // Verify that the wrapper offset was calculated correctly.
150     DCHECK_EQ(kWrapperType, wrapperStruct->type_);
151 
152     wrapperStruct->wrapper_->AddRef();
153   }
154 
struct_release(cef_base_ref_counted_t * base)155   static int CEF_CALLBACK struct_release(cef_base_ref_counted_t* base) {
156     DCHECK(base);
157     if (!base)
158       return 0;
159 
160     WrapperStruct* wrapperStruct =
161         GetWrapperStruct(reinterpret_cast<StructName*>(base));
162     // Verify that the wrapper offset was calculated correctly.
163     DCHECK_EQ(kWrapperType, wrapperStruct->type_);
164 
165     return wrapperStruct->wrapper_->Release();
166   }
167 
struct_has_one_ref(cef_base_ref_counted_t * base)168   static int CEF_CALLBACK struct_has_one_ref(cef_base_ref_counted_t* base) {
169     DCHECK(base);
170     if (!base)
171       return 0;
172 
173     WrapperStruct* wrapperStruct =
174         GetWrapperStruct(reinterpret_cast<StructName*>(base));
175     // Verify that the wrapper offset was calculated correctly.
176     DCHECK_EQ(kWrapperType, wrapperStruct->type_);
177 
178     return wrapperStruct->wrapper_->HasOneRef();
179   }
180 
181   static int CEF_CALLBACK
struct_has_at_least_one_ref(cef_base_ref_counted_t * base)182   struct_has_at_least_one_ref(cef_base_ref_counted_t* base) {
183     DCHECK(base);
184     if (!base)
185       return 0;
186 
187     WrapperStruct* wrapperStruct =
188         GetWrapperStruct(reinterpret_cast<StructName*>(base));
189     // Verify that the wrapper offset was calculated correctly.
190     DCHECK_EQ(kWrapperType, wrapperStruct->type_);
191 
192     return wrapperStruct->wrapper_->HasAtLeastOneRef();
193   }
194 
195   WrapperStruct wrapper_struct_;
196   CefRefCount ref_count_;
197 
198   static CefWrapperType kWrapperType;
199 
200   DISALLOW_COPY_AND_ASSIGN(CefCppToCRefCounted);
201 };
202 
203 #endif  // CEF_LIBCEF_DLL_CPPTOC_CPPTOC_REF_COUNTED_H_
204