Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/gpu/gpu_process_host.h" | 5 #include "content/browser/gpu/gpu_process_host.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/base_switches.h" | 8 #include "base/base_switches.h" |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/debug/trace_event.h" | 12 #include "base/debug/trace_event.h" |
| 13 #include "base/logging.h" | |
| 13 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
| 14 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 15 #include "base/process_util.h" | 16 #include "base/process_util.h" |
| 16 #include "base/sha1.h" | 17 #include "base/sha1.h" |
| 17 #include "base/threading/thread.h" | 18 #include "base/threading/thread.h" |
| 18 #include "content/browser/browser_child_process_host_impl.h" | 19 #include "content/browser/browser_child_process_host_impl.h" |
| 19 #include "content/browser/gpu/gpu_data_manager_impl.h" | 20 #include "content/browser/gpu/gpu_data_manager_impl.h" |
| 20 #include "content/browser/gpu/gpu_process_host_ui_shim.h" | 21 #include "content/browser/gpu/gpu_process_host_ui_shim.h" |
| 21 #include "content/browser/gpu/gpu_surface_tracker.h" | 22 #include "content/browser/gpu/gpu_surface_tracker.h" |
| 22 #include "content/browser/gpu/shader_disk_cache.h" | 23 #include "content/browser/gpu/shader_disk_cache.h" |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 38 #include "gpu/command_buffer/service/gpu_switches.h" | 39 #include "gpu/command_buffer/service/gpu_switches.h" |
| 39 #include "ipc/ipc_channel_handle.h" | 40 #include "ipc/ipc_channel_handle.h" |
| 40 #include "ipc/ipc_switches.h" | 41 #include "ipc/ipc_switches.h" |
| 41 #include "ui/gl/gl_switches.h" | 42 #include "ui/gl/gl_switches.h" |
| 42 | 43 |
| 43 #if defined(TOOLKIT_GTK) | 44 #if defined(TOOLKIT_GTK) |
| 44 #include "ui/gfx/gtk_native_view_id_manager.h" | 45 #include "ui/gfx/gtk_native_view_id_manager.h" |
| 45 #endif | 46 #endif |
| 46 | 47 |
| 47 #if defined(OS_WIN) | 48 #if defined(OS_WIN) |
| 49 #include "base/win/windows_version.h" | |
| 50 #include "content/common/sandbox_win.h" | |
| 51 #include "content/public/common/sandboxed_process_launcher_delegate.h" | |
| 52 #include "sandbox/win/src/sandbox_policy.h" | |
| 48 #include "ui/surface/accelerated_surface_win.h" | 53 #include "ui/surface/accelerated_surface_win.h" |
| 49 #endif | 54 #endif |
| 50 | 55 |
| 51 namespace content { | 56 namespace content { |
| 52 | 57 |
| 53 bool GpuProcessHost::gpu_enabled_ = true; | 58 bool GpuProcessHost::gpu_enabled_ = true; |
| 54 bool GpuProcessHost::hardware_gpu_enabled_ = true; | 59 bool GpuProcessHost::hardware_gpu_enabled_ = true; |
| 55 | 60 |
| 56 namespace { | 61 namespace { |
| 57 | 62 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 int surface_id, | 160 int surface_id, |
| 156 uint64 surface_handle, | 161 uint64 surface_handle, |
| 157 bool alive, | 162 bool alive, |
| 158 base::TimeTicks timebase, | 163 base::TimeTicks timebase, |
| 159 base::TimeDelta interval) { | 164 base::TimeDelta interval) { |
| 160 AcceleratedSurfaceBuffersSwappedCompletedForGPU(host_id, route_id, | 165 AcceleratedSurfaceBuffersSwappedCompletedForGPU(host_id, route_id, |
| 161 alive, surface_handle); | 166 alive, surface_handle); |
| 162 AcceleratedSurfaceBuffersSwappedCompletedForRenderer(surface_id, timebase, | 167 AcceleratedSurfaceBuffersSwappedCompletedForRenderer(surface_id, timebase, |
| 163 interval); | 168 interval); |
| 164 } | 169 } |
| 170 | |
| 171 class GpuSandboxedProcessLauncherDelegate | |
| 172 : public SandboxedProcessLauncherDelegate { | |
| 173 public: | |
| 174 explicit GpuSandboxedProcessLauncherDelegate(CommandLine* cmd_line) | |
| 175 : cmd_line_(cmd_line) {} | |
| 176 virtual ~GpuSandboxedProcessLauncherDelegate() {} | |
| 177 | |
| 178 virtual void PreSandbox(bool* disable_default_policy, | |
| 179 base::FilePath* exposed_dir) { | |
| 180 *disable_default_policy = true; | |
| 181 } | |
| 182 | |
| 183 // For the GPU process we gotten as far as USER_LIMITED. The next level | |
| 184 // which is USER_RESTRICTED breaks both the DirectX backend and the OpenGL | |
| 185 // backend. Note that the GPU process is connected to the interactive | |
| 186 // desktop. | |
| 187 // TODO(cpu): Lock down the sandbox more if possible. | |
| 188 virtual void PreSpawnTarget(sandbox::TargetPolicy* policy, | |
| 189 bool* success) { | |
| 190 if (base::win::GetVersion() > base::win::VERSION_XP) { | |
| 191 if (cmd_line_->GetSwitchValueASCII(switches::kUseGL) == | |
| 192 gfx::kGLImplementationDesktopName) { | |
| 193 // Open GL path. | |
| 194 policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, | |
| 195 sandbox::USER_LIMITED); | |
| 196 SetJobLevel(*cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy); | |
| 197 policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); | |
| 198 } else { | |
| 199 if (cmd_line_->GetSwitchValueASCII(switches::kUseGL) == | |
| 200 gfx::kGLImplementationSwiftShaderName || | |
| 201 cmd_line_->HasSwitch(switches::kReduceGpuSandbox) || | |
| 202 cmd_line_->HasSwitch(switches::kDisableImageTransportSurface)) { | |
| 203 // Swiftshader path. | |
| 204 policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, | |
| 205 sandbox::USER_LIMITED); | |
| 206 } else { | |
| 207 // Angle + DirectX path. | |
| 208 policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, | |
| 209 sandbox::USER_RESTRICTED); | |
| 210 // This is a trick to keep the GPU out of low-integrity processes. It | |
| 211 // starts at low-integrity for UIPI to work, then drops below | |
| 212 // low-integrity after warm-up. | |
| 213 policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED); | |
| 214 } | |
| 215 | |
| 216 // UI restrictions break when we access Windows from outside our job. | |
| 217 // However, we don't want a proxy window in this process because it can | |
| 218 // introduce deadlocks where the renderer blocks on the gpu, which in | |
| 219 // turn blocks on the browser UI thread. So, instead we forgo a window | |
| 220 // message pump entirely and just add job restrictions to prevent child | |
| 221 // processes. | |
| 222 SetJobLevel(*cmd_line_, | |
| 223 sandbox::JOB_LIMITED_USER, | |
| 224 JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | | |
| 225 JOB_OBJECT_UILIMIT_DESKTOP | | |
| 226 JOB_OBJECT_UILIMIT_EXITWINDOWS | | |
| 227 JOB_OBJECT_UILIMIT_DISPLAYSETTINGS, | |
| 228 policy); | |
| 229 | |
| 230 policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); | |
| 231 } | |
| 232 } else { | |
| 233 SetJobLevel(*cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy); | |
| 234 policy->SetTokenLevel(sandbox::USER_UNPROTECTED, | |
| 235 sandbox::USER_LIMITED); | |
| 236 } | |
| 237 | |
| 238 // Allow the server side of GPU sockets, which are pipes that have | |
| 239 // the "chrome.gpu" namespace and an arbitrary suffix. | |
| 240 sandbox::ResultCode result = policy->AddRule( | |
| 241 sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, | |
| 242 sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, | |
| 243 L"\\\\.\\pipe\\chrome.gpu.*"); | |
| 244 if (result != sandbox::SBOX_ALL_OK) { | |
| 245 *success = false; | |
| 246 return; | |
| 247 } | |
| 248 | |
| 249 #ifdef USE_AURA | |
| 250 // GPU also needs to add sections to the browser for aura | |
| 251 // TODO(jschuh): refactor the GPU channel to remove this. crbug.com/128786 | |
| 252 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES, | |
| 253 sandbox::TargetPolicy::HANDLES_DUP_BROKER, | |
| 254 L"Section"); | |
| 255 if (result != sandbox::SBOX_ALL_OK) { | |
| 256 *success = false; | |
| 257 return; | |
| 258 } | |
| 259 #endif | |
| 260 | |
| 261 if (cmd_line_->HasSwitch(switches::kEnableLogging)) { | |
| 262 string16 log_file_path = logging::GetLogFileFullPath(); | |
| 263 if (!log_file_path.empty()) { | |
| 264 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, | |
| 265 sandbox::TargetPolicy::FILES_ALLOW_ANY, | |
| 266 log_file_path.c_str()); | |
| 267 if (result != sandbox::SBOX_ALL_OK) { | |
| 268 *success = false; | |
| 269 return; | |
| 270 } | |
| 271 } | |
| 272 } | |
| 273 } | |
| 274 | |
| 275 private: | |
| 276 CommandLine* cmd_line_; | |
| 277 }; | |
| 165 #endif // defined(OS_WIN) | 278 #endif // defined(OS_WIN) |
| 166 | 279 |
| 167 } // anonymous namespace | 280 } // anonymous namespace |
| 168 | 281 |
| 169 #if defined(TOOLKIT_GTK) | 282 #if defined(TOOLKIT_GTK) |
| 170 // Used to put a lock on surfaces so that the window to which the GPU | 283 // Used to put a lock on surfaces so that the window to which the GPU |
| 171 // process is drawing to doesn't disappear while it is drawing when | 284 // process is drawing to doesn't disappear while it is drawing when |
| 172 // a WebContents is closed. | 285 // a WebContents is closed. |
| 173 class GpuProcessHost::SurfaceRef { | 286 class GpuProcessHost::SurfaceRef { |
| 174 public: | 287 public: |
| (...skipping 851 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1026 switches::kDisableSeccompFilterSandbox, | 1139 switches::kDisableSeccompFilterSandbox, |
| 1027 switches::kEnableGpuSandbox, | 1140 switches::kEnableGpuSandbox, |
| 1028 switches::kEnableLogging, | 1141 switches::kEnableLogging, |
| 1029 switches::kEnableVirtualGLContexts, | 1142 switches::kEnableVirtualGLContexts, |
| 1030 switches::kGpuStartupDialog, | 1143 switches::kGpuStartupDialog, |
| 1031 switches::kLoggingLevel, | 1144 switches::kLoggingLevel, |
| 1032 switches::kNoSandbox, | 1145 switches::kNoSandbox, |
| 1033 switches::kReduceGpuSandbox, | 1146 switches::kReduceGpuSandbox, |
| 1034 switches::kTestGLLib, | 1147 switches::kTestGLLib, |
| 1035 switches::kTraceStartup, | 1148 switches::kTraceStartup, |
| 1149 switches::kUseExynosVda, | |
| 1036 switches::kV, | 1150 switches::kV, |
| 1037 switches::kVModule, | 1151 switches::kVModule, |
| 1038 #if defined(OS_MACOSX) | 1152 #if defined(OS_MACOSX) |
| 1039 switches::kEnableSandboxLogging, | 1153 switches::kEnableSandboxLogging, |
| 1040 #endif | 1154 #endif |
| 1041 #if defined(USE_AURA) | 1155 #if defined(USE_AURA) |
| 1042 switches::kUIPrioritizeInGpuProcess, | 1156 switches::kUIPrioritizeInGpuProcess, |
| 1043 #endif | 1157 #endif |
| 1044 switches::kUseExynosVda, | |
| 1045 }; | 1158 }; |
| 1046 cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames, | 1159 cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames, |
| 1047 arraysize(kSwitchNames)); | 1160 arraysize(kSwitchNames)); |
| 1048 cmd_line->CopySwitchesFrom( | 1161 cmd_line->CopySwitchesFrom( |
| 1049 browser_command_line, switches::kGpuSwitches, switches::kNumGpuSwitches); | 1162 browser_command_line, switches::kGpuSwitches, switches::kNumGpuSwitches); |
| 1050 cmd_line->CopySwitchesFrom( | 1163 cmd_line->CopySwitchesFrom( |
| 1051 browser_command_line, switches::kGLSwitchesCopiedFromGpuProcessHost, | 1164 browser_command_line, switches::kGLSwitchesCopiedFromGpuProcessHost, |
| 1052 switches::kGLSwitchesCopiedFromGpuProcessHostNumSwitches); | 1165 switches::kGLSwitchesCopiedFromGpuProcessHostNumSwitches); |
| 1053 | 1166 |
| 1054 GetContentClient()->browser()->AppendExtraCommandLineSwitches( | 1167 GetContentClient()->browser()->AppendExtraCommandLineSwitches( |
| 1055 cmd_line, process_->GetData().id); | 1168 cmd_line, process_->GetData().id); |
| 1056 | 1169 |
| 1057 GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line); | 1170 GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line); |
| 1058 | 1171 |
| 1059 if (cmd_line->HasSwitch(switches::kUseGL)) { | 1172 if (cmd_line->HasSwitch(switches::kUseGL)) { |
| 1060 software_rendering_ = | 1173 software_rendering_ = |
| 1061 (cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader"); | 1174 (cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader"); |
| 1062 } | 1175 } |
| 1063 | 1176 |
| 1064 UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessSoftwareRendering", software_rendering_); | 1177 UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessSoftwareRendering", software_rendering_); |
| 1065 | 1178 |
| 1066 #if defined(OS_WIN) | |
| 1067 // Make GoogleDesktopNetwork3.dll think that the GPU process is a renderer | |
| 1068 // process so the DLL unloads itself. http://crbug/129884 | |
| 1069 cmd_line->AppendSwitchASCII("ignored", " --type=renderer "); | |
|
jam
2013/03/19 16:06:27
btw I too this out because I made the code in sand
| |
| 1070 #endif | |
| 1071 | |
| 1072 // If specified, prepend a launcher program to the command line. | 1179 // If specified, prepend a launcher program to the command line. |
| 1073 if (!gpu_launcher.empty()) | 1180 if (!gpu_launcher.empty()) |
| 1074 cmd_line->PrependWrapper(gpu_launcher); | 1181 cmd_line->PrependWrapper(gpu_launcher); |
| 1075 | 1182 |
| 1076 process_->Launch( | 1183 process_->Launch( |
| 1077 #if defined(OS_WIN) | 1184 #if defined(OS_WIN) |
| 1078 base::FilePath(), | 1185 new GpuSandboxedProcessLauncherDelegate(cmd_line), |
| 1079 #elif defined(OS_POSIX) | 1186 #elif defined(OS_POSIX) |
| 1080 false, | 1187 false, |
| 1081 base::EnvironmentVector(), | 1188 base::EnvironmentVector(), |
| 1082 #endif | 1189 #endif |
| 1083 cmd_line); | 1190 cmd_line); |
| 1084 process_launched_ = true; | 1191 process_launched_ = true; |
| 1085 | 1192 |
| 1086 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", | 1193 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", |
| 1087 LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX); | 1194 LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX); |
| 1088 return true; | 1195 return true; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1153 TRACE_EVENT0("gpu", "GpuProcessHost::OnCacheShader"); | 1260 TRACE_EVENT0("gpu", "GpuProcessHost::OnCacheShader"); |
| 1154 ClientIdToShaderCacheMap::iterator iter = | 1261 ClientIdToShaderCacheMap::iterator iter = |
| 1155 client_id_to_shader_cache_.find(client_id); | 1262 client_id_to_shader_cache_.find(client_id); |
| 1156 // If the cache doesn't exist then this is an off the record profile. | 1263 // If the cache doesn't exist then this is an off the record profile. |
| 1157 if (iter == client_id_to_shader_cache_.end()) | 1264 if (iter == client_id_to_shader_cache_.end()) |
| 1158 return; | 1265 return; |
| 1159 iter->second->Cache(GetShaderPrefixKey() + ":" + key, shader); | 1266 iter->second->Cache(GetShaderPrefixKey() + ":" + key, shader); |
| 1160 } | 1267 } |
| 1161 | 1268 |
| 1162 } // namespace content | 1269 } // namespace content |
| OLD | NEW |