• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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/common/thread_impl.h"
6 
7 #include "libcef/common/task_runner_impl.h"
8 
9 #include "base/bind.h"
10 #include "base/threading/thread_restrictions.h"
11 
12 namespace {
13 
StopAndDestroy(base::Thread * thread)14 void StopAndDestroy(base::Thread* thread) {
15   // Calling PlatformThread::Join() on the UI thread is otherwise disallowed.
16   base::ScopedAllowBaseSyncPrimitivesForTesting scoped_allow_sync_primitives;
17 
18   // Deleting |thread| will implicitly stop and join it.
19   delete thread;
20 }
21 
22 }  // namespace
23 
24 // static
CreateThread(const CefString & display_name,cef_thread_priority_t priority,cef_message_loop_type_t message_loop_type,bool stoppable,cef_com_init_mode_t com_init_mode)25 CefRefPtr<CefThread> CefThread::CreateThread(
26     const CefString& display_name,
27     cef_thread_priority_t priority,
28     cef_message_loop_type_t message_loop_type,
29     bool stoppable,
30     cef_com_init_mode_t com_init_mode) {
31   if (!CefTaskRunnerImpl::GetCurrentTaskRunner()) {
32     NOTREACHED() << "called on invalid thread";
33     return nullptr;
34   }
35 
36   CefRefPtr<CefThreadImpl> thread_impl = new CefThreadImpl();
37   if (!thread_impl->Create(display_name, priority, message_loop_type, stoppable,
38                            com_init_mode)) {
39     return nullptr;
40   }
41   return thread_impl;
42 }
43 
CefThreadImpl()44 CefThreadImpl::CefThreadImpl() : thread_id_(kInvalidPlatformThreadId) {}
45 
~CefThreadImpl()46 CefThreadImpl::~CefThreadImpl() {
47   if (thread_.get()) {
48     if (!owner_task_runner_->RunsTasksInCurrentSequence()) {
49       // Delete |thread_| on the correct thread.
50       owner_task_runner_->PostTask(
51           FROM_HERE,
52           base::BindOnce(StopAndDestroy, base::Unretained(thread_.release())));
53     } else {
54       StopAndDestroy(thread_.release());
55     }
56   }
57 }
58 
Create(const CefString & display_name,cef_thread_priority_t priority,cef_message_loop_type_t message_loop_type,bool stoppable,cef_com_init_mode_t com_init_mode)59 bool CefThreadImpl::Create(const CefString& display_name,
60                            cef_thread_priority_t priority,
61                            cef_message_loop_type_t message_loop_type,
62                            bool stoppable,
63                            cef_com_init_mode_t com_init_mode) {
64   owner_task_runner_ = CefTaskRunnerImpl::GetCurrentTaskRunner();
65   DCHECK(owner_task_runner_);
66   if (!owner_task_runner_)
67     return false;
68 
69   thread_.reset(new base::Thread(display_name));
70 
71   base::Thread::Options options;
72 
73   switch (priority) {
74     case TP_BACKGROUND:
75       options.priority = base::ThreadPriority::BACKGROUND;
76       break;
77     case TP_DISPLAY:
78       options.priority = base::ThreadPriority::DISPLAY;
79       break;
80     case TP_REALTIME_AUDIO:
81       options.priority = base::ThreadPriority::REALTIME_AUDIO;
82       break;
83     default:
84       break;
85   }
86 
87   switch (message_loop_type) {
88     case ML_TYPE_UI:
89       options.message_pump_type = base::MessagePumpType::UI;
90       break;
91     case ML_TYPE_IO:
92       options.message_pump_type = base::MessagePumpType::IO;
93       break;
94     default:
95       break;
96   }
97 
98   options.joinable = stoppable;
99 
100 #if BUILDFLAG(IS_WIN)
101   if (com_init_mode != COM_INIT_MODE_NONE) {
102     if (com_init_mode == COM_INIT_MODE_STA)
103       options.message_pump_type = base::MessagePumpType::UI;
104     thread_->init_com_with_mta(com_init_mode == COM_INIT_MODE_MTA);
105   }
106 #endif
107 
108   if (!thread_->StartWithOptions(std::move(options))) {
109     thread_.reset();
110     return false;
111   }
112 
113   thread_task_runner_ = new CefTaskRunnerImpl(thread_->task_runner());
114   thread_id_ = thread_->GetThreadId();
115   return true;
116 }
117 
GetTaskRunner()118 CefRefPtr<CefTaskRunner> CefThreadImpl::GetTaskRunner() {
119   return thread_task_runner_;
120 }
121 
GetPlatformThreadId()122 cef_platform_thread_id_t CefThreadImpl::GetPlatformThreadId() {
123   return thread_id_;
124 }
125 
Stop()126 void CefThreadImpl::Stop() {
127   if (!owner_task_runner_)
128     return;
129   if (!owner_task_runner_->RunsTasksInCurrentSequence()) {
130     NOTREACHED() << "called on invalid thread";
131     return;
132   }
133 
134   if (thread_)
135     StopAndDestroy(thread_.release());
136 }
137 
IsRunning()138 bool CefThreadImpl::IsRunning() {
139   if (!owner_task_runner_)
140     return false;
141   if (!owner_task_runner_->RunsTasksInCurrentSequence()) {
142     NOTREACHED() << "called on invalid thread";
143     return false;
144   }
145 
146   return thread_ && thread_->IsRunning();
147 }
148