Change the WebCrypto behavior when exporting EC private keys that were imported witho...
[chromium-blink-merge.git] / content / gpu / gpu_child_thread.cc
blob86dac86c50747b8f1731989815c01881fcd8a008
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/gpu/gpu_child_thread.h"
7 #include "base/bind.h"
8 #include "base/lazy_instance.h"
9 #include "base/threading/worker_pool.h"
10 #include "build/build_config.h"
11 #include "content/child/child_process.h"
12 #include "content/child/thread_safe_sender.h"
13 #include "content/common/gpu/gpu_messages.h"
14 #include "content/gpu/gpu_watchdog_thread.h"
15 #include "content/public/common/content_client.h"
16 #include "content/public/common/content_switches.h"
17 #include "gpu/config/gpu_info_collector.h"
18 #include "ipc/ipc_channel_handle.h"
19 #include "ipc/ipc_sync_message_filter.h"
20 #include "ui/gl/gl_implementation.h"
21 #include "ui/gl/gpu_switching_manager.h"
23 #if defined(USE_OZONE)
24 #include "ui/ozone/public/gpu_platform_support.h"
25 #include "ui/ozone/public/ozone_platform.h"
26 #endif
28 namespace content {
29 namespace {
31 static base::LazyInstance<scoped_refptr<ThreadSafeSender> >
32 g_thread_safe_sender = LAZY_INSTANCE_INITIALIZER;
34 bool GpuProcessLogMessageHandler(int severity,
35 const char* file, int line,
36 size_t message_start,
37 const std::string& str) {
38 std::string header = str.substr(0, message_start);
39 std::string message = str.substr(message_start);
41 g_thread_safe_sender.Get()->Send(new GpuHostMsg_OnLogMessage(
42 severity, header, message));
44 return false;
47 } // namespace
49 GpuChildThread::GpuChildThread(GpuWatchdogThread* watchdog_thread,
50 bool dead_on_arrival,
51 const gpu::GPUInfo& gpu_info,
52 const DeferredMessages& deferred_messages)
53 : dead_on_arrival_(dead_on_arrival),
54 gpu_info_(gpu_info),
55 deferred_messages_(deferred_messages),
56 in_browser_process_(false) {
57 watchdog_thread_ = watchdog_thread;
58 #if defined(OS_WIN)
59 target_services_ = NULL;
60 #endif
61 g_thread_safe_sender.Get() = thread_safe_sender();
64 GpuChildThread::GpuChildThread(const std::string& channel_id)
65 : ChildThread(Options(channel_id, false)),
66 dead_on_arrival_(false),
67 in_browser_process_(true) {
68 #if defined(OS_WIN)
69 target_services_ = NULL;
70 #endif
71 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
72 switches::kSingleProcess) ||
73 base::CommandLine::ForCurrentProcess()->HasSwitch(
74 switches::kInProcessGPU));
75 #if !defined(OS_ANDROID)
76 // For single process and in-process GPU mode, we need to load and
77 // initialize the GL implementation and locate the GL entry points here.
78 // On Android, GLSurface::InitializeOneOff() is called from BrowserMainLoop
79 // before getting here. crbug.com/326295
80 if (!gfx::GLSurface::InitializeOneOff())
81 VLOG(1) << "gfx::GLSurface::InitializeOneOff failed";
82 #endif
83 g_thread_safe_sender.Get() = thread_safe_sender();
86 GpuChildThread::~GpuChildThread() {
89 void GpuChildThread::Shutdown() {
90 ChildThread::Shutdown();
91 logging::SetLogMessageHandler(NULL);
94 void GpuChildThread::Init(const base::Time& process_start_time) {
95 process_start_time_ = process_start_time;
98 bool GpuChildThread::Send(IPC::Message* msg) {
99 // The GPU process must never send a synchronous IPC message to the browser
100 // process. This could result in deadlock.
101 DCHECK(!msg->is_sync());
103 return ChildThread::Send(msg);
106 bool GpuChildThread::OnControlMessageReceived(const IPC::Message& msg) {
107 bool handled = true;
108 IPC_BEGIN_MESSAGE_MAP(GpuChildThread, msg)
109 IPC_MESSAGE_HANDLER(GpuMsg_Initialize, OnInitialize)
110 IPC_MESSAGE_HANDLER(GpuMsg_CollectGraphicsInfo, OnCollectGraphicsInfo)
111 IPC_MESSAGE_HANDLER(GpuMsg_GetVideoMemoryUsageStats,
112 OnGetVideoMemoryUsageStats)
113 IPC_MESSAGE_HANDLER(GpuMsg_Clean, OnClean)
114 IPC_MESSAGE_HANDLER(GpuMsg_Crash, OnCrash)
115 IPC_MESSAGE_HANDLER(GpuMsg_Hang, OnHang)
116 IPC_MESSAGE_HANDLER(GpuMsg_DisableWatchdog, OnDisableWatchdog)
117 IPC_MESSAGE_HANDLER(GpuMsg_GpuSwitched, OnGpuSwitched)
118 IPC_MESSAGE_UNHANDLED(handled = false)
119 IPC_END_MESSAGE_MAP()
121 if (handled)
122 return true;
124 #if defined(USE_OZONE)
125 if (ui::OzonePlatform::GetInstance()
126 ->GetGpuPlatformSupport()
127 ->OnMessageReceived(msg))
128 return true;
129 #endif
131 return gpu_channel_manager_.get() &&
132 gpu_channel_manager_->OnMessageReceived(msg);
135 void GpuChildThread::OnInitialize() {
136 // Record initialization only after collecting the GPU info because that can
137 // take a significant amount of time.
138 gpu_info_.initialization_time = base::Time::Now() - process_start_time_;
139 Send(new GpuHostMsg_Initialized(!dead_on_arrival_, gpu_info_));
140 while (!deferred_messages_.empty()) {
141 Send(deferred_messages_.front());
142 deferred_messages_.pop();
145 if (dead_on_arrival_) {
146 LOG(ERROR) << "Exiting GPU process due to errors during initialization";
147 base::MessageLoop::current()->Quit();
148 return;
151 #if defined(OS_ANDROID)
152 base::PlatformThread::SetThreadPriority(
153 base::PlatformThread::CurrentHandle(),
154 base::kThreadPriority_Display);
155 #endif
157 // We don't need to pipe log messages if we are running the GPU thread in
158 // the browser process.
159 if (!in_browser_process_)
160 logging::SetLogMessageHandler(GpuProcessLogMessageHandler);
162 // Defer creation of the render thread. This is to prevent it from handling
163 // IPC messages before the sandbox has been enabled and all other necessary
164 // initialization has succeeded.
165 gpu_channel_manager_.reset(
166 new GpuChannelManager(GetRouter(),
167 watchdog_thread_.get(),
168 ChildProcess::current()->io_message_loop_proxy(),
169 ChildProcess::current()->GetShutDownEvent(),
170 channel()));
172 #if defined(USE_OZONE)
173 ui::GpuPlatformSupport* gpu_platform_support =
174 ui::OzonePlatform::GetInstance()->GetGpuPlatformSupport();
176 gpu_platform_support->OnChannelEstablished(this);
177 IPC::MessageFilter* message_filter = gpu_platform_support->GetMessageFilter();
178 if (message_filter)
179 channel()->AddFilter(message_filter);
180 #endif
183 void GpuChildThread::StopWatchdog() {
184 if (watchdog_thread_.get()) {
185 watchdog_thread_->Stop();
189 void GpuChildThread::OnCollectGraphicsInfo() {
190 #if defined(OS_WIN)
191 // GPU full info collection should only happen on un-sandboxed GPU process
192 // or single process/in-process gpu mode on Windows.
193 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
194 DCHECK(command_line->HasSwitch(switches::kDisableGpuSandbox) ||
195 in_browser_process_);
196 #endif // OS_WIN
198 gpu::CollectInfoResult result =
199 gpu::CollectContextGraphicsInfo(&gpu_info_);
200 switch (result) {
201 case gpu::kCollectInfoFatalFailure:
202 LOG(ERROR) << "gpu::CollectGraphicsInfo failed (fatal).";
203 // TODO(piman): can we signal overall failure?
204 break;
205 case gpu::kCollectInfoNonFatalFailure:
206 DVLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal).";
207 break;
208 case gpu::kCollectInfoNone:
209 NOTREACHED();
210 break;
211 case gpu::kCollectInfoSuccess:
212 break;
214 GetContentClient()->SetGpuInfo(gpu_info_);
216 #if defined(OS_WIN)
217 // This is slow, but it's the only thing the unsandboxed GPU process does,
218 // and GpuDataManager prevents us from sending multiple collecting requests,
219 // so it's OK to be blocking.
220 gpu::GetDxDiagnostics(&gpu_info_.dx_diagnostics);
221 gpu_info_.dx_diagnostics_info_state = gpu::kCollectInfoSuccess;
222 #endif // OS_WIN
224 Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_));
226 #if defined(OS_WIN)
227 if (!in_browser_process_) {
228 // The unsandboxed GPU process fulfilled its duty. Rest in peace.
229 base::MessageLoop::current()->Quit();
231 #endif // OS_WIN
234 void GpuChildThread::OnGetVideoMemoryUsageStats() {
235 GPUVideoMemoryUsageStats video_memory_usage_stats;
236 if (gpu_channel_manager_)
237 gpu_channel_manager_->gpu_memory_manager()->GetVideoMemoryUsageStats(
238 &video_memory_usage_stats);
239 Send(new GpuHostMsg_VideoMemoryUsageStats(video_memory_usage_stats));
242 void GpuChildThread::OnClean() {
243 DVLOG(1) << "GPU: Removing all contexts";
244 if (gpu_channel_manager_)
245 gpu_channel_manager_->LoseAllContexts();
248 void GpuChildThread::OnCrash() {
249 DVLOG(1) << "GPU: Simulating GPU crash";
250 // Good bye, cruel world.
251 volatile int* it_s_the_end_of_the_world_as_we_know_it = NULL;
252 *it_s_the_end_of_the_world_as_we_know_it = 0xdead;
255 void GpuChildThread::OnHang() {
256 DVLOG(1) << "GPU: Simulating GPU hang";
257 for (;;) {
258 // Do not sleep here. The GPU watchdog timer tracks the amount of user
259 // time this thread is using and it doesn't use much while calling Sleep.
263 void GpuChildThread::OnDisableWatchdog() {
264 DVLOG(1) << "GPU: Disabling watchdog thread";
265 if (watchdog_thread_.get()) {
266 // Disarm the watchdog before shutting down the message loop. This prevents
267 // the future posting of tasks to the message loop.
268 if (watchdog_thread_->message_loop())
269 watchdog_thread_->PostAcknowledge();
270 // Prevent rearming.
271 watchdog_thread_->Stop();
275 void GpuChildThread::OnGpuSwitched() {
276 DVLOG(1) << "GPU: GPU has switched";
277 // Notify observers in the GPU process.
278 ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched();
281 } // namespace content