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"
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.
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"
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";
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
120 void ComputeBuiltInPlugins(std::vector
<content::PepperPluginInfo
>* plugins
) {
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;
129 if (PathService::Get(chrome::FILE_PDF_PLUGIN
, &path
)) {
130 if (skip_pdf_file_check
|| file_util::PathExists(path
)) {
131 content::PepperPluginInfo pdf
;
133 pdf
.name
= kPDFPluginName
;
134 webkit::WebPluginMimeType
pdf_mime_type(kPDFPluginMimeType
,
136 kPDFPluginDescription
);
137 webkit::WebPluginMimeType
print_preview_pdf_mime_type(
138 kPDFPluginPrintPreviewMimeType
,
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
;
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
;
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
,
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
;
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
);
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
;
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
);
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())
304 // Also get the version from the command-line. Should be something like 11.2
306 std::string flash_version
=
307 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
308 switches::kPpapiFlashVersion
);
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
319 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kPpapiFlashPath
))
322 bool force_disable
= CommandLine::ForCurrentProcess()->HasSwitch(
323 switches::kDisableBundledPpapiFlash
);
327 // For Linux ia32, Flapper requires SSE2.
328 #if defined(OS_LINUX) && defined(ARCH_CPU_X86)
329 if (!base::CPU().has_sse2())
331 #endif // ARCH_CPU_X86
334 if (!PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN
, &flash_path
))
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();
345 #endif // FLAPPER_AVAILABLE
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
);
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
:
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";
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";
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(
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(
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
;
460 std::string
ChromeContentClient::GetCarbonInterposePath() const {
461 return std::string(kInterposeLibraryPath
);
465 bool ChromeContentClient::GetBundledFieldTrialPepperFlash(
466 content::PepperPluginInfo
* plugin
,
467 bool* override_npapi_flash
) {
468 if (!ConductingPepperFlashFieldTrial())
470 return GetBundledPepperFlash(plugin
, override_npapi_flash
);
473 } // namespace chrome