 Chromium Code Reviews
 Chromium Code Reviews Issue 893823002:
  Register system Pepper Flash plugin if no packaged Pepper plugin is found.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 893823002:
  Register system Pepper Flash plugin if no packaged Pepper plugin is found.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| 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 <stdint.h> | 5 #include <stdint.h> | 
| 6 #include <string.h> | 6 #include <string.h> | 
| 7 #include <vector> | 7 #include <vector> | 
| 8 | 8 | 
| 9 #include "base/base_paths.h" | 9 #include "base/base_paths.h" | 
| 10 #include "base/bind.h" | 10 #include "base/bind.h" | 
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 | 83 | 
| 84 // The base directory on Windows looks like: | 84 // The base directory on Windows looks like: | 
| 85 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\. | 85 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\. | 
| 86 base::FilePath GetPepperFlashBaseDirectory() { | 86 base::FilePath GetPepperFlashBaseDirectory() { | 
| 87 base::FilePath result; | 87 base::FilePath result; | 
| 88 PathService::Get(chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, &result); | 88 PathService::Get(chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, &result); | 
| 89 return result; | 89 return result; | 
| 90 } | 90 } | 
| 91 | 91 | 
| 92 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 92 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 
| 93 // Install directory for pepper flash debugger dlls will be like | |
| 94 // c:\windows\system32\macromed\flash\, or basically the Macromed\Flash | |
| 95 // subdirectory of the Windows system directory. | |
| 96 base::FilePath GetPepperFlashDebuggerDirectory() { | |
| 97 base::FilePath result; | |
| 98 PathService::Get(chrome::DIR_PEPPER_FLASH_DEBUGGER_PLUGIN, &result); | |
| 99 return result; | |
| 100 } | |
| 101 | |
| 102 // Pepper Flash plugins have the version encoded in the path itself | 93 // Pepper Flash plugins have the version encoded in the path itself | 
| 103 // so we need to enumerate the directories to find the full path. | 94 // so we need to enumerate the directories to find the full path. | 
| 104 // On success, |latest_dir| returns something like: | 95 // On success, |latest_dir| returns something like: | 
| 105 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\10.3.44.555\. | 96 // <profile>\AppData\Local\Google\Chrome\User Data\PepperFlash\10.3.44.555\. | 
| 106 // |latest_version| returns the corresponding version number. |older_dirs| | 97 // |latest_version| returns the corresponding version number. |older_dirs| | 
| 107 // returns directories of all older versions. | 98 // returns directories of all older versions. | 
| 108 bool GetPepperFlashDirectory(base::FilePath* latest_dir, | 99 bool GetPepperFlashDirectory(base::FilePath* latest_dir, | 
| 109 Version* latest_version, | 100 Version* latest_version, | 
| 110 std::vector<base::FilePath>* older_dirs) { | 101 std::vector<base::FilePath>* older_dirs) { | 
| 111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 
| (...skipping 15 matching lines...) Expand all Loading... | |
| 127 older_dirs->push_back(path); | 118 older_dirs->push_back(path); | 
| 128 } | 119 } | 
| 129 } else { | 120 } else { | 
| 130 *latest_dir = path; | 121 *latest_dir = path; | 
| 131 *latest_version = version; | 122 *latest_version = version; | 
| 132 found = true; | 123 found = true; | 
| 133 } | 124 } | 
| 134 } | 125 } | 
| 135 return found; | 126 return found; | 
| 136 } | 127 } | 
| 137 | |
| 138 #if defined(OS_WIN) | |
| 139 const wchar_t kPepperFlashDebuggerDLLSearchString[] = | |
| 140 #if defined(ARCH_CPU_X86) | |
| 141 L"pepflashplayer32*.dll"; | |
| 142 #elif defined(ARCH_CPU_X86_64) | |
| 143 L"pepflashplayer64*.dll"; | |
| 144 #else | |
| 145 #error Unsupported Windows CPU architecture. | |
| 146 #endif // defined(ARCH_CPU_X86) | |
| 147 #endif // defined(OS_WIN) | |
| 148 | |
| 149 bool GetPepperFlashDebuggerPath(base::FilePath* dll_path, | |
| 150 Version* dll_version) { | |
| 151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 152 base::FilePath debugger_dir = GetPepperFlashDebuggerDirectory(); | |
| 153 // If path doesn't exist they simply don't have the flash debugger installed. | |
| 154 if (!base::PathExists(debugger_dir)) | |
| 155 return false; | |
| 156 | |
| 157 bool found = false; | |
| 158 #if defined(OS_WIN) | |
| 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().RemoveExtension().MaybeAsASCII()); | |
| 169 // file_name should now be basename_x_y_z. Split along '_' for version. | |
| 170 std::vector<std::string> components; | |
| 171 base::SplitString(file_name, '_', &components); | |
| 172 // Should have at least one version number. | |
| 173 if (components.size() <= 1) | |
| 174 continue; | |
| 175 // Meld version components back into a string, now separated by periods, so | |
| 176 // Version can parse it. | |
| 177 std::string version_string(components[1]); | |
| 178 for (size_t i = 2; i < components.size(); ++i) { | |
| 179 version_string += "." + components[i]; | |
| 180 } | |
| 181 Version version(version_string); | |
| 182 if (!version.IsValid()) | |
| 183 continue; | |
| 184 if (found) { | |
| 185 if (version.CompareTo(*dll_version) > 0) { | |
| 186 *dll_path = path; | |
| 187 *dll_version = version; | |
| 188 } | |
| 189 } else { | |
| 190 *dll_path = path; | |
| 191 *dll_version = version; | |
| 192 found = true; | |
| 193 } | |
| 194 } | |
| 195 #endif | |
| 196 return found; | |
| 197 } | |
| 198 #endif // defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 128 #endif // defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 
| 199 | 129 | 
| 200 // Returns true if the Pepper |interface_name| is implemented by this browser. | 130 // Returns true if the Pepper |interface_name| is implemented by this browser. | 
| 201 // It does not check if the interface is proxied. | 131 // It does not check if the interface is proxied. | 
| 202 bool SupportsPepperInterface(const char* interface_name) { | 132 bool SupportsPepperInterface(const char* interface_name) { | 
| 203 if (IsSupportedPepperInterface(interface_name)) | 133 if (IsSupportedPepperInterface(interface_name)) | 
| 204 return true; | 134 return true; | 
| 205 // The PDF interface is invisible to SupportsInterface() on the browser | 135 // The PDF interface is invisible to SupportsInterface() on the browser | 
| 206 // process because it is provided using PpapiInterfaceFactoryManager. We need | 136 // process because it is provided using PpapiInterfaceFactoryManager. We need | 
| 207 // to check for that as well. | 137 // to check for that as well. | 
| 208 // TODO(cpu): make this more sane. | 138 // TODO(cpu): make this more sane. | 
| 209 return (strcmp(interface_name, PPB_PDF_INTERFACE) == 0); | 139 return (strcmp(interface_name, PPB_PDF_INTERFACE) == 0); | 
| 210 } | 140 } | 
| 211 | 141 | 
| 212 bool MakePepperFlashPluginInfo(const base::FilePath& flash_path, | 142 bool MakePepperFlashPluginInfo(const base::FilePath& flash_path, | 
| 213 const Version& flash_version, | 143 const Version& flash_version, | 
| 214 bool out_of_process, | 144 bool out_of_process, | 
| 215 bool is_debugger, | |
| 216 content::PepperPluginInfo* plugin_info) { | 145 content::PepperPluginInfo* plugin_info) { | 
| 217 if (!flash_version.IsValid()) | 146 if (!flash_version.IsValid()) | 
| 218 return false; | 147 return false; | 
| 219 const std::vector<uint16_t> ver_nums = flash_version.components(); | 148 const std::vector<uint16_t> ver_nums = flash_version.components(); | 
| 220 if (ver_nums.size() < 3) | 149 if (ver_nums.size() < 3) | 
| 221 return false; | 150 return false; | 
| 222 | 151 | 
| 223 plugin_info->is_internal = false; | 152 plugin_info->is_internal = false; | 
| 224 plugin_info->is_out_of_process = out_of_process; | 153 plugin_info->is_out_of_process = out_of_process; | 
| 225 plugin_info->path = flash_path; | 154 plugin_info->path = flash_path; | 
| (...skipping 22 matching lines...) Expand all Loading... | |
| 248 | 177 | 
| 249 bool IsPepperFlash(const content::WebPluginInfo& plugin) { | 178 bool IsPepperFlash(const content::WebPluginInfo& plugin) { | 
| 250 // We try to recognize Pepper Flash by the following criteria: | 179 // We try to recognize Pepper Flash by the following criteria: | 
| 251 // * It is a Pepper plug-in. | 180 // * It is a Pepper plug-in. | 
| 252 // * It has the special Flash permissions. | 181 // * It has the special Flash permissions. | 
| 253 return plugin.is_pepper_plugin() && | 182 return plugin.is_pepper_plugin() && | 
| 254 (plugin.pepper_permissions & ppapi::PERMISSION_FLASH); | 183 (plugin.pepper_permissions & ppapi::PERMISSION_FLASH); | 
| 255 } | 184 } | 
| 256 | 185 | 
| 257 void RegisterPepperFlashWithChrome(const base::FilePath& path, | 186 void RegisterPepperFlashWithChrome(const base::FilePath& path, | 
| 258 const Version& version, | 187 const Version& version) { | 
| 259 bool is_debugger) { | |
| 260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
| 261 content::PepperPluginInfo plugin_info; | 189 content::PepperPluginInfo plugin_info; | 
| 262 if (!MakePepperFlashPluginInfo( | 190 if (!MakePepperFlashPluginInfo(path, version, true, &plugin_info)) | 
| 263 path, version, true, is_debugger, &plugin_info)) | |
| 264 return; | 191 return; | 
| 265 | 192 | 
| 266 // If this is the non-debugger version, we enumerate any installed versions of | 193 std::vector<content::WebPluginInfo> plugins; | 
| 267 // pepper flash to make sure we only replace the installed version with a | 194 PluginService::GetInstance()->GetInternalPlugins(&plugins); | 
| 268 // newer version. | 195 for (std::vector<content::WebPluginInfo>::const_iterator it = | 
| 269 if (!is_debugger) { | 196 plugins.begin(); | 
| 270 std::vector<content::WebPluginInfo> plugins; | 197 it != plugins.end(); | 
| 271 PluginService::GetInstance()->GetInternalPlugins(&plugins); | 198 ++it) { | 
| 272 for (std::vector<content::WebPluginInfo>::const_iterator it = | 199 if (!IsPepperFlash(*it)) | 
| 273 plugins.begin(); | 200 continue; | 
| 274 it != plugins.end(); | |
| 275 ++it) { | |
| 276 if (!IsPepperFlash(*it)) | |
| 277 continue; | |
| 278 | 201 | 
| 279 // Do it only if the version we're trying to register is newer. | 202 // Do it only if the version we're trying to register is newer. | 
| 280 Version registered_version(base::UTF16ToUTF8(it->version)); | 203 Version registered_version(base::UTF16ToUTF8(it->version)); | 
| 281 if (registered_version.IsValid() && | 204 if (registered_version.IsValid() && | 
| 282 version.CompareTo(registered_version) <= 0) { | 205 version.CompareTo(registered_version) <= 0) { | 
| 283 return; | 206 return; | 
| 284 } | 207 } | 
| 285 | 208 | 
| 286 // If the version is newer, remove the old one first. | 209 // If the version is newer, remove the old one first. | 
| 287 PluginService::GetInstance()->UnregisterInternalPlugin(it->path); | 210 PluginService::GetInstance()->UnregisterInternalPlugin(it->path); | 
| 288 break; | 211 break; | 
| 289 } | |
| 290 } | 212 } | 
| 291 | 213 | 
| 292 // We only ask for registration at the beginning for the non-debugger plugin, | |
| 293 // that way the debugger plugin doesn't automatically clobber the built-in or | |
| 294 // updated non-debugger version. | |
| 295 PluginService::GetInstance()->RegisterInternalPlugin( | 214 PluginService::GetInstance()->RegisterInternalPlugin( | 
| 296 plugin_info.ToWebPluginInfo(), !is_debugger); | 215 plugin_info.ToWebPluginInfo(), true); | 
| 297 PluginService::GetInstance()->RefreshPlugins(); | 216 PluginService::GetInstance()->RefreshPlugins(); | 
| 298 } | 217 } | 
| 299 | 218 | 
| 300 // Returns true if this browser implements one of the interfaces given in | 219 // Returns true if this browser implements one of the interfaces given in | 
| 301 // |interface_string|, which is a '|'-separated string of interface names. | 220 // |interface_string|, which is a '|'-separated string of interface names. | 
| 302 bool CheckPepperFlashInterfaceString(const std::string& interface_string) { | 221 bool CheckPepperFlashInterfaceString(const std::string& interface_string) { | 
| 303 std::vector<std::string> interface_names; | 222 std::vector<std::string> interface_names; | 
| 304 base::SplitString(interface_string, '|', &interface_names); | 223 base::SplitString(interface_string, '|', &interface_names); | 
| 305 for (size_t i = 0; i < interface_names.size(); i++) { | 224 for (size_t i = 0; i < interface_names.size(); i++) { | 
| 
cpu_(ooo_6.6-7.5)
2015/02/03 18:58:03
this code needs to be run before we decide to regi
 
Will Harris
2015/02/16 03:39:42
Done.
 | |
| 306 if (SupportsPepperInterface(interface_names[i].c_str())) | 225 if (SupportsPepperInterface(interface_names[i].c_str())) | 
| 307 return true; | 226 return true; | 
| 308 } | 227 } | 
| 309 return false; | 228 return false; | 
| 310 } | 229 } | 
| 311 | 230 | 
| 312 // Returns true if this browser implements all the interfaces that Flash | 231 // Returns true if this browser implements all the interfaces that Flash | 
| 313 // specifies in its component installer manifest. | 232 // specifies in its component installer manifest. | 
| 314 bool CheckPepperFlashInterfaces(const base::DictionaryValue& manifest) { | 233 bool CheckPepperFlashInterfaces(const base::DictionaryValue& manifest) { | 
| 315 const base::ListValue* interface_list = NULL; | 234 const base::ListValue* interface_list = NULL; | 
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 if (!base::Move(unpack_path, path)) | 296 if (!base::Move(unpack_path, path)) | 
| 378 return false; | 297 return false; | 
| 379 // Installation is done. Now tell the rest of chrome. Both the path service | 298 // Installation is done. Now tell the rest of chrome. Both the path service | 
| 380 // and to the plugin service. | 299 // and to the plugin service. | 
| 381 current_version_ = version; | 300 current_version_ = version; | 
| 382 PathService::Override(chrome::DIR_PEPPER_FLASH_PLUGIN, path); | 301 PathService::Override(chrome::DIR_PEPPER_FLASH_PLUGIN, path); | 
| 383 path = path.Append(chrome::kPepperFlashPluginFilename); | 302 path = path.Append(chrome::kPepperFlashPluginFilename); | 
| 384 BrowserThread::PostTask( | 303 BrowserThread::PostTask( | 
| 385 BrowserThread::UI, | 304 BrowserThread::UI, | 
| 386 FROM_HERE, | 305 FROM_HERE, | 
| 387 base::Bind(&RegisterPepperFlashWithChrome, path, version, false)); | 306 base::Bind(&RegisterPepperFlashWithChrome, path, version)); | 
| 388 return true; | 307 return true; | 
| 389 } | 308 } | 
| 390 | 309 | 
| 391 bool PepperFlashComponentInstaller::GetInstalledFile( | 310 bool PepperFlashComponentInstaller::GetInstalledFile( | 
| 392 const std::string& file, | 311 const std::string& file, | 
| 393 base::FilePath* installed_file) { | 312 base::FilePath* installed_file) { | 
| 394 return false; | 313 return false; | 
| 395 } | 314 } | 
| 396 | 315 | 
| 397 bool CheckPepperFlashManifest(const base::DictionaryValue& manifest, | 316 bool CheckPepperFlashManifest(const base::DictionaryValue& manifest, | 
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 460 } | 379 } | 
| 461 | 380 | 
| 462 Version version(kNullVersion); | 381 Version version(kNullVersion); | 
| 463 std::vector<base::FilePath> older_dirs; | 382 std::vector<base::FilePath> older_dirs; | 
| 464 if (GetPepperFlashDirectory(&path, &version, &older_dirs)) { | 383 if (GetPepperFlashDirectory(&path, &version, &older_dirs)) { | 
| 465 path = path.Append(chrome::kPepperFlashPluginFilename); | 384 path = path.Append(chrome::kPepperFlashPluginFilename); | 
| 466 if (base::PathExists(path)) { | 385 if (base::PathExists(path)) { | 
| 467 BrowserThread::PostTask( | 386 BrowserThread::PostTask( | 
| 468 BrowserThread::UI, | 387 BrowserThread::UI, | 
| 469 FROM_HERE, | 388 FROM_HERE, | 
| 470 base::Bind(&RegisterPepperFlashWithChrome, path, version, false)); | 389 base::Bind(&RegisterPepperFlashWithChrome, path, version)); | 
| 471 } else { | 390 } else { | 
| 472 version = Version(kNullVersion); | 391 version = Version(kNullVersion); | 
| 473 } | 392 } | 
| 474 } | 393 } | 
| 475 | 394 | 
| 476 BrowserThread::PostTask( | 395 BrowserThread::PostTask( | 
| 477 BrowserThread::UI, | 396 BrowserThread::UI, | 
| 478 FROM_HERE, | 397 FROM_HERE, | 
| 479 base::Bind(&FinishPepperFlashUpdateRegistration, cus, version)); | 398 base::Bind(&FinishPepperFlashUpdateRegistration, cus, version)); | 
| 480 | 399 | 
| 481 // Remove older versions of Pepper Flash. | 400 // Remove older versions of Pepper Flash. | 
| 482 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); | 401 for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); | 
| 483 iter != older_dirs.end(); | 402 iter != older_dirs.end(); | 
| 484 ++iter) { | 403 ++iter) { | 
| 485 base::DeleteFile(*iter, true); | 404 base::DeleteFile(*iter, true); | 
| 486 } | 405 } | 
| 487 | |
| 488 // Check for Debugging version of Flash and register if present. | |
| 489 base::FilePath debugger_path; | |
| 490 Version debugger_version(kNullVersion); | |
| 491 if (GetPepperFlashDebuggerPath(&debugger_path, &debugger_version)) { | |
| 492 BrowserThread::PostTask(BrowserThread::UI, | |
| 493 FROM_HERE, | |
| 494 base::Bind(&RegisterPepperFlashWithChrome, | |
| 495 debugger_path, | |
| 496 debugger_version, | |
| 497 true)); | |
| 498 } | |
| 499 } | 406 } | 
| 500 #endif // defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 407 #endif // defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 
| 501 | 408 | 
| 502 } // namespace | 409 } // namespace | 
| 503 | 410 | 
| 504 void RegisterPepperFlashComponent(ComponentUpdateService* cus) { | 411 void RegisterPepperFlashComponent(ComponentUpdateService* cus) { | 
| 505 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 412 #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_LINUX) | 
| 506 // Component updated flash supersedes bundled flash therefore if that one | 413 // Component updated flash supersedes bundled flash therefore if that one | 
| 507 // is disabled then this one should never install. | 414 // is disabled then this one should never install. | 
| 508 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | 415 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | 
| 509 if (cmd_line->HasSwitch(switches::kDisableBundledPpapiFlash)) | 416 if (cmd_line->HasSwitch(switches::kDisableBundledPpapiFlash)) | 
| 510 return; | 417 return; | 
| 511 BrowserThread::PostTask(BrowserThread::FILE, | 418 BrowserThread::PostTask(BrowserThread::FILE, | 
| 512 FROM_HERE, | 419 FROM_HERE, | 
| 513 base::Bind(&StartPepperFlashUpdateRegistration, cus)); | 420 base::Bind(&StartPepperFlashUpdateRegistration, cus)); | 
| 514 #endif | 421 #endif | 
| 515 } | 422 } | 
| 516 | 423 | 
| 517 } // namespace component_updater | 424 } // namespace component_updater | 
| OLD | NEW |