OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "chrome/browser/component_updater/flash_component_installer.h" | 5 #include "chrome/browser/component_updater/flash_component_installer.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/base_paths.h" | 11 #include "base/base_paths.h" |
12 #include "base/base_paths_win.h" | |
12 #include "base/bind.h" | 13 #include "base/bind.h" |
13 #include "base/command_line.h" | 14 #include "base/command_line.h" |
14 #include "base/compiler_specific.h" | 15 #include "base/compiler_specific.h" |
15 #include "base/file_util.h" | 16 #include "base/file_util.h" |
16 #include "base/files/file_enumerator.h" | 17 #include "base/files/file_enumerator.h" |
17 #include "base/files/file_path.h" | 18 #include "base/files/file_path.h" |
18 #include "base/logging.h" | 19 #include "base/logging.h" |
19 #include "base/path_service.h" | 20 #include "base/path_service.h" |
20 #include "base/strings/string_split.h" | 21 #include "base/strings/string_split.h" |
21 #include "base/strings/string_util.h" | 22 #include "base/strings/string_util.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 #endif | 84 #endif |
84 | 85 |
85 // The base directory on Windows looks like: | 86 // The base directory on Windows looks like: |
86 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\. | 87 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\. |
87 base::FilePath GetPepperFlashBaseDirectory() { | 88 base::FilePath GetPepperFlashBaseDirectory() { |
88 base::FilePath result; | 89 base::FilePath result; |
89 PathService::Get(chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, &result); | 90 PathService::Get(chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, &result); |
90 return result; | 91 return result; |
91 } | 92 } |
92 | 93 |
94 // Install directory for pepper flash debugger dlls will be like | |
95 // c:\windows\system32\macromed\flash\, or basically the Macromed\Flash | |
96 // subdirectory of the Windows system directory. | |
97 base::FilePath GetPepperFlashDebuggerDirectory() { | |
98 base::FilePath result; | |
99 PathService::Get(base::DIR_SYSTEM, &result); | |
100 base::FilePath subdir; | |
101 PathService::Get(chrome::DIR_PEPPER_FLASH_DEBUGGER_PLUGIN, &subdir); | |
cpu_(ooo_6.6-7.5)
2014/04/24 20:42:04
any reason not to return the full path when chrome
luken
2014/04/24 22:04:15
Done.
| |
102 return result.Append(subdir); | |
103 } | |
104 | |
93 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 105 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) |
94 // Pepper Flash plugins have the version encoded in the path itself | 106 // Pepper Flash plugins have the version encoded in the path itself |
95 // so we need to enumerate the directories to find the full path. | 107 // so we need to enumerate the directories to find the full path. |
96 // On success, |latest_dir| returns something like: | 108 // On success, |latest_dir| returns something like: |
97 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\10.3.44.555\. | 109 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\10.3.44.555\. |
98 // |latest_version| returns the corresponding version number. |older_dirs| | 110 // |latest_version| returns the corresponding version number. |older_dirs| |
99 // returns directories of all older versions. | 111 // returns directories of all older versions. |
100 bool GetPepperFlashDirectory(base::FilePath* latest_dir, | 112 bool GetPepperFlashDirectory(base::FilePath* latest_dir, |
101 Version* latest_version, | 113 Version* latest_version, |
102 std::vector<base::FilePath>* older_dirs) { | 114 std::vector<base::FilePath>* older_dirs) { |
(...skipping 17 matching lines...) Expand all Loading... | |
120 } else { | 132 } else { |
121 *latest_dir = path; | 133 *latest_dir = path; |
122 *latest_version = version; | 134 *latest_version = version; |
123 found = true; | 135 found = true; |
124 } | 136 } |
125 } | 137 } |
126 return found; | 138 return found; |
127 } | 139 } |
128 #endif | 140 #endif |
129 | 141 |
142 const wchar_t kPepperFlashDebuggerDLLSearchString[] = | |
143 #if defined(ARCH_CPU_X86) | |
144 L"pepflashplayer32*.dll"; | |
145 #elif defined(ARCH_CPU_X86_64) | |
146 L"pepflashplayer64*.dll"; | |
147 #else // TODO(luken): ARM flash debugger? | |
148 L"???"; | |
cpu_(ooo_6.6-7.5)
2014/04/24 20:42:04
elif defined(ARCH_CPU_ARM_FAMILY) ?
luken
2014/04/24 22:04:15
Done.
| |
149 #endif | |
150 | |
151 bool GetPepperFlashDebuggerPath(base::FilePath* dll_path, | |
152 Version* dll_version) { | |
cpu_(ooo_6.6-7.5)
2014/04/24 20:42:04
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::F
luken
2014/04/24 22:04:15
We are on the file IO thread, and the other functi
| |
153 base::FilePath debugger_dir = GetPepperFlashDebuggerDirectory(); | |
154 // If path doesn't exist they simply don't have the flash debugger installed. | |
155 if (!base::PathExists(debugger_dir)) { | |
cpu_(ooo_6.6-7.5)
2014/04/24 20:42:04
if the style of this file has single statement ifs
luken
2014/04/24 22:04:15
Done.
| |
156 return false; | |
157 } | |
158 bool found = false; | |
159 // Enumerate any DLLs that match the appropriate pattern for this DLL, and | |
160 // pick the highest version number we find. | |
161 base::FileEnumerator file_enumerator(debugger_dir, | |
162 false, | |
163 base::FileEnumerator::FILES, | |
164 kPepperFlashDebuggerDLLSearchString); | |
165 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); | |
166 path = file_enumerator.Next()) { | |
167 // Version number is embedded in file name like basename_x_y_z.dll. Extract. | |
168 std::string file_name(path.BaseName().MaybeAsASCII()); | |
cpu_(ooo_6.6-7.5)
2014/04/24 20:42:04
I have the feeling that using base/strings/string_
luken
2014/04/24 22:04:15
I didn't know about this, yes!
| |
169 std::size_t ver_start = file_name.find_first_of("_"); | |
170 if (ver_start == std::string::npos) | |
171 continue; | |
172 // Add one to the ver_start to skip over the starting underscore. | |
173 ++ver_start; | |
174 std::size_t ver_end = file_name.find_first_of(".", ver_start); | |
175 if (ver_end == std::string::npos) | |
176 continue; | |
177 std::string version_string = | |
178 file_name.substr(ver_start, ver_end - ver_start); | |
179 // Now swap all the underscores for dots, so our version object can parse. | |
180 for (std::size_t i = 0; i < version_string.length(); ++i) { | |
181 if (version_string[i] == '_') | |
182 version_string[i] = '.'; | |
183 } | |
184 Version version(version_string); | |
185 if (!version.IsValid()) | |
186 continue; | |
187 if (found) { | |
188 if (version.CompareTo(*dll_version) > 0) { | |
189 *dll_path = path; | |
190 *dll_version = version; | |
191 } | |
192 } else { | |
193 *dll_path = path; | |
194 *dll_version = version; | |
195 found = true; | |
196 } | |
197 } | |
198 return found; | |
199 } | |
200 | |
130 // Returns true if the Pepper |interface_name| is implemented by this browser. | 201 // Returns true if the Pepper |interface_name| is implemented by this browser. |
131 // It does not check if the interface is proxied. | 202 // It does not check if the interface is proxied. |
132 bool SupportsPepperInterface(const char* interface_name) { | 203 bool SupportsPepperInterface(const char* interface_name) { |
133 if (IsSupportedPepperInterface(interface_name)) | 204 if (IsSupportedPepperInterface(interface_name)) |
134 return true; | 205 return true; |
135 // The PDF interface is invisible to SupportsInterface() on the browser | 206 // The PDF interface is invisible to SupportsInterface() on the browser |
136 // process because it is provided using PpapiInterfaceFactoryManager. We need | 207 // process because it is provided using PpapiInterfaceFactoryManager. We need |
137 // to check for that as well. | 208 // to check for that as well. |
138 // TODO(cpu): make this more sane. | 209 // TODO(cpu): make this more sane. |
139 return (strcmp(interface_name, PPB_PDF_INTERFACE) == 0); | 210 return (strcmp(interface_name, PPB_PDF_INTERFACE) == 0); |
140 } | 211 } |
141 | 212 |
142 bool MakePepperFlashPluginInfo(const base::FilePath& flash_path, | 213 bool MakePepperFlashPluginInfo(const base::FilePath& flash_path, |
143 const Version& flash_version, | 214 const Version& flash_version, |
144 bool out_of_process, | 215 bool out_of_process, |
216 bool is_debugger, | |
145 content::PepperPluginInfo* plugin_info) { | 217 content::PepperPluginInfo* plugin_info) { |
146 if (!flash_version.IsValid()) | 218 if (!flash_version.IsValid()) |
147 return false; | 219 return false; |
148 const std::vector<uint16> ver_nums = flash_version.components(); | 220 const std::vector<uint16> ver_nums = flash_version.components(); |
149 if (ver_nums.size() < 3) | 221 if (ver_nums.size() < 3) |
150 return false; | 222 return false; |
151 | 223 |
152 plugin_info->is_internal = false; | 224 plugin_info->is_internal = false; |
153 plugin_info->is_out_of_process = out_of_process; | 225 plugin_info->is_out_of_process = out_of_process; |
154 plugin_info->path = flash_path; | 226 plugin_info->path = flash_path; |
155 plugin_info->name = content::kFlashPluginName; | 227 plugin_info->name = content::kFlashPluginName; |
156 plugin_info->permissions = kPepperFlashPermissions; | 228 plugin_info->permissions = kPepperFlashPermissions; |
157 | 229 |
158 // The description is like "Shockwave Flash 10.2 r154". | 230 // The description is like "Shockwave Flash 10.2 r154". |
159 plugin_info->description = base::StringPrintf("%s %d.%d r%d", | 231 plugin_info->description = base::StringPrintf("%s %d.%d r%d", |
160 content::kFlashPluginName, ver_nums[0], ver_nums[1], ver_nums[2]); | 232 content::kFlashPluginName, ver_nums[0], ver_nums[1], ver_nums[2]); |
233 if (is_debugger) { | |
234 plugin_info->description += " Debug"; | |
235 } | |
161 | 236 |
162 plugin_info->version = flash_version.GetString(); | 237 plugin_info->version = flash_version.GetString(); |
163 | 238 |
164 content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType, | 239 content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType, |
165 content::kFlashPluginSwfExtension, | 240 content::kFlashPluginSwfExtension, |
166 content::kFlashPluginName); | 241 content::kFlashPluginName); |
167 plugin_info->mime_types.push_back(swf_mime_type); | 242 plugin_info->mime_types.push_back(swf_mime_type); |
168 content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType, | 243 content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType, |
169 content::kFlashPluginSplExtension, | 244 content::kFlashPluginSplExtension, |
170 content::kFlashPluginName); | 245 content::kFlashPluginName); |
171 plugin_info->mime_types.push_back(spl_mime_type); | 246 plugin_info->mime_types.push_back(spl_mime_type); |
172 return true; | 247 return true; |
173 } | 248 } |
174 | 249 |
175 bool IsPepperFlash(const content::WebPluginInfo& plugin) { | 250 bool IsPepperFlash(const content::WebPluginInfo& plugin) { |
176 // We try to recognize Pepper Flash by the following criteria: | 251 // We try to recognize Pepper Flash by the following criteria: |
177 // * It is a Pepper plug-in. | 252 // * It is a Pepper plug-in. |
178 // * It has the special Flash permissions. | 253 // * It has the special Flash permissions. |
179 return plugin.is_pepper_plugin() && | 254 return plugin.is_pepper_plugin() && |
180 (plugin.pepper_permissions & ppapi::PERMISSION_FLASH); | 255 (plugin.pepper_permissions & ppapi::PERMISSION_FLASH); |
181 } | 256 } |
182 | 257 |
183 void RegisterPepperFlashWithChrome(const base::FilePath& path, | 258 void RegisterPepperFlashWithChrome(const base::FilePath& path, |
184 const Version& version) { | 259 const Version& version, |
260 bool is_debugger) { | |
185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
186 content::PepperPluginInfo plugin_info; | 262 content::PepperPluginInfo plugin_info; |
187 if (!MakePepperFlashPluginInfo(path, version, true, &plugin_info)) | 263 if (!MakePepperFlashPluginInfo( |
264 path, version, true, is_debugger, &plugin_info)) | |
188 return; | 265 return; |
189 | 266 |
190 std::vector<content::WebPluginInfo> plugins; | 267 // If this is the non-debugger version, we enumerate any installed versions of |
191 PluginService::GetInstance()->GetInternalPlugins(&plugins); | 268 // pepper flash to make sure we only replace the installed version with a |
192 for (std::vector<content::WebPluginInfo>::const_iterator it = plugins.begin(); | 269 // newer version. |
193 it != plugins.end(); ++it) { | 270 if (!is_debugger) { |
194 if (!IsPepperFlash(*it)) | 271 std::vector<content::WebPluginInfo> plugins; |
195 continue; | 272 PluginService::GetInstance()->GetInternalPlugins(&plugins); |
273 for (std::vector<content::WebPluginInfo>::const_iterator it = | |
274 plugins.begin(); | |
275 it != plugins.end(); | |
276 ++it) { | |
277 if (!IsPepperFlash(*it)) | |
278 continue; | |
196 | 279 |
197 // Do it only if the version we're trying to register is newer. | 280 // Do it only if the version we're trying to register is newer. |
198 Version registered_version(base::UTF16ToUTF8(it->version)); | 281 Version registered_version(base::UTF16ToUTF8(it->version)); |
199 if (registered_version.IsValid() && | 282 if (registered_version.IsValid() && |
200 version.CompareTo(registered_version) <= 0) { | 283 version.CompareTo(registered_version) <= 0) { |
201 return; | 284 return; |
285 } | |
286 | |
287 // If the version is newer, remove the old one first. | |
288 PluginService::GetInstance()->UnregisterInternalPlugin(it->path); | |
289 break; | |
202 } | 290 } |
203 | |
204 // If the version is newer, remove the old one first. | |
205 PluginService::GetInstance()->UnregisterInternalPlugin(it->path); | |
206 break; | |
207 } | 291 } |
208 | 292 |
293 // We only ask for registration at the beginning for the non-debugger plugin, | |
294 // that way the debugger plugin doesn't automatically clobber the built-in or | |
295 // updated non-debugger version. | |
209 PluginService::GetInstance()->RegisterInternalPlugin( | 296 PluginService::GetInstance()->RegisterInternalPlugin( |
210 plugin_info.ToWebPluginInfo(), true); | 297 plugin_info.ToWebPluginInfo(), !is_debugger); |
211 PluginService::GetInstance()->RefreshPlugins(); | 298 PluginService::GetInstance()->RefreshPlugins(); |
212 } | 299 } |
213 | 300 |
214 // Returns true if this browser implements one of the interfaces given in | 301 // Returns true if this browser implements one of the interfaces given in |
215 // |interface_string|, which is a '|'-separated string of interface names. | 302 // |interface_string|, which is a '|'-separated string of interface names. |
216 bool CheckPepperFlashInterfaceString(const std::string& interface_string) { | 303 bool CheckPepperFlashInterfaceString(const std::string& interface_string) { |
217 std::vector<std::string> interface_names; | 304 std::vector<std::string> interface_names; |
218 base::SplitString(interface_string, '|', &interface_names); | 305 base::SplitString(interface_string, '|', &interface_names); |
219 for (size_t i = 0; i < interface_names.size(); i++) { | 306 for (size_t i = 0; i < interface_names.size(); i++) { |
220 if (SupportsPepperInterface(interface_names[i].c_str())) | 307 if (SupportsPepperInterface(interface_names[i].c_str())) |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
289 if (base::PathExists(path)) | 376 if (base::PathExists(path)) |
290 return false; | 377 return false; |
291 if (!base::Move(unpack_path, path)) | 378 if (!base::Move(unpack_path, path)) |
292 return false; | 379 return false; |
293 // Installation is done. Now tell the rest of chrome. Both the path service | 380 // Installation is done. Now tell the rest of chrome. Both the path service |
294 // and to the plugin service. | 381 // and to the plugin service. |
295 current_version_ = version; | 382 current_version_ = version; |
296 PathService::Override(chrome::DIR_PEPPER_FLASH_PLUGIN, path); | 383 PathService::Override(chrome::DIR_PEPPER_FLASH_PLUGIN, path); |
297 path = path.Append(chrome::kPepperFlashPluginFilename); | 384 path = path.Append(chrome::kPepperFlashPluginFilename); |
298 BrowserThread::PostTask( | 385 BrowserThread::PostTask( |
299 BrowserThread::UI, FROM_HERE, | 386 BrowserThread::UI, |
300 base::Bind(&RegisterPepperFlashWithChrome, path, version)); | 387 FROM_HERE, |
388 base::Bind(&RegisterPepperFlashWithChrome, path, version, false)); | |
301 return true; | 389 return true; |
302 } | 390 } |
303 | 391 |
304 bool PepperFlashComponentInstaller::GetInstalledFile( | 392 bool PepperFlashComponentInstaller::GetInstalledFile( |
305 const std::string& file, base::FilePath* installed_file) { | 393 const std::string& file, base::FilePath* installed_file) { |
306 return false; | 394 return false; |
307 } | 395 } |
308 | 396 |
309 bool CheckPepperFlashManifest(const base::DictionaryValue& manifest, | 397 bool CheckPepperFlashManifest(const base::DictionaryValue& manifest, |
310 Version* version_out) { | 398 Version* version_out) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
370 return; | 458 return; |
371 } | 459 } |
372 } | 460 } |
373 | 461 |
374 Version version(kNullVersion); | 462 Version version(kNullVersion); |
375 std::vector<base::FilePath> older_dirs; | 463 std::vector<base::FilePath> older_dirs; |
376 if (GetPepperFlashDirectory(&path, &version, &older_dirs)) { | 464 if (GetPepperFlashDirectory(&path, &version, &older_dirs)) { |
377 path = path.Append(chrome::kPepperFlashPluginFilename); | 465 path = path.Append(chrome::kPepperFlashPluginFilename); |
378 if (base::PathExists(path)) { | 466 if (base::PathExists(path)) { |
379 BrowserThread::PostTask( | 467 BrowserThread::PostTask( |
380 BrowserThread::UI, FROM_HERE, | 468 BrowserThread::UI, |
381 base::Bind(&RegisterPepperFlashWithChrome, path, version)); | 469 FROM_HERE, |
470 base::Bind(&RegisterPepperFlashWithChrome, path, version, false)); | |
382 } else { | 471 } else { |
383 version = Version(kNullVersion); | 472 version = Version(kNullVersion); |
384 } | 473 } |
385 } | 474 } |
386 | 475 |
387 BrowserThread::PostTask( | 476 BrowserThread::PostTask( |
388 BrowserThread::UI, FROM_HERE, | 477 BrowserThread::UI, FROM_HERE, |
389 base::Bind(&FinishPepperFlashUpdateRegistration, cus, version)); | 478 base::Bind(&FinishPepperFlashUpdateRegistration, cus, version)); |
390 | 479 |
391 // Remove older versions of Pepper Flash. | 480 // Remove older versions of Pepper Flash. |
392 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); | 481 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); |
393 iter != older_dirs.end(); ++iter) { | 482 iter != older_dirs.end(); ++iter) { |
394 base::DeleteFile(*iter, true); | 483 base::DeleteFile(*iter, true); |
395 } | 484 } |
485 | |
486 // Check for Debugging version of Flash and register if present. | |
487 base::FilePath debugger_path; | |
488 Version debugger_version(kNullVersion); | |
489 if (GetPepperFlashDebuggerPath(&debugger_path, &debugger_version)) { | |
490 BrowserThread::PostTask(BrowserThread::UI, | |
491 FROM_HERE, | |
492 base::Bind(&RegisterPepperFlashWithChrome, | |
493 debugger_path, | |
494 debugger_version, | |
495 true)); | |
496 } | |
396 } | 497 } |
397 #endif // defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 498 #endif // defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) |
398 | 499 |
399 } // namespace | 500 } // namespace |
400 | 501 |
401 void RegisterPepperFlashComponent(ComponentUpdateService* cus) { | 502 void RegisterPepperFlashComponent(ComponentUpdateService* cus) { |
402 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 503 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) |
403 // Component updated flash supersedes bundled flash therefore if that one | 504 // Component updated flash supersedes bundled flash therefore if that one |
404 // is disabled then this one should never install. | 505 // is disabled then this one should never install. |
405 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); | 506 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); |
406 if (cmd_line->HasSwitch(switches::kDisableBundledPpapiFlash)) | 507 if (cmd_line->HasSwitch(switches::kDisableBundledPpapiFlash)) |
407 return; | 508 return; |
408 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 509 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
409 base::Bind(&StartPepperFlashUpdateRegistration, cus)); | 510 base::Bind(&StartPepperFlashUpdateRegistration, cus)); |
410 #endif | 511 #endif |
411 } | 512 } |
412 | 513 |
413 } // namespace component_updater | 514 } // namespace component_updater |
414 | 515 |
OLD | NEW |