#include "chrome/browser/component_updater/flash_component_installer.h"
#include <algorithm>
#include "base/base_paths.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/component_updater/component_updater_service.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
#include "webkit/plugins/webplugininfo.h"
using content::BrowserThread;
using content::PluginService;
namespace {
const uint8 sha2_hash[] = {0x8c, 0xc3, 0x8b, 0xa7, 0x86, 0xe3, 0xc9, 0x1d,
0xd6, 0x0f, 0x14, 0x72, 0x7c, 0x87, 0x01, 0x16,
0xe2, 0x00, 0x6c, 0x98, 0xbc, 0xfb, 0x14, 0x1b,
0x5c, 0xcd, 0xff, 0x3d, 0xa3, 0x2e, 0x2c, 0x49};
const FilePath::CharType kFlashPluginFileName[] =
#if defined(OS_MACOSX)
FILE_PATH_LITERAL("Flash Player Plugin for Chrome.plugin");
#elif defined(OS_WIN)
FILE_PATH_LITERAL("gcswf32.dll");
#else
FILE_PATH_LITERAL("libgcflashplayer.so");
#endif
const char kNPAPIFlashManifestName[] = "NPAPIFlash";
const FilePath::CharType kNPAPIFlashBaseDirectory[] =
FILE_PATH_LITERAL("NPAPIFlash");
FilePath GetNPAPIFlashBaseDirectory() {
FilePath result;
PathService::Get(chrome::DIR_USER_DATA, &result);
return result.Append(kNPAPIFlashBaseDirectory);
}
std::string NormalizeVersion(const string16& version) {
std::string ascii_ver = UTF16ToASCII(version);
std::replace(ascii_ver.begin(), ascii_ver.end(), ',', '.');
return ascii_ver;
}
}
class NPAPIFlashComponentInstaller : public ComponentInstaller {
public:
explicit NPAPIFlashComponentInstaller(const Version& version);
virtual ~NPAPIFlashComponentInstaller() {}
virtual void OnUpdateError(int error) OVERRIDE;
virtual bool Install(base::DictionaryValue* manifest,
const FilePath& unpack_path) OVERRIDE;
private:
Version current_version_;
};
NPAPIFlashComponentInstaller::NPAPIFlashComponentInstaller(
const Version& version) : current_version_(version) {
DCHECK(version.IsValid());
}
void NPAPIFlashComponentInstaller::OnUpdateError(int error) {
NOTREACHED() << "NPAPI flash update error: " << error;
}
bool NPAPIFlashComponentInstaller::Install(base::DictionaryValue* manifest,
const FilePath& unpack_path) {
std::string name;
manifest->GetStringASCII("name", &name);
if (name != kNPAPIFlashManifestName)
return false;
std::string proposed_version;
manifest->GetStringASCII("version", &proposed_version);
Version version(proposed_version.c_str());
if (!version.IsValid())
return false;
if (current_version_.CompareTo(version) >= 0)
return false;
if (!file_util::PathExists(unpack_path.Append(kFlashPluginFileName)))
return false;
if (!file_util::Move(unpack_path, GetNPAPIFlashBaseDirectory()))
return false;
current_version_ = version;
PluginService::GetInstance()->RefreshPlugins();
return true;
}
void FinishFlashUpdateRegistration(ComponentUpdateService* cus,
const webkit::WebPluginInfo& info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
Version version(NormalizeVersion(info.version));
if (!version.IsValid()) {
NOTREACHED();
return;
}
CrxComponent flash;
flash.name = "npapi_flash";
flash.installer = new NPAPIFlashComponentInstaller(version);
flash.version = version;
flash.pk_hash.assign(sha2_hash, &sha2_hash[sizeof(sha2_hash)]);
if (cus->RegisterComponent(flash) != ComponentUpdateService::kOk) {
NOTREACHED() << "Flash component registration fail";
}
}
void StartFlashUpdateRegistration(ComponentUpdateService* cus,
const std::vector<webkit::WebPluginInfo>&) {
FilePath builtin_plugin_path;
if (!PathService::Get(chrome::FILE_FLASH_PLUGIN_EXISTING,
&builtin_plugin_path))
return;
FilePath updated_plugin_path =
GetNPAPIFlashBaseDirectory().Append(kFlashPluginFileName);
PluginService* plugins = PluginService::GetInstance();
webkit::WebPluginInfo plugin_info;
if (plugins->GetPluginInfoByPath(updated_plugin_path, &plugin_info)) {
DLOG(INFO) << "updated plugin overriding built-in flash";
return;
} else if (plugins->GetPluginInfoByPath(builtin_plugin_path, &plugin_info)) {
file_util::Delete(GetNPAPIFlashBaseDirectory(), true);
} else {
DLOG(WARNING) << "Strange flash npapi configuration";
return;
}
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&FinishFlashUpdateRegistration, cus, plugin_info));
}
void RegisterNPAPIFlashComponent(ComponentUpdateService* cus) {
#if !defined(OS_CHROMEOS)
FilePath path = GetNPAPIFlashBaseDirectory().Append(kFlashPluginFileName);
PluginService::GetInstance()->AddExtraPluginPath(path);
PluginService::GetInstance()->RefreshPlugins();
BrowserThread::PostDelayedTask(
BrowserThread::FILE,
FROM_HERE,
base::Bind(&PluginService::GetPlugins,
base::Unretained(PluginService::GetInstance()),
base::Bind(&StartFlashUpdateRegistration, cus)),
base::TimeDelta::FromSeconds(8));
#endif
}