1 // Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights 2 // reserved. Use of this source code is governed by a BSD-style license that can 3 // be found in the LICENSE file. 4 5 #include "libcef/browser/browser_message_loop.h" 6 #include "libcef/common/app_manager.h" 7 8 #include "base/memory/ptr_util.h" 9 #include "base/message_loop/message_pump.h" 10 #include "base/message_loop/message_pump_for_ui.h" 11 12 #if BUILDFLAG(IS_MAC) 13 #include "base/mac/scoped_nsautorelease_pool.h" 14 #include "base/message_loop/message_pump_mac.h" 15 #endif 16 17 #include "content/public/browser/browser_thread.h" 18 19 namespace { 20 21 // MessagePump implementation that delegates to OnScheduleMessagePumpWork() for 22 // scheduling. 23 class MessagePumpExternal : public base::MessagePumpForUI { 24 public: MessagePumpExternal(float max_time_slice,CefRefPtr<CefBrowserProcessHandler> handler)25 MessagePumpExternal(float max_time_slice, 26 CefRefPtr<CefBrowserProcessHandler> handler) 27 : max_time_slice_(max_time_slice), handler_(handler) {} 28 Run(Delegate * delegate)29 void Run(Delegate* delegate) override { 30 base::TimeTicks start = base::TimeTicks::Now(); 31 while (true) { 32 #if BUILDFLAG(IS_MAC) 33 base::mac::ScopedNSAutoreleasePool autorelease_pool; 34 #endif 35 36 base::TimeTicks next_run_time; // is_null() 37 const bool has_more_work = DirectRunWork(delegate, &next_run_time); 38 if (!has_more_work) 39 break; 40 41 if (next_run_time.is_null()) { 42 // We have more work that should run immediately. 43 next_run_time = base::TimeTicks::Now(); 44 } 45 46 const base::TimeDelta& delta = next_run_time - start; 47 if (delta.InSecondsF() > max_time_slice_) 48 break; 49 } 50 } 51 Quit()52 void Quit() override {} 53 ScheduleWork()54 void ScheduleWork() override { handler_->OnScheduleMessagePumpWork(0); } 55 ScheduleDelayedWork(const base::TimeTicks & delayed_work_time)56 void ScheduleDelayedWork(const base::TimeTicks& delayed_work_time) override { 57 const base::TimeDelta& delta = delayed_work_time - base::TimeTicks::Now(); 58 handler_->OnScheduleMessagePumpWork(delta.InMilliseconds()); 59 } 60 61 private: DirectRunWork(Delegate * delegate,base::TimeTicks * next_run_time)62 static bool DirectRunWork(Delegate* delegate, 63 base::TimeTicks* next_run_time) { 64 bool more_immediate_work = false; 65 bool more_idle_work = false; 66 bool more_delayed_work = false; 67 68 Delegate::NextWorkInfo next_work_info = delegate->DoWork(); 69 70 // is_immediate() returns true if the next task is ready right away. 71 more_immediate_work = next_work_info.is_immediate(); 72 if (!more_immediate_work) { 73 // Check the next PendingTask's |delayed_run_time|. 74 // is_max() returns true if there are no more immediate nor delayed tasks. 75 more_delayed_work = !next_work_info.delayed_run_time.is_max(); 76 if (more_delayed_work) { 77 // The only remaining work that we know about is the PendingTask. 78 // Consider the run time for that task in the time slice calculation. 79 *next_run_time = next_work_info.delayed_run_time; 80 } 81 } 82 83 if (!more_immediate_work && !more_delayed_work) { 84 // DoIdleWork() returns true if idle work was all done. 85 more_idle_work = !delegate->DoIdleWork(); 86 } 87 88 return more_immediate_work || more_idle_work || more_delayed_work; 89 } 90 91 const float max_time_slice_; 92 CefRefPtr<CefBrowserProcessHandler> handler_; 93 }; 94 GetBrowserProcessHandler()95CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() { 96 CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication(); 97 if (app) 98 return app->GetBrowserProcessHandler(); 99 return nullptr; 100 } 101 MessagePumpFactoryForUI()102std::unique_ptr<base::MessagePump> MessagePumpFactoryForUI() { 103 if (!content::BrowserThread::IsThreadInitialized( 104 content::BrowserThread::UI) || 105 content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { 106 CefRefPtr<CefBrowserProcessHandler> handler = GetBrowserProcessHandler(); 107 if (handler) 108 return std::make_unique<MessagePumpExternal>(0.01f, handler); 109 } 110 111 #if BUILDFLAG(IS_MAC) 112 return base::MessagePumpMac::Create(); 113 #else 114 return std::make_unique<base::MessagePumpForUI>(); 115 #endif 116 } 117 118 } // namespace 119 InitExternalMessagePumpFactoryForUI()120void InitExternalMessagePumpFactoryForUI() { 121 base::MessagePump::OverrideMessagePumpForUIFactory(MessagePumpFactoryForUI); 122 } 123