Extract SIGPIPE ignoring code to a common place.
[chromium-blink-merge.git] / chrome / common / chrome_content_client.cc
blobe8fb3d021a1bca696c5115896f846edc4ecc2495
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 "chrome/common/chrome_content_client.h"
7 #include "base/command_line.h"
8 #include "base/cpu.h"
9 #include "base/file_util.h"
10 #include "base/path_service.h"
11 #include "base/process_util.h"
12 #include "base/string_number_conversions.h"
13 #include "base/string_split.h"
14 #include "base/string_util.h"
15 #include "base/stringprintf.h"
16 #include "base/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/pepper_flash.h"
23 #include "chrome/common/render_messages.h"
24 #include "chrome/common/url_constants.h"
25 #include "content/public/common/content_switches.h"
26 #include "content/public/common/pepper_plugin_info.h"
27 #include "content/public/common/url_constants.h"
28 #include "extensions/common/constants.h"
29 #include "grit/common_resources.h"
30 #include "ppapi/shared_impl/ppapi_permissions.h"
31 #include "remoting/client/plugin/pepper_entrypoints.h"
32 #include "ui/base/l10n/l10n_util.h"
33 #include "ui/base/layout.h"
34 #include "ui/base/resource/resource_bundle.h"
35 #include "webkit/plugins/npapi/plugin_list.h"
36 #include "webkit/plugins/plugin_constants.h"
37 #include "webkit/user_agent/user_agent_util.h"
39 #include "flapper_version.h" // In SHARED_INTERMEDIATE_DIR.
40 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
42 #if defined(OS_WIN)
43 #include "base/win/registry.h"
44 #include "base/win/windows_version.h"
45 #include "sandbox/win/src/sandbox.h"
46 #elif defined(OS_MACOSX)
47 #include "chrome/common/chrome_sandbox_type_mac.h"
48 #endif
50 namespace {
52 const char kPDFPluginName[] = "Chrome PDF Viewer";
53 const char kPDFPluginMimeType[] = "application/pdf";
54 const char kPDFPluginExtension[] = "pdf";
55 const char kPDFPluginDescription[] = "Portable Document Format";
56 const char kPDFPluginPrintPreviewMimeType
57 [] = "application/x-google-chrome-print-preview-pdf";
58 const uint32 kPDFPluginPermissions = ppapi::PERMISSION_PRIVATE |
59 ppapi::PERMISSION_DEV;
61 const char kNaClPluginName[] = "Native Client";
62 const char kNaClPluginMimeType[] = "application/x-nacl";
63 const char kNaClPluginExtension[] = "nexe";
64 const char kNaClPluginDescription[] = "Native Client Executable";
65 const uint32 kNaClPluginPermissions = ppapi::PERMISSION_PRIVATE |
66 ppapi::PERMISSION_DEV;
68 const char kNaClOldPluginName[] = "Chrome NaCl";
70 const char kO3DPluginName[] = "Google Talk Plugin Video Accelerator";
71 const char kO3DPluginMimeType[] ="application/vnd.o3d.auto";
72 const char kO3DPluginExtension[] = "";
73 const char kO3DPluginDescription[] = "O3D MIME";
74 const uint32 kO3DPluginPermissions = ppapi::PERMISSION_PRIVATE |
75 ppapi::PERMISSION_DEV;
77 const char kGTalkPluginName[] = "Google Talk Plugin";
78 const char kGTalkPluginMimeType[] ="application/googletalk";
79 const char kGTalkPluginExtension[] = ".googletalk";
80 const char kGTalkPluginDescription[] = "Google Talk Plugin";
81 const uint32 kGTalkPluginPermissions = ppapi::PERMISSION_PRIVATE |
82 ppapi::PERMISSION_DEV;
84 #if defined(WIDEVINE_CDM_AVAILABLE)
85 const char kWidevineCdmPluginExtension[] = "";
86 const uint32 kWidevineCdmPluginPermissions = ppapi::PERMISSION_PRIVATE |
87 ppapi::PERMISSION_DEV;
88 #endif // WIDEVINE_CDM_AVAILABLE
90 #if defined(ENABLE_REMOTING)
91 #if defined(GOOGLE_CHROME_BUILD)
92 const char kRemotingViewerPluginName[] = "Chrome Remote Desktop Viewer";
93 #else
94 const char kRemotingViewerPluginName[] = "Chromoting Viewer";
95 #endif // defined(GOOGLE_CHROME_BUILD)
96 const char kRemotingViewerPluginDescription[] =
97 "This plugin allows you to securely access other computers that have been "
98 "shared with you. To use this plugin you must first install the "
99 "<a href=\"https://chrome.google.com/remotedesktop\">"
100 "Chrome Remote Desktop</a> webapp.";
101 const FilePath::CharType kRemotingViewerPluginPath[] =
102 FILE_PATH_LITERAL("internal-remoting-viewer");
103 // Use a consistent MIME-type regardless of branding.
104 const char kRemotingViewerPluginMimeType[] =
105 "application/vnd.chromium.remoting-viewer";
106 const char kRemotingViewerPluginMimeExtension[] = "";
107 const char kRemotingViewerPluginMimeDescription[] = "";
108 const uint32 kRemotingViewerPluginPermissions = ppapi::PERMISSION_PRIVATE |
109 ppapi::PERMISSION_DEV;
110 #endif // defined(ENABLE_REMOTING)
112 const char kInterposeLibraryPath[] =
113 "@executable_path/../../../libplugin_carbon_interpose.dylib";
115 // Appends the known built-in plugins to the given vector. Some built-in
116 // plugins are "internal" which means they are compiled into the Chrome binary,
117 // and some are extra shared libraries distributed with the browser (these are
118 // not marked internal, aside from being automatically registered, they're just
119 // regular plugins).
120 void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
121 // PDF.
123 // Once we're sandboxed, we can't know if the PDF plugin is available or not;
124 // but (on Linux) this function is always called once before we're sandboxed.
125 // So the first time through test if the file is available and then skip the
126 // check on subsequent calls if yes.
127 static bool skip_pdf_file_check = false;
128 FilePath path;
129 if (PathService::Get(chrome::FILE_PDF_PLUGIN, &path)) {
130 if (skip_pdf_file_check || file_util::PathExists(path)) {
131 content::PepperPluginInfo pdf;
132 pdf.path = path;
133 pdf.name = kPDFPluginName;
134 webkit::WebPluginMimeType pdf_mime_type(kPDFPluginMimeType,
135 kPDFPluginExtension,
136 kPDFPluginDescription);
137 webkit::WebPluginMimeType print_preview_pdf_mime_type(
138 kPDFPluginPrintPreviewMimeType,
139 kPDFPluginExtension,
140 kPDFPluginDescription);
141 pdf.mime_types.push_back(pdf_mime_type);
142 pdf.mime_types.push_back(print_preview_pdf_mime_type);
143 pdf.permissions = kPDFPluginPermissions;
144 plugins->push_back(pdf);
146 skip_pdf_file_check = true;
150 // Handle the Native Client just like the PDF plugin. This means that it is
151 // enabled by default. This allows apps installed from the Chrome Web Store
152 // to use NaCl even if the command line switch isn't set. For other uses of
153 // NaCl we check for the command line switch.
154 static bool skip_nacl_file_check = false;
155 if (PathService::Get(chrome::FILE_NACL_PLUGIN, &path)) {
156 if (skip_nacl_file_check || file_util::PathExists(path)) {
157 content::PepperPluginInfo nacl;
158 nacl.path = path;
159 nacl.name = kNaClPluginName;
160 webkit::WebPluginMimeType nacl_mime_type(kNaClPluginMimeType,
161 kNaClPluginExtension,
162 kNaClPluginDescription);
163 nacl.mime_types.push_back(nacl_mime_type);
164 nacl.permissions = kNaClPluginPermissions;
165 plugins->push_back(nacl);
167 skip_nacl_file_check = true;
171 static bool skip_o3d_file_check = false;
172 if (PathService::Get(chrome::FILE_O3D_PLUGIN, &path)) {
173 if (skip_o3d_file_check || file_util::PathExists(path)) {
174 content::PepperPluginInfo o3d;
175 o3d.path = path;
176 o3d.name = kO3DPluginName;
177 o3d.is_out_of_process = true;
178 o3d.is_sandboxed = false;
179 o3d.permissions = kO3DPluginPermissions;
180 webkit::WebPluginMimeType o3d_mime_type(kO3DPluginMimeType,
181 kO3DPluginExtension,
182 kO3DPluginDescription);
183 o3d.mime_types.push_back(o3d_mime_type);
184 plugins->push_back(o3d);
186 skip_o3d_file_check = true;
190 static bool skip_gtalk_file_check = false;
191 if (PathService::Get(chrome::FILE_GTALK_PLUGIN, &path)) {
192 if (skip_gtalk_file_check || file_util::PathExists(path)) {
193 content::PepperPluginInfo gtalk;
194 gtalk.path = path;
195 gtalk.name = kGTalkPluginName;
196 gtalk.is_out_of_process = true;
197 gtalk.is_sandboxed = false;
198 gtalk.permissions = kGTalkPluginPermissions;
199 webkit::WebPluginMimeType gtalk_mime_type(kGTalkPluginMimeType,
200 kGTalkPluginExtension,
201 kGTalkPluginDescription);
202 gtalk.mime_types.push_back(gtalk_mime_type);
203 plugins->push_back(gtalk);
205 skip_gtalk_file_check = true;
209 #if defined(WIDEVINE_CDM_AVAILABLE)
210 static bool skip_widevine_cdm_file_check = false;
211 if (PathService::Get(chrome::FILE_WIDEVINE_CDM_PLUGIN, &path)) {
212 if (skip_widevine_cdm_file_check || file_util::PathExists(path)) {
213 content::PepperPluginInfo widevine_cdm;
214 widevine_cdm.is_out_of_process = true;
215 widevine_cdm.path = path;
216 widevine_cdm.name = kWidevineCdmPluginName;
217 widevine_cdm.description = kWidevineCdmPluginDescription;
218 widevine_cdm.version = WIDEVINE_CDM_VERSION_STRING;
219 webkit::WebPluginMimeType widevine_cdm_mime_type(
220 kWidevineCdmPluginMimeType,
221 kWidevineCdmPluginExtension,
222 kWidevineCdmPluginMimeTypeDescription);
223 widevine_cdm.mime_types.push_back(widevine_cdm_mime_type);
224 widevine_cdm.permissions = kWidevineCdmPluginPermissions;
225 plugins->push_back(widevine_cdm);
227 skip_widevine_cdm_file_check = true;
230 #endif // WIDEVINE_CDM_AVAILABLE
232 // The Remoting Viewer plugin is built-in.
233 #if defined(ENABLE_REMOTING)
234 content::PepperPluginInfo info;
235 info.is_internal = true;
236 info.is_out_of_process = true;
237 info.name = kRemotingViewerPluginName;
238 info.description = kRemotingViewerPluginDescription;
239 info.path = FilePath(kRemotingViewerPluginPath);
240 webkit::WebPluginMimeType remoting_mime_type(
241 kRemotingViewerPluginMimeType,
242 kRemotingViewerPluginMimeExtension,
243 kRemotingViewerPluginMimeDescription);
244 info.mime_types.push_back(remoting_mime_type);
245 info.internal_entry_points.get_interface = remoting::PPP_GetInterface;
246 info.internal_entry_points.initialize_module =
247 remoting::PPP_InitializeModule;
248 info.internal_entry_points.shutdown_module = remoting::PPP_ShutdownModule;
249 info.permissions = kRemotingViewerPluginPermissions;
251 plugins->push_back(info);
252 #endif
255 content::PepperPluginInfo CreatePepperFlashInfo(const FilePath& path,
256 const std::string& version) {
257 content::PepperPluginInfo plugin;
259 // Flash being out of process is handled separately than general plugins
260 // for testing purposes.
261 plugin.is_out_of_process = !CommandLine::ForCurrentProcess()->HasSwitch(
262 switches::kPpapiFlashInProcess);
263 plugin.name = kFlashPluginName;
264 plugin.path = path;
265 plugin.permissions = kPepperFlashPermissions;
267 std::vector<std::string> flash_version_numbers;
268 base::SplitString(version, '.', &flash_version_numbers);
269 if (flash_version_numbers.size() < 1)
270 flash_version_numbers.push_back("11");
271 // |SplitString()| puts in an empty string given an empty string. :(
272 else if (flash_version_numbers[0].empty())
273 flash_version_numbers[0] = "11";
274 if (flash_version_numbers.size() < 2)
275 flash_version_numbers.push_back("2");
276 if (flash_version_numbers.size() < 3)
277 flash_version_numbers.push_back("999");
278 if (flash_version_numbers.size() < 4)
279 flash_version_numbers.push_back("999");
280 // E.g., "Shockwave Flash 10.2 r154":
281 plugin.description = plugin.name + " " + flash_version_numbers[0] + "." +
282 flash_version_numbers[1] + " r" + flash_version_numbers[2];
283 plugin.version = JoinString(flash_version_numbers, '.');
284 webkit::WebPluginMimeType swf_mime_type(kFlashPluginSwfMimeType,
285 kFlashPluginSwfExtension,
286 kFlashPluginSwfDescription);
287 plugin.mime_types.push_back(swf_mime_type);
288 webkit::WebPluginMimeType spl_mime_type(kFlashPluginSplMimeType,
289 kFlashPluginSplExtension,
290 kFlashPluginSplDescription);
291 plugin.mime_types.push_back(spl_mime_type);
293 return plugin;
296 void AddPepperFlashFromCommandLine(
297 std::vector<content::PepperPluginInfo>* plugins) {
298 const CommandLine::StringType flash_path =
299 CommandLine::ForCurrentProcess()->GetSwitchValueNative(
300 switches::kPpapiFlashPath);
301 if (flash_path.empty())
302 return;
304 // Also get the version from the command-line. Should be something like 11.2
305 // or 11.2.123.45.
306 std::string flash_version =
307 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
308 switches::kPpapiFlashVersion);
310 plugins->push_back(
311 CreatePepperFlashInfo(FilePath(flash_path), flash_version));
314 bool GetBundledPepperFlash(content::PepperPluginInfo* plugin,
315 bool* override_npapi_flash) {
316 #if defined(FLAPPER_AVAILABLE)
317 // Ignore bundled Pepper Flash if there is Pepper Flash specified from the
318 // command-line.
319 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kPpapiFlashPath))
320 return false;
322 bool force_disable = CommandLine::ForCurrentProcess()->HasSwitch(
323 switches::kDisableBundledPpapiFlash);
324 if (force_disable)
325 return false;
327 // For Linux ia32, Flapper requires SSE2.
328 #if defined(OS_LINUX) && defined(ARCH_CPU_X86)
329 if (!base::CPU().has_sse2())
330 return false;
331 #endif // ARCH_CPU_X86
333 FilePath flash_path;
334 if (!PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN, &flash_path))
335 return false;
337 bool force_enable = CommandLine::ForCurrentProcess()->HasSwitch(
338 switches::kEnableBundledPpapiFlash);
340 *plugin = CreatePepperFlashInfo(flash_path, FLAPPER_VERSION_STRING);
341 *override_npapi_flash = force_enable || IsPepperFlashEnabledByDefault();
342 return true;
343 #else
344 return false;
345 #endif // FLAPPER_AVAILABLE
348 } // namespace
350 namespace chrome {
352 const char* const ChromeContentClient::kPDFPluginName = ::kPDFPluginName;
353 const char* const ChromeContentClient::kNaClPluginName = ::kNaClPluginName;
354 const char* const ChromeContentClient::kNaClOldPluginName =
355 ::kNaClOldPluginName;
357 void ChromeContentClient::SetActiveURL(const GURL& url) {
358 child_process_logging::SetActiveURL(url);
361 void ChromeContentClient::SetGpuInfo(const content::GPUInfo& gpu_info) {
362 child_process_logging::SetGpuInfo(gpu_info);
365 void ChromeContentClient::AddPepperPlugins(
366 std::vector<content::PepperPluginInfo>* plugins) {
367 ComputeBuiltInPlugins(plugins);
368 AddPepperFlashFromCommandLine(plugins);
370 // Don't try to register Pepper Flash if there exists a Pepper Flash field
371 // trial. It will be registered separately.
372 if (!ConductingPepperFlashFieldTrial() && IsPepperFlashEnabledByDefault()) {
373 content::PepperPluginInfo plugin;
374 bool add_at_beginning = false;
375 if (GetBundledPepperFlash(&plugin, &add_at_beginning))
376 plugins->push_back(plugin);
380 void ChromeContentClient::AddNPAPIPlugins(
381 webkit::npapi::PluginList* plugin_list) {
384 void ChromeContentClient::AddAdditionalSchemes(
385 std::vector<std::string>* standard_schemes,
386 std::vector<std::string>* savable_schemes) {
387 standard_schemes->push_back(extensions::kExtensionScheme);
388 savable_schemes->push_back(extensions::kExtensionScheme);
389 standard_schemes->push_back(kExtensionResourceScheme);
390 savable_schemes->push_back(kExtensionResourceScheme);
391 #if defined(OS_CHROMEOS)
392 standard_schemes->push_back(kCrosScheme);
393 #endif
396 bool ChromeContentClient::HasWebUIScheme(const GURL& url) const {
397 return url.SchemeIs(chrome::kChromeDevToolsScheme) ||
398 url.SchemeIs(chrome::kChromeInternalScheme) ||
399 url.SchemeIs(chrome::kChromeUIScheme);
402 bool ChromeContentClient::CanHandleWhileSwappedOut(
403 const IPC::Message& msg) {
404 // Any Chrome-specific messages (apart from those listed in
405 // CanSendWhileSwappedOut) that must be handled by the browser when sent from
406 // swapped out renderers.
407 switch (msg.type()) {
408 case ChromeViewHostMsg_Snapshot::ID:
409 return true;
410 default:
411 break;
413 return false;
416 std::string ChromeContentClient::GetProduct() const {
417 chrome::VersionInfo version_info;
418 std::string product("Chrome/");
419 product += version_info.is_valid() ? version_info.Version() : "0.0.0.0";
420 return product;
423 std::string ChromeContentClient::GetUserAgent() const {
424 std::string product = GetProduct();
425 #if defined(OS_ANDROID)
426 CommandLine* command_line = CommandLine::ForCurrentProcess();
427 if (command_line->HasSwitch(switches::kUseMobileUserAgent))
428 product += " Mobile";
429 #endif
430 return webkit_glue::BuildUserAgentFromProduct(product);
433 string16 ChromeContentClient::GetLocalizedString(int message_id) const {
434 return l10n_util::GetStringUTF16(message_id);
437 base::StringPiece ChromeContentClient::GetDataResource(
438 int resource_id,
439 ui::ScaleFactor scale_factor) const {
440 return ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
441 resource_id, scale_factor);
444 gfx::Image& ChromeContentClient::GetNativeImageNamed(int resource_id) const {
445 return ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id);
448 #if defined(OS_MACOSX) && !defined(OS_IOS)
449 bool ChromeContentClient::GetSandboxProfileForSandboxType(
450 int sandbox_type,
451 int* sandbox_profile_resource_id) const {
452 DCHECK(sandbox_profile_resource_id);
453 if (sandbox_type == CHROME_SANDBOX_TYPE_NACL_LOADER) {
454 *sandbox_profile_resource_id = IDR_NACL_SANDBOX_PROFILE;
455 return true;
457 return false;
460 std::string ChromeContentClient::GetCarbonInterposePath() const {
461 return std::string(kInterposeLibraryPath);
463 #endif
465 bool ChromeContentClient::GetBundledFieldTrialPepperFlash(
466 content::PepperPluginInfo* plugin,
467 bool* override_npapi_flash) {
468 if (!ConductingPepperFlashFieldTrial())
469 return false;
470 return GetBundledPepperFlash(plugin, override_npapi_flash);
473 } // namespace chrome