• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()95 CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() {
96   CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
97   if (app)
98     return app->GetBrowserProcessHandler();
99   return nullptr;
100 }
101 
MessagePumpFactoryForUI()102 std::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()120 void InitExternalMessagePumpFactoryForUI() {
121   base::MessagePump::OverrideMessagePumpForUIFactory(MessagePumpFactoryForUI);
122 }
123