| 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 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 | 84 |
| 85 // The base directory on Windows looks like: | 85 // The base directory on Windows looks like: |
| 86 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\. | 86 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\. |
| 87 base::FilePath GetPepperFlashBaseDirectory() { | 87 base::FilePath GetPepperFlashBaseDirectory() { |
| 88 base::FilePath result; | 88 base::FilePath result; |
| 89 PathService::Get(chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, &result); | 89 PathService::Get(chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, &result); |
| 90 return result; | 90 return result; |
| 91 } | 91 } |
| 92 | 92 |
| 93 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 93 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) |
| 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(chrome::DIR_PEPPER_FLASH_DEBUGGER_PLUGIN, &result); |
| 100 return result; |
| 101 } |
| 102 |
| 94 // Pepper Flash plugins have the version encoded in the path itself | 103 // Pepper Flash plugins have the version encoded in the path itself |
| 95 // so we need to enumerate the directories to find the full path. | 104 // so we need to enumerate the directories to find the full path. |
| 96 // On success, |latest_dir| returns something like: | 105 // On success, |latest_dir| returns something like: |
| 97 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\10.3.44.555\. | 106 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\10.3.44.555\. |
| 98 // |latest_version| returns the corresponding version number. |older_dirs| | 107 // |latest_version| returns the corresponding version number. |older_dirs| |
| 99 // returns directories of all older versions. | 108 // returns directories of all older versions. |
| 100 bool GetPepperFlashDirectory(base::FilePath* latest_dir, | 109 bool GetPepperFlashDirectory(base::FilePath* latest_dir, |
| 101 Version* latest_version, | 110 Version* latest_version, |
| 102 std::vector<base::FilePath>* older_dirs) { | 111 std::vector<base::FilePath>* older_dirs) { |
| 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 103 base::FilePath base_dir = GetPepperFlashBaseDirectory(); | 113 base::FilePath base_dir = GetPepperFlashBaseDirectory(); |
| 104 bool found = false; | 114 bool found = false; |
| 105 base::FileEnumerator | 115 base::FileEnumerator |
| 106 file_enumerator(base_dir, false, base::FileEnumerator::DIRECTORIES); | 116 file_enumerator(base_dir, false, base::FileEnumerator::DIRECTORIES); |
| 107 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); | 117 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); |
| 108 path = file_enumerator.Next()) { | 118 path = file_enumerator.Next()) { |
| 109 Version version(path.BaseName().MaybeAsASCII()); | 119 Version version(path.BaseName().MaybeAsASCII()); |
| 110 if (!version.IsValid()) | 120 if (!version.IsValid()) |
| 111 continue; | 121 continue; |
| 112 if (found) { | 122 if (found) { |
| 113 if (version.CompareTo(*latest_version) > 0) { | 123 if (version.CompareTo(*latest_version) > 0) { |
| 114 older_dirs->push_back(*latest_dir); | 124 older_dirs->push_back(*latest_dir); |
| 115 *latest_dir = path; | 125 *latest_dir = path; |
| 116 *latest_version = version; | 126 *latest_version = version; |
| 117 } else { | 127 } else { |
| 118 older_dirs->push_back(path); | 128 older_dirs->push_back(path); |
| 119 } | 129 } |
| 120 } else { | 130 } else { |
| 121 *latest_dir = path; | 131 *latest_dir = path; |
| 122 *latest_version = version; | 132 *latest_version = version; |
| 123 found = true; | 133 found = true; |
| 124 } | 134 } |
| 125 } | 135 } |
| 126 return found; | 136 return found; |
| 127 } | 137 } |
| 138 |
| 139 #if defined(OS_WIN) |
| 140 const wchar_t kPepperFlashDebuggerDLLSearchString[] = |
| 141 #if defined(ARCH_CPU_X86) |
| 142 L"pepflashplayer32*.dll"; |
| 143 #elif defined(ARCH_CPU_X86_64) |
| 144 L"pepflashplayer64*.dll"; |
| 145 #else |
| 146 #error Unsupported Windows CPU architecture. |
| 147 #endif // defined(ARCH_CPU_X86) |
| 148 #endif // defined(OS_WIN) |
| 149 |
| 150 bool GetPepperFlashDebuggerPath(base::FilePath* dll_path, |
| 151 Version* dll_version) { |
| 152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 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)) |
| 156 return false; |
| 157 |
| 158 bool found = false; |
| 159 #if defined(OS_WIN) |
| 160 // Enumerate any DLLs that match the appropriate pattern for this DLL, and |
| 161 // pick the highest version number we find. |
| 162 base::FileEnumerator file_enumerator(debugger_dir, |
| 163 false, |
| 164 base::FileEnumerator::FILES, |
| 165 kPepperFlashDebuggerDLLSearchString); |
| 166 for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); |
| 167 path = file_enumerator.Next()) { |
| 168 // Version number is embedded in file name like basename_x_y_z.dll. Extract. |
| 169 std::string file_name(path.BaseName().RemoveExtension().MaybeAsASCII()); |
| 170 // file_name should now be basename_x_y_z. Split along '_' for version. |
| 171 std::vector<std::string> components; |
| 172 base::SplitString(file_name, '_', &components); |
| 173 // Should have at least one version number. |
| 174 if (components.size() <= 1) |
| 175 continue; |
| 176 // Meld version components back into a string, now separated by periods, so |
| 177 // Version can parse it. |
| 178 std::string version_string(components[1]); |
| 179 for (size_t i = 2; i < components.size(); ++i) { |
| 180 version_string += "." + components[i]; |
| 181 } |
| 182 Version version(version_string); |
| 183 if (!version.IsValid()) |
| 184 continue; |
| 185 if (found) { |
| 186 if (version.CompareTo(*dll_version) > 0) { |
| 187 *dll_path = path; |
| 188 *dll_version = version; |
| 189 } |
| 190 } else { |
| 191 *dll_path = path; |
| 192 *dll_version = version; |
| 193 found = true; |
| 194 } |
| 195 } |
| 128 #endif | 196 #endif |
| 197 return found; |
| 198 } |
| 199 #endif // defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) |
| 129 | 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 |