1 // Copyright (c) 2014 Marshall A. Greenblatt. All rights reserved. 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google Inc. nor the name Chromium Embedded 14 // Framework nor the names of its contributors may be used to endorse 15 // or promote products derived from this software without specific prior 16 // written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 // 30 // --------------------------------------------------------------------------- 31 // 32 // The contents of this file are only available to applications that link 33 // against the libcef_dll_wrapper target. 34 // 35 36 #ifndef CEF_INCLUDE_WRAPPER_CEF_HELPERS_H_ 37 #define CEF_INCLUDE_WRAPPER_CEF_HELPERS_H_ 38 #pragma once 39 40 #include <cstring> 41 #include <string> 42 #include <vector> 43 44 #include "include/base/cef_bind.h" 45 #include "include/base/cef_logging.h" 46 #include "include/cef_task.h" 47 48 #define CEF_REQUIRE_UI_THREAD() DCHECK(CefCurrentlyOn(TID_UI)); 49 #define CEF_REQUIRE_IO_THREAD() DCHECK(CefCurrentlyOn(TID_IO)); 50 #define CEF_REQUIRE_FILE_BACKGROUND_THREAD() \ 51 DCHECK(CefCurrentlyOn(TID_FILE_BACKGROUND)); 52 #define CEF_REQUIRE_FILE_USER_VISIBLE_THREAD() \ 53 DCHECK(CefCurrentlyOn(TID_FILE_USER_VISIBLE)); 54 #define CEF_REQUIRE_FILE_USER_BLOCKING_THREAD() \ 55 DCHECK(CefCurrentlyOn(TID_FILE_USER_BLOCKING)); 56 #define CEF_REQUIRE_RENDERER_THREAD() DCHECK(CefCurrentlyOn(TID_RENDERER)); 57 58 // Use this struct in conjuction with refcounted types to ensure that an 59 // object is deleted on the specified thread. For example: 60 // 61 // class Foo : public base::RefCountedThreadSafe<Foo, CefDeleteOnUIThread> { 62 // public: 63 // Foo(); 64 // void DoSomething(); 65 // 66 // private: 67 // // Allow deletion via scoped_refptr only. 68 // friend struct CefDeleteOnThread<TID_UI>; 69 // friend class base::RefCountedThreadSafe<Foo, CefDeleteOnUIThread>; 70 // 71 // virtual ~Foo() {} 72 // }; 73 // 74 // base::scoped_refptr<Foo> foo = new Foo(); 75 // foo->DoSomething(); 76 // foo = NULL; // Deletion of |foo| will occur on the UI thread. 77 // 78 template <CefThreadId thread> 79 struct CefDeleteOnThread { 80 template <typename T> DestructCefDeleteOnThread81 static void Destruct(const T* x) { 82 if (CefCurrentlyOn(thread)) { 83 delete x; 84 } else { 85 CefPostTask(thread, 86 base::BindOnce(&CefDeleteOnThread<thread>::Destruct<T>, 87 base::Unretained(x))); 88 } 89 } 90 }; 91 92 struct CefDeleteOnUIThread : public CefDeleteOnThread<TID_UI> {}; 93 struct CefDeleteOnIOThread : public CefDeleteOnThread<TID_IO> {}; 94 struct CefDeleteOnFileBackgroundThread 95 : public CefDeleteOnThread<TID_FILE_BACKGROUND> {}; 96 struct CefDeleteOnFileUserVisibleThread 97 : public CefDeleteOnThread<TID_FILE_USER_VISIBLE> {}; 98 struct CefDeleteOnFileUserBlockingThread 99 : public CefDeleteOnThread<TID_FILE_USER_BLOCKING> {}; 100 struct CefDeleteOnRendererThread : public CefDeleteOnThread<TID_RENDERER> {}; 101 102 // Same as IMPLEMENT_REFCOUNTING() but using the specified Destructor. 103 #define IMPLEMENT_REFCOUNTING_EX(ClassName, Destructor) \ 104 public: \ 105 void AddRef() const override { ref_count_.AddRef(); } \ 106 bool Release() const override { \ 107 if (ref_count_.Release()) { \ 108 Destructor::Destruct(this); \ 109 return true; \ 110 } \ 111 return false; \ 112 } \ 113 bool HasOneRef() const override { return ref_count_.HasOneRef(); } \ 114 bool HasAtLeastOneRef() const override { \ 115 return ref_count_.HasAtLeastOneRef(); \ 116 } \ 117 \ 118 private: \ 119 CefRefCount ref_count_ 120 121 #define IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(ClassName) \ 122 IMPLEMENT_REFCOUNTING_EX(ClassName, CefDeleteOnUIThread) 123 124 #define IMPLEMENT_REFCOUNTING_DELETE_ON_IOT(ClassName) \ 125 IMPLEMENT_REFCOUNTING_EX(ClassName, CefDeleteOnIOThread) 126 127 /// 128 // Helper class to manage a scoped copy of |argv|. 129 /// 130 class CefScopedArgArray { 131 public: CefScopedArgArray(int argc,char * argv[])132 CefScopedArgArray(int argc, char* argv[]) { 133 // argv should have (argc + 1) elements, the last one always being NULL. 134 array_ = new char*[argc + 1]; 135 values_.resize(argc); 136 for (int i = 0; i < argc; ++i) { 137 values_[i] = argv[i]; 138 array_[i] = const_cast<char*>(values_[i].c_str()); 139 } 140 array_[argc] = NULL; 141 } 142 143 CefScopedArgArray(const CefScopedArgArray&) = delete; 144 CefScopedArgArray& operator=(const CefScopedArgArray&) = delete; 145 ~CefScopedArgArray()146 ~CefScopedArgArray() { delete[] array_; } 147 array()148 char** array() const { return array_; } 149 150 private: 151 char** array_; 152 153 // Keep values in a vector separate from |array_| because various users may 154 // modify |array_| and we still want to clean up memory properly. 155 std::vector<std::string> values_; 156 }; 157 158 #endif // CEF_INCLUDE_WRAPPER_CEF_HELPERS_H_ 159