1 // Copyright (c) 2015 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_TESTS_SHARED_BROWSER_MAIN_MESSAGE_LOOP_H_ 6 #define CEF_TESTS_SHARED_BROWSER_MAIN_MESSAGE_LOOP_H_ 7 #pragma once 8 9 #include "include/base/cef_bind.h" 10 #include "include/base/cef_scoped_ptr.h" 11 #include "include/cef_task.h" 12 13 #if defined(OS_WIN) 14 #include <windows.h> 15 #endif 16 17 namespace client { 18 19 // Represents the message loop running on the main application thread in the 20 // browser process. This will be the same as the CEF UI thread on Linux, OS X 21 // and Windows when not using multi-threaded message loop mode. The methods of 22 // this class are thread-safe unless otherwise indicated. 23 class MainMessageLoop { 24 public: 25 // Returns the singleton instance of this object. 26 static MainMessageLoop* Get(); 27 28 // Run the message loop. The thread that this method is called on will be 29 // considered the main thread. This blocks until Quit() is called. 30 virtual int Run() = 0; 31 32 // Quit the message loop. 33 virtual void Quit() = 0; 34 35 // Post a task for execution on the main message loop. 36 virtual void PostTask(CefRefPtr<CefTask> task) = 0; 37 38 // Returns true if this message loop runs tasks on the current thread. 39 virtual bool RunsTasksOnCurrentThread() const = 0; 40 41 #if defined(OS_WIN) 42 // Set the current modeless dialog on Windows for proper delivery of dialog 43 // messages when using multi-threaded message loop mode. This method must be 44 // called from the main thread. See http://support.microsoft.com/kb/71450 for 45 // background. 46 virtual void SetCurrentModelessDialog(HWND hWndDialog) = 0; 47 #endif 48 49 // Post a closure for execution on the main message loop. 50 void PostClosure(const base::Closure& closure); 51 52 protected: 53 // Only allow deletion via scoped_ptr. 54 friend struct base::DefaultDeleter<MainMessageLoop>; 55 56 MainMessageLoop(); 57 virtual ~MainMessageLoop(); 58 59 private: 60 DISALLOW_COPY_AND_ASSIGN(MainMessageLoop); 61 }; 62 63 #define CURRENTLY_ON_MAIN_THREAD() \ 64 client::MainMessageLoop::Get()->RunsTasksOnCurrentThread() 65 66 #define REQUIRE_MAIN_THREAD() DCHECK(CURRENTLY_ON_MAIN_THREAD()) 67 68 #define MAIN_POST_TASK(task) client::MainMessageLoop::Get()->PostTask(task) 69 70 #define MAIN_POST_CLOSURE(closure) \ 71 client::MainMessageLoop::Get()->PostClosure(closure) 72 73 // Use this struct in conjuction with RefCountedThreadSafe to ensure that an 74 // object is deleted on the main thread. For example: 75 // 76 // class Foo : public base::RefCountedThreadSafe<Foo, DeleteOnMainThread> { 77 // public: 78 // Foo(); 79 // void DoSomething(); 80 // 81 // private: 82 // // Allow deletion via scoped_refptr only. 83 // friend struct DeleteOnMainThread; 84 // friend class base::RefCountedThreadSafe<Foo, DeleteOnMainThread>; 85 // 86 // virtual ~Foo() {} 87 // }; 88 // 89 // base::scoped_refptr<Foo> foo = new Foo(); 90 // foo->DoSomething(); 91 // foo = nullptr; // Deletion of |foo| will occur on the main thread. 92 // 93 struct DeleteOnMainThread { 94 template <typename T> 95 static void Destruct(const T* x) { 96 if (CURRENTLY_ON_MAIN_THREAD()) { 97 delete x; 98 } else { 99 client::MainMessageLoop::Get()->PostClosure( 100 base::Bind(&DeleteOnMainThread::Destruct<T>, x)); 101 } 102 } 103 }; 104 105 } // namespace client 106 107 #endif // CEF_TESTS_SHARED_BROWSER_MAIN_MESSAGE_LOOP_H_ 108