1// Copyright (c) 2011 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/file_util.h"
9#include "base/path_service.h"
10#include "base/string_split.h"
11#include "base/string_util.h"
12#include "chrome/common/child_process_logging.h"
13#include "chrome/common/chrome_paths.h"
14#include "chrome/common/chrome_switches.h"
15#include "content/common/pepper_plugin_registry.h"
16#include "remoting/client/plugin/pepper_entrypoints.h"
17
18namespace {
19
20const char* kPDFPluginName = "Chrome PDF Viewer";
21const char* kPDFPluginMimeType = "application/pdf";
22const char* kPDFPluginExtension = "pdf";
23const char* kPDFPluginDescription = "Portable Document Format";
24
25const char* kNaClPluginName = "Chrome NaCl";
26const char* kNaClPluginMimeType = "application/x-nacl";
27const char* kNaClPluginExtension = "nexe";
28const char* kNaClPluginDescription = "Native Client Executable";
29
30#if defined(ENABLE_REMOTING)
31const char* kRemotingPluginMimeType = "pepper-application/x-chromoting";
32#endif
33
34const char* kFlashPluginName = "Shockwave Flash";
35const char* kFlashPluginSwfMimeType = "application/x-shockwave-flash";
36const char* kFlashPluginSwfExtension = "swf";
37const char* kFlashPluginSwfDescription = "Shockwave Flash";
38const char* kFlashPluginSplMimeType = "application/futuresplash";
39const char* kFlashPluginSplExtension = "spl";
40const char* kFlashPluginSplDescription = "FutureSplash Player";
41
42#if !defined(NACL_WIN64)  // The code this needs isn't linked on Win64 builds.
43
44// Appends the known built-in plugins to the given vector. Some built-in
45// plugins are "internal" which means they are compiled into the Chrome binary,
46// and some are extra shared libraries distributed with the browser (these are
47// not marked internal, aside from being automatically registered, they're just
48// regular plugins).
49void ComputeBuiltInPlugins(std::vector<PepperPluginInfo>* plugins) {
50  // PDF.
51  //
52  // Once we're sandboxed, we can't know if the PDF plugin is available or not;
53  // but (on Linux) this function is always called once before we're sandboxed.
54  // So the first time through test if the file is available and then skip the
55  // check on subsequent calls if yes.
56  static bool skip_pdf_file_check = false;
57  FilePath path;
58  if (PathService::Get(chrome::FILE_PDF_PLUGIN, &path)) {
59    if (skip_pdf_file_check || file_util::PathExists(path)) {
60      PepperPluginInfo pdf;
61      pdf.path = path;
62      pdf.name = kPDFPluginName;
63      webkit::npapi::WebPluginMimeType pdf_mime_type(kPDFPluginMimeType,
64                                                     kPDFPluginExtension,
65                                                     kPDFPluginDescription);
66      pdf.mime_types.push_back(pdf_mime_type);
67      plugins->push_back(pdf);
68
69      skip_pdf_file_check = true;
70    }
71  }
72
73  // Handle the Native Client plugin just like the PDF plugin.
74  static bool skip_nacl_file_check = false;
75  if (PathService::Get(chrome::FILE_NACL_PLUGIN, &path)) {
76    if (skip_nacl_file_check || file_util::PathExists(path)) {
77      PepperPluginInfo nacl;
78      nacl.path = path;
79      nacl.name = kNaClPluginName;
80      // Enable the Native Client Plugin based on the command line.
81      nacl.enabled = CommandLine::ForCurrentProcess()->HasSwitch(
82          switches::kEnableNaCl);
83      webkit::npapi::WebPluginMimeType nacl_mime_type(kNaClPluginMimeType,
84                                                      kNaClPluginExtension,
85                                                      kNaClPluginDescription);
86      nacl.mime_types.push_back(nacl_mime_type);
87      plugins->push_back(nacl);
88
89      skip_nacl_file_check = true;
90    }
91  }
92
93  // Remoting.
94#if defined(ENABLE_REMOTING)
95  if (CommandLine::ForCurrentProcess()->HasSwitch(
96      switches::kEnableRemoting)) {
97    PepperPluginInfo info;
98    info.is_internal = true;
99    info.path = FilePath(FILE_PATH_LITERAL("internal-chromoting"));
100    webkit::npapi::WebPluginMimeType remoting_mime_type(kRemotingPluginMimeType,
101                                                        std::string(),
102                                                        std::string());
103    info.mime_types.push_back(remoting_mime_type);
104    info.internal_entry_points.get_interface = remoting::PPP_GetInterface;
105    info.internal_entry_points.initialize_module =
106        remoting::PPP_InitializeModule;
107    info.internal_entry_points.shutdown_module = remoting::PPP_ShutdownModule;
108
109    plugins->push_back(info);
110  }
111#endif
112}
113
114void AddOutOfProcessFlash(std::vector<PepperPluginInfo>* plugins) {
115  // Flash being out of process is handled separately than general plugins
116  // for testing purposes.
117  bool flash_out_of_process = !CommandLine::ForCurrentProcess()->HasSwitch(
118      switches::kPpapiFlashInProcess);
119
120  // Handle any Pepper Flash first.
121  const CommandLine::StringType flash_path =
122      CommandLine::ForCurrentProcess()->GetSwitchValueNative(
123          switches::kPpapiFlashPath);
124  if (flash_path.empty())
125    return;
126
127  PepperPluginInfo plugin;
128  plugin.is_out_of_process = flash_out_of_process;
129  plugin.path = FilePath(flash_path);
130  plugin.name = kFlashPluginName;
131
132  const std::string flash_version =
133      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
134              switches::kPpapiFlashVersion);
135  std::vector<std::string> flash_version_numbers;
136  base::SplitString(flash_version, '.', &flash_version_numbers);
137  if (flash_version_numbers.size() < 1)
138    flash_version_numbers.push_back("10");
139  // |SplitString()| puts in an empty string given an empty string. :(
140  else if (flash_version_numbers[0].empty())
141    flash_version_numbers[0] = "10";
142  if (flash_version_numbers.size() < 2)
143    flash_version_numbers.push_back("2");
144  if (flash_version_numbers.size() < 3)
145    flash_version_numbers.push_back("999");
146  if (flash_version_numbers.size() < 4)
147    flash_version_numbers.push_back("999");
148  // E.g., "Shockwave Flash 10.2 r154":
149  plugin.description = plugin.name + " " + flash_version_numbers[0] + "." +
150      flash_version_numbers[1] + " r" + flash_version_numbers[2];
151  plugin.version = JoinString(flash_version_numbers, '.');
152  webkit::npapi::WebPluginMimeType swf_mime_type(kFlashPluginSwfMimeType,
153                                                 kFlashPluginSwfExtension,
154                                                 kFlashPluginSwfDescription);
155  plugin.mime_types.push_back(swf_mime_type);
156  webkit::npapi::WebPluginMimeType spl_mime_type(kFlashPluginSplMimeType,
157                                                 kFlashPluginSplExtension,
158                                                 kFlashPluginSplDescription);
159  plugin.mime_types.push_back(spl_mime_type);
160  plugins->push_back(plugin);
161}
162
163#endif  // !defined(NACL_WIN64)
164
165}  // namespace
166
167namespace chrome {
168
169const char* ChromeContentClient::kPDFPluginName = ::kPDFPluginName;
170
171void ChromeContentClient::SetActiveURL(const GURL& url) {
172  child_process_logging::SetActiveURL(url);
173}
174
175void ChromeContentClient::SetGpuInfo(const GPUInfo& gpu_info) {
176  child_process_logging::SetGpuInfo(gpu_info);
177}
178
179void ChromeContentClient::AddPepperPlugins(
180    std::vector<PepperPluginInfo>* plugins) {
181#if !defined(NACL_WIN64)  // The code this needs isn't linked on Win64 builds.
182  ComputeBuiltInPlugins(plugins);
183  AddOutOfProcessFlash(plugins);
184#endif
185}
186
187}  // namespace chrome
188