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