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. 4 5#include "chrome/common/chrome_content_client.h" 6 7#include "base/command_line.h" 8#include "base/debug/crash_logging.h" 9#include "base/files/file_util.h" 10#include "base/path_service.h" 11#include "base/strings/string16.h" 12#include "base/strings/string_number_conversions.h" 13#include "base/strings/string_split.h" 14#include "base/strings/string_util.h" 15#include "base/strings/stringprintf.h" 16#include "base/strings/utf_string_conversions.h" 17#include "build/build_config.h" 18#include "chrome/common/child_process_logging.h" 19#include "chrome/common/chrome_paths.h" 20#include "chrome/common/chrome_switches.h" 21#include "chrome/common/chrome_version_info.h" 22#include "chrome/common/crash_keys.h" 23#include "chrome/common/render_messages.h" 24#include "chrome/common/url_constants.h" 25#include "chrome/grit/common_resources.h" 26#include "components/dom_distiller/core/url_constants.h" 27#include "content/public/common/content_constants.h" 28#include "content/public/common/content_switches.h" 29#include "content/public/common/url_constants.h" 30#include "content/public/common/user_agent.h" 31#include "extensions/common/constants.h" 32#include "gpu/config/gpu_info.h" 33#include "net/http/http_util.h" 34#include "ui/base/l10n/l10n_util.h" 35#include "ui/base/layout.h" 36#include "ui/base/resource/resource_bundle.h" 37 38#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. 39 40#if defined(OS_WIN) 41#include "base/win/registry.h" 42#include "base/win/windows_version.h" 43#elif defined(OS_MACOSX) 44#include "components/nacl/common/nacl_sandbox_type_mac.h" 45#endif 46 47#if !defined(DISABLE_NACL) 48#include "components/nacl/common/nacl_constants.h" 49#include "components/nacl/common/nacl_process_type.h" 50#include "ppapi/native_client/src/trusted/plugin/ppapi_entrypoints.h" 51#endif 52 53#if defined(ENABLE_PLUGINS) 54#include "chrome/common/pepper_flash.h" 55#include "content/public/common/pepper_plugin_info.h" 56#include "flapper_version.h" // In SHARED_INTERMEDIATE_DIR. 57#include "ppapi/shared_impl/ppapi_permissions.h" 58#endif 59 60#if defined(ENABLE_REMOTING) 61#include "remoting/client/plugin/pepper_entrypoints.h" 62#endif 63 64#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) && \ 65 !defined(WIDEVINE_CDM_IS_COMPONENT) 66#include "chrome/common/widevine_cdm_constants.h" 67#endif 68 69namespace { 70 71#if defined(ENABLE_PLUGINS) 72const char kPDFPluginMimeType[] = "application/pdf"; 73const char kPDFPluginExtension[] = "pdf"; 74const char kPDFPluginDescription[] = "Portable Document Format"; 75const char kPDFPluginPrintPreviewMimeType[] = 76 "application/x-google-chrome-print-preview-pdf"; 77const char kPDFPluginOutOfProcessMimeType[] = 78 "application/x-google-chrome-pdf"; 79const uint32 kPDFPluginPermissions = ppapi::PERMISSION_PRIVATE | 80 ppapi::PERMISSION_DEV; 81 82const char kO1DPluginName[] = "Google Talk Plugin Video Renderer"; 83const char kO1DPluginMimeType[] ="application/o1d"; 84const char kO1DPluginExtension[] = ""; 85const char kO1DPluginDescription[] = "Google Talk Plugin Video Renderer"; 86const uint32 kO1DPluginPermissions = ppapi::PERMISSION_PRIVATE | 87 ppapi::PERMISSION_DEV; 88 89const char kEffectsPluginName[] = "Google Talk Effects Plugin"; 90const char kEffectsPluginMimeType[] ="application/x-ppapi-hangouts-effects"; 91const char kEffectsPluginExtension[] = ""; 92const char kEffectsPluginDescription[] = "Google Talk Effects Plugin"; 93const uint32 kEffectsPluginPermissions = ppapi::PERMISSION_PRIVATE | 94 ppapi::PERMISSION_DEV; 95 96const char kGTalkPluginName[] = "Google Talk Plugin"; 97const char kGTalkPluginMimeType[] ="application/googletalk"; 98const char kGTalkPluginExtension[] = ".googletalk"; 99const char kGTalkPluginDescription[] = "Google Talk Plugin"; 100const uint32 kGTalkPluginPermissions = ppapi::PERMISSION_PRIVATE | 101 ppapi::PERMISSION_DEV; 102 103#if defined(ENABLE_REMOTING) 104#if defined(GOOGLE_CHROME_BUILD) 105const char kRemotingViewerPluginName[] = "Chrome Remote Desktop Viewer"; 106#else 107const char kRemotingViewerPluginName[] = "Chromoting Viewer"; 108#endif // defined(GOOGLE_CHROME_BUILD) 109const char kRemotingViewerPluginDescription[] = 110 "This plugin allows you to securely access other computers that have been " 111 "shared with you. To use this plugin you must first install the " 112 "<a href=\"https://chrome.google.com/remotedesktop\">" 113 "Chrome Remote Desktop</a> webapp."; 114// Use a consistent MIME-type regardless of branding. 115const char kRemotingViewerPluginMimeType[] = 116 "application/vnd.chromium.remoting-viewer"; 117const char kRemotingViewerPluginMimeExtension[] = ""; 118const char kRemotingViewerPluginMimeDescription[] = ""; 119const uint32 kRemotingViewerPluginPermissions = ppapi::PERMISSION_PRIVATE | 120 ppapi::PERMISSION_DEV; 121#endif // defined(ENABLE_REMOTING) 122 123// Appends the known built-in plugins to the given vector. Some built-in 124// plugins are "internal" which means they are compiled into the Chrome binary, 125// and some are extra shared libraries distributed with the browser (these are 126// not marked internal, aside from being automatically registered, they're just 127// regular plugins). 128void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) { 129 // PDF. 130 // 131 // Once we're sandboxed, we can't know if the PDF plugin is available or not; 132 // but (on Linux) this function is always called once before we're sandboxed. 133 // So the first time through test if the file is available and then skip the 134 // check on subsequent calls if yes. 135 static bool skip_pdf_file_check = false; 136 base::FilePath path; 137 if (PathService::Get(chrome::FILE_PDF_PLUGIN, &path)) { 138 if (skip_pdf_file_check || base::PathExists(path)) { 139 content::PepperPluginInfo pdf; 140 pdf.path = path; 141 pdf.name = ChromeContentClient::kPDFPluginName; 142 if (CommandLine::ForCurrentProcess()->HasSwitch( 143 switches::kOutOfProcessPdf)) { 144 pdf.is_out_of_process = true; 145 content::WebPluginMimeType pdf_mime_type(kPDFPluginOutOfProcessMimeType, 146 kPDFPluginExtension, 147 kPDFPluginDescription); 148 pdf.mime_types.push_back(pdf_mime_type); 149 // TODO(raymes): Make print preview work with out of process PDF. 150 } else { 151 content::WebPluginMimeType pdf_mime_type(kPDFPluginMimeType, 152 kPDFPluginExtension, 153 kPDFPluginDescription); 154 content::WebPluginMimeType print_preview_pdf_mime_type( 155 kPDFPluginPrintPreviewMimeType, 156 kPDFPluginExtension, 157 kPDFPluginDescription); 158 pdf.mime_types.push_back(pdf_mime_type); 159 pdf.mime_types.push_back(print_preview_pdf_mime_type); 160 } 161 pdf.permissions = kPDFPluginPermissions; 162 plugins->push_back(pdf); 163 164 skip_pdf_file_check = true; 165 } 166 } 167 168#if !defined(DISABLE_NACL) 169 // Handle Native Client just like the PDF plugin. This means that it is 170 // enabled by default for the non-portable case. This allows apps installed 171 // from the Chrome Web Store to use NaCl even if the command line switch 172 // isn't set. For other uses of NaCl we check for the command line switch. 173 if (PathService::Get(chrome::FILE_NACL_PLUGIN, &path)) { 174 content::PepperPluginInfo nacl; 175 // The nacl plugin is now built into the Chromium binary. 176 nacl.is_internal = true; 177 nacl.path = path; 178 nacl.name = nacl::kNaClPluginName; 179 content::WebPluginMimeType nacl_mime_type(nacl::kNaClPluginMimeType, 180 nacl::kNaClPluginExtension, 181 nacl::kNaClPluginDescription); 182 nacl.mime_types.push_back(nacl_mime_type); 183 content::WebPluginMimeType pnacl_mime_type(nacl::kPnaclPluginMimeType, 184 nacl::kPnaclPluginExtension, 185 nacl::kPnaclPluginDescription); 186 nacl.mime_types.push_back(pnacl_mime_type); 187 nacl.internal_entry_points.get_interface = nacl_plugin::PPP_GetInterface; 188 nacl.internal_entry_points.initialize_module = 189 nacl_plugin::PPP_InitializeModule; 190 nacl.internal_entry_points.shutdown_module = 191 nacl_plugin::PPP_ShutdownModule; 192 nacl.permissions = ppapi::PERMISSION_PRIVATE | ppapi::PERMISSION_DEV; 193 plugins->push_back(nacl); 194 } 195#endif // !defined(DISABLE_NACL) 196 197 static bool skip_o1d_file_check = false; 198 if (PathService::Get(chrome::FILE_O1D_PLUGIN, &path)) { 199 if (skip_o1d_file_check || base::PathExists(path)) { 200 content::PepperPluginInfo o1d; 201 o1d.path = path; 202 o1d.name = kO1DPluginName; 203 o1d.is_out_of_process = true; 204 o1d.is_sandboxed = false; 205 o1d.permissions = kO1DPluginPermissions; 206 content::WebPluginMimeType o1d_mime_type(kO1DPluginMimeType, 207 kO1DPluginExtension, 208 kO1DPluginDescription); 209 o1d.mime_types.push_back(o1d_mime_type); 210 plugins->push_back(o1d); 211 212 skip_o1d_file_check = true; 213 } 214 } 215 216 // TODO(vrk): Remove this when NaCl effects plugin replaces the ppapi effects 217 // plugin. 218 static bool skip_effects_file_check = false; 219 if (PathService::Get(chrome::FILE_EFFECTS_PLUGIN, &path)) { 220 if (skip_effects_file_check || base::PathExists(path)) { 221 content::PepperPluginInfo effects; 222 effects.path = path; 223 effects.name = kEffectsPluginName; 224 effects.is_out_of_process = true; 225 effects.is_sandboxed = true; 226 effects.permissions = kEffectsPluginPermissions; 227 content::WebPluginMimeType effects_mime_type(kEffectsPluginMimeType, 228 kEffectsPluginExtension, 229 kEffectsPluginDescription); 230 effects.mime_types.push_back(effects_mime_type); 231 plugins->push_back(effects); 232 233 skip_effects_file_check = true; 234 } 235 } 236 237 static bool skip_gtalk_file_check = false; 238 if (PathService::Get(chrome::FILE_GTALK_PLUGIN, &path)) { 239 if (skip_gtalk_file_check || base::PathExists(path)) { 240 content::PepperPluginInfo gtalk; 241 gtalk.path = path; 242 gtalk.name = kGTalkPluginName; 243 gtalk.is_out_of_process = true; 244 gtalk.is_sandboxed = false; 245 gtalk.permissions = kGTalkPluginPermissions; 246 content::WebPluginMimeType gtalk_mime_type(kGTalkPluginMimeType, 247 kGTalkPluginExtension, 248 kGTalkPluginDescription); 249 gtalk.mime_types.push_back(gtalk_mime_type); 250 plugins->push_back(gtalk); 251 252 skip_gtalk_file_check = true; 253 } 254 } 255 256#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) && \ 257 !defined(WIDEVINE_CDM_IS_COMPONENT) 258 static bool skip_widevine_cdm_file_check = false; 259 if (PathService::Get(chrome::FILE_WIDEVINE_CDM_ADAPTER, &path)) { 260 if (skip_widevine_cdm_file_check || base::PathExists(path)) { 261 content::PepperPluginInfo widevine_cdm; 262 widevine_cdm.is_out_of_process = true; 263 widevine_cdm.path = path; 264 widevine_cdm.name = kWidevineCdmDisplayName; 265 widevine_cdm.description = kWidevineCdmDescription + 266 std::string(" (version: ") + 267 WIDEVINE_CDM_VERSION_STRING + ")"; 268 widevine_cdm.version = WIDEVINE_CDM_VERSION_STRING; 269 content::WebPluginMimeType widevine_cdm_mime_type( 270 kWidevineCdmPluginMimeType, 271 kWidevineCdmPluginExtension, 272 kWidevineCdmPluginMimeTypeDescription); 273 274 // Add the supported codecs as if they came from the component manifest. 275 std::vector<std::string> codecs; 276 codecs.push_back(kCdmSupportedCodecVorbis); 277 codecs.push_back(kCdmSupportedCodecVp8); 278 codecs.push_back(kCdmSupportedCodecVp9); 279#if defined(USE_PROPRIETARY_CODECS) 280// TODO(ddorwin): Rename these macros to reflect their real meaning: whether the 281// CDM Chrome was built [and shipped] with support these types. 282#if defined(WIDEVINE_CDM_AAC_SUPPORT_AVAILABLE) 283 codecs.push_back(kCdmSupportedCodecAac); 284#endif 285#if defined(WIDEVINE_CDM_AVC1_SUPPORT_AVAILABLE) 286 codecs.push_back(kCdmSupportedCodecAvc1); 287#endif 288#endif // defined(USE_PROPRIETARY_CODECS) 289 std::string codec_string = 290 JoinString(codecs, kCdmSupportedCodecsValueDelimiter); 291 widevine_cdm_mime_type.additional_param_names.push_back( 292 base::ASCIIToUTF16(kCdmSupportedCodecsParamName)); 293 widevine_cdm_mime_type.additional_param_values.push_back( 294 base::ASCIIToUTF16(codec_string)); 295 296 widevine_cdm.mime_types.push_back(widevine_cdm_mime_type); 297 widevine_cdm.permissions = kWidevineCdmPluginPermissions; 298 plugins->push_back(widevine_cdm); 299 300 skip_widevine_cdm_file_check = true; 301 } 302 } 303#endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) && 304 // !defined(WIDEVINE_CDM_IS_COMPONENT) 305 306 // The Remoting Viewer plugin is built-in. 307#if defined(ENABLE_REMOTING) 308 content::PepperPluginInfo info; 309 info.is_internal = true; 310 info.is_out_of_process = true; 311 info.name = kRemotingViewerPluginName; 312 info.description = kRemotingViewerPluginDescription; 313 info.path = base::FilePath::FromUTF8Unsafe( 314 ChromeContentClient::kRemotingViewerPluginPath); 315 content::WebPluginMimeType remoting_mime_type( 316 kRemotingViewerPluginMimeType, 317 kRemotingViewerPluginMimeExtension, 318 kRemotingViewerPluginMimeDescription); 319 info.mime_types.push_back(remoting_mime_type); 320 info.internal_entry_points.get_interface = remoting::PPP_GetInterface; 321 info.internal_entry_points.initialize_module = 322 remoting::PPP_InitializeModule; 323 info.internal_entry_points.shutdown_module = remoting::PPP_ShutdownModule; 324 info.permissions = kRemotingViewerPluginPermissions; 325 326 plugins->push_back(info); 327#endif 328} 329 330content::PepperPluginInfo CreatePepperFlashInfo(const base::FilePath& path, 331 const std::string& version) { 332 content::PepperPluginInfo plugin; 333 334 plugin.is_out_of_process = true; 335 plugin.name = content::kFlashPluginName; 336 plugin.path = path; 337 plugin.permissions = kPepperFlashPermissions; 338 339 std::vector<std::string> flash_version_numbers; 340 base::SplitString(version, '.', &flash_version_numbers); 341 if (flash_version_numbers.size() < 1) 342 flash_version_numbers.push_back("11"); 343 // |SplitString()| puts in an empty string given an empty string. :( 344 else if (flash_version_numbers[0].empty()) 345 flash_version_numbers[0] = "11"; 346 if (flash_version_numbers.size() < 2) 347 flash_version_numbers.push_back("2"); 348 if (flash_version_numbers.size() < 3) 349 flash_version_numbers.push_back("999"); 350 if (flash_version_numbers.size() < 4) 351 flash_version_numbers.push_back("999"); 352 // E.g., "Shockwave Flash 10.2 r154": 353 plugin.description = plugin.name + " " + flash_version_numbers[0] + "." + 354 flash_version_numbers[1] + " r" + flash_version_numbers[2]; 355 plugin.version = JoinString(flash_version_numbers, '.'); 356 content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType, 357 content::kFlashPluginSwfExtension, 358 content::kFlashPluginSwfDescription); 359 plugin.mime_types.push_back(swf_mime_type); 360 content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType, 361 content::kFlashPluginSplExtension, 362 content::kFlashPluginSplDescription); 363 plugin.mime_types.push_back(spl_mime_type); 364 365 return plugin; 366} 367 368void AddPepperFlashFromCommandLine( 369 std::vector<content::PepperPluginInfo>* plugins) { 370 const CommandLine::StringType flash_path = 371 CommandLine::ForCurrentProcess()->GetSwitchValueNative( 372 switches::kPpapiFlashPath); 373 if (flash_path.empty()) 374 return; 375 376 // Also get the version from the command-line. Should be something like 11.2 377 // or 11.2.123.45. 378 std::string flash_version = 379 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 380 switches::kPpapiFlashVersion); 381 382 plugins->push_back( 383 CreatePepperFlashInfo(base::FilePath(flash_path), flash_version)); 384} 385 386bool GetBundledPepperFlash(content::PepperPluginInfo* plugin) { 387#if defined(FLAPPER_AVAILABLE) 388 CommandLine* command_line = CommandLine::ForCurrentProcess(); 389 390 // Ignore bundled Pepper Flash if there is Pepper Flash specified from the 391 // command-line. 392 if (command_line->HasSwitch(switches::kPpapiFlashPath)) 393 return false; 394 395 bool force_disable = 396 command_line->HasSwitch(switches::kDisableBundledPpapiFlash); 397 if (force_disable) 398 return false; 399 400 base::FilePath flash_path; 401 if (!PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN, &flash_path)) 402 return false; 403 404 *plugin = CreatePepperFlashInfo(flash_path, FLAPPER_VERSION_STRING); 405 return true; 406#else 407 return false; 408#endif // FLAPPER_AVAILABLE 409} 410#endif // defined(ENABLE_PLUGINS) 411 412std::string GetProduct() { 413 chrome::VersionInfo version_info; 414 return version_info.is_valid() ? 415 version_info.ProductNameAndVersionForUserAgent() : std::string(); 416} 417 418} // namespace 419 420std::string GetUserAgent() { 421 CommandLine* command_line = CommandLine::ForCurrentProcess(); 422 if (command_line->HasSwitch(switches::kUserAgent)) { 423 std::string ua = command_line->GetSwitchValueASCII(switches::kUserAgent); 424 if (net::HttpUtil::IsValidHeaderValue(ua)) 425 return ua; 426 LOG(WARNING) << "Ignored invalid value for flag --" << switches::kUserAgent; 427 } 428 429 std::string product = GetProduct(); 430#if defined(OS_ANDROID) 431 if (command_line->HasSwitch(switches::kUseMobileUserAgent)) 432 product += " Mobile"; 433#endif 434 return content::BuildUserAgentFromProduct(product); 435} 436 437void ChromeContentClient::SetActiveURL(const GURL& url) { 438 base::debug::SetCrashKeyValue(crash_keys::kActiveURL, 439 url.possibly_invalid_spec()); 440} 441 442void ChromeContentClient::SetGpuInfo(const gpu::GPUInfo& gpu_info) { 443#if !defined(OS_ANDROID) 444 base::debug::SetCrashKeyValue(crash_keys::kGPUVendorID, 445 base::StringPrintf("0x%04x", gpu_info.gpu.vendor_id)); 446 base::debug::SetCrashKeyValue(crash_keys::kGPUDeviceID, 447 base::StringPrintf("0x%04x", gpu_info.gpu.device_id)); 448#endif 449 base::debug::SetCrashKeyValue(crash_keys::kGPUDriverVersion, 450 gpu_info.driver_version); 451 base::debug::SetCrashKeyValue(crash_keys::kGPUPixelShaderVersion, 452 gpu_info.pixel_shader_version); 453 base::debug::SetCrashKeyValue(crash_keys::kGPUVertexShaderVersion, 454 gpu_info.vertex_shader_version); 455#if defined(OS_MACOSX) 456 base::debug::SetCrashKeyValue(crash_keys::kGPUGLVersion, gpu_info.gl_version); 457#elif defined(OS_POSIX) 458 base::debug::SetCrashKeyValue(crash_keys::kGPUVendor, gpu_info.gl_vendor); 459 base::debug::SetCrashKeyValue(crash_keys::kGPURenderer, gpu_info.gl_renderer); 460#endif 461} 462 463void ChromeContentClient::AddPepperPlugins( 464 std::vector<content::PepperPluginInfo>* plugins) { 465#if defined(ENABLE_PLUGINS) 466 ComputeBuiltInPlugins(plugins); 467 AddPepperFlashFromCommandLine(plugins); 468 469 content::PepperPluginInfo plugin; 470 if (GetBundledPepperFlash(&plugin)) 471 plugins->push_back(plugin); 472#endif 473} 474 475void ChromeContentClient::AddAdditionalSchemes( 476 std::vector<std::string>* standard_schemes, 477 std::vector<std::string>* savable_schemes) { 478 standard_schemes->push_back(extensions::kExtensionScheme); 479 savable_schemes->push_back(extensions::kExtensionScheme); 480 standard_schemes->push_back(chrome::kChromeNativeScheme); 481 standard_schemes->push_back(extensions::kExtensionResourceScheme); 482 savable_schemes->push_back(extensions::kExtensionResourceScheme); 483 standard_schemes->push_back(chrome::kChromeSearchScheme); 484 savable_schemes->push_back(chrome::kChromeSearchScheme); 485 standard_schemes->push_back(dom_distiller::kDomDistillerScheme); 486 savable_schemes->push_back(dom_distiller::kDomDistillerScheme); 487#if defined(OS_CHROMEOS) 488 standard_schemes->push_back(chrome::kCrosScheme); 489#endif 490} 491 492std::string ChromeContentClient::GetProduct() const { 493 return ::GetProduct(); 494} 495 496std::string ChromeContentClient::GetUserAgent() const { 497 return ::GetUserAgent(); 498} 499 500base::string16 ChromeContentClient::GetLocalizedString(int message_id) const { 501 return l10n_util::GetStringUTF16(message_id); 502} 503 504base::StringPiece ChromeContentClient::GetDataResource( 505 int resource_id, 506 ui::ScaleFactor scale_factor) const { 507 return ResourceBundle::GetSharedInstance().GetRawDataResourceForScale( 508 resource_id, scale_factor); 509} 510 511base::RefCountedStaticMemory* ChromeContentClient::GetDataResourceBytes( 512 int resource_id) const { 513 return ResourceBundle::GetSharedInstance().LoadDataResourceBytes(resource_id); 514} 515 516gfx::Image& ChromeContentClient::GetNativeImageNamed(int resource_id) const { 517 return ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id); 518} 519 520std::string ChromeContentClient::GetProcessTypeNameInEnglish(int type) { 521#if !defined(DISABLE_NACL) 522 switch (type) { 523 case PROCESS_TYPE_NACL_LOADER: 524 return "Native Client module"; 525 case PROCESS_TYPE_NACL_BROKER: 526 return "Native Client broker"; 527 } 528#endif 529 530 NOTREACHED() << "Unknown child process type!"; 531 return "Unknown"; 532} 533 534#if defined(OS_MACOSX) && !defined(OS_IOS) 535bool ChromeContentClient::GetSandboxProfileForSandboxType( 536 int sandbox_type, 537 int* sandbox_profile_resource_id) const { 538 DCHECK(sandbox_profile_resource_id); 539 if (sandbox_type == NACL_SANDBOX_TYPE_NACL_LOADER) { 540 *sandbox_profile_resource_id = IDR_NACL_SANDBOX_PROFILE; 541 return true; 542 } 543 return false; 544} 545#endif 546