This source file includes following definitions.
- Create
- GetSupportedPlugins
- resource_context_
- Init
- InitOnIOThread
- OnTimeout
- ID
- OffTheRecord
- GetResourceContext
- SetPluginInfo
- OnFoundPluginProcessHost
- OnSentPluginChannelRequest
- OnChannelOpened
- OnError
- GetPpapiChannelInfo
- OnPpapiChannelOpened
- OnMessageReceived
- OnChannelError
- event
- CreatePpapiClearSiteDataMsg
- ConnectToChannel
- OnPpapiClearSiteDataResult
- OnClearSiteDataResult
- SignalDone
- browser_context_
- StartRemoving
#include "content/browser/plugin_data_remover_impl.h"
#include <limits>
#include "base/bind.h"
#include "base/metrics/histogram.h"
#include "base/sequenced_task_runner_helpers.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/version.h"
#include "content/browser/plugin_process_host.h"
#include "content/browser/plugin_service_impl.h"
#include "content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/plugin_process_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/pepper_plugin_info.h"
#include "ppapi/proxy/ppapi_messages.h"
namespace content {
namespace {
const char kMinFlashVersion[] = "10.3";
const int64 kRemovalTimeoutMs = 10000;
const uint64 kClearAllData = 0;
}
PluginDataRemover* PluginDataRemover::Create(BrowserContext* browser_context) {
return new PluginDataRemoverImpl(browser_context);
}
void PluginDataRemover::GetSupportedPlugins(
std::vector<WebPluginInfo>* supported_plugins) {
bool allow_wildcard = false;
std::vector<WebPluginInfo> plugins;
PluginService::GetInstance()->GetPluginInfoArray(
GURL(), kFlashPluginSwfMimeType, allow_wildcard, &plugins, NULL);
Version min_version(kMinFlashVersion);
for (std::vector<WebPluginInfo>::iterator it = plugins.begin();
it != plugins.end(); ++it) {
Version version;
WebPluginInfo::CreateVersionFromString(it->version, &version);
if (version.IsValid() && min_version.CompareTo(version) == -1)
supported_plugins->push_back(*it);
}
}
class PluginDataRemoverImpl::Context
: public PluginProcessHost::Client,
public PpapiPluginProcessHost::BrokerClient,
public IPC::Listener,
public base::RefCountedThreadSafe<Context,
BrowserThread::DeleteOnIOThread> {
public:
Context(base::Time begin_time, BrowserContext* browser_context)
: event_(new base::WaitableEvent(true, false)),
begin_time_(begin_time),
is_removing_(false),
browser_context_path_(browser_context->GetPath()),
resource_context_(browser_context->GetResourceContext()) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
void Init(const std::string& mime_type) {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&Context::InitOnIOThread, this, mime_type));
BrowserThread::PostDelayedTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&Context::OnTimeout, this),
base::TimeDelta::FromMilliseconds(kRemovalTimeoutMs));
}
void InitOnIOThread(const std::string& mime_type) {
PluginServiceImpl* plugin_service = PluginServiceImpl::GetInstance();
std::vector<WebPluginInfo> plugins;
plugin_service->GetPluginInfoArray(
GURL(), mime_type, false, &plugins, NULL);
base::FilePath plugin_path;
if (!plugins.empty())
plugin_path = plugins[0].path;
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
remove_start_time_ = base::Time::Now();
is_removing_ = true;
AddRef();
PepperPluginInfo* pepper_info =
plugin_service->GetRegisteredPpapiPluginInfo(plugin_path);
if (pepper_info) {
plugin_name_ = pepper_info->name;
plugin_service->OpenChannelToPpapiBroker(0, plugin_path, this);
} else {
plugin_service->OpenChannelToNpapiPlugin(
0, 0, GURL(), GURL(), mime_type, this);
}
}
void OnTimeout() {
LOG_IF(ERROR, is_removing_) << "Timed out";
SignalDone();
}
virtual int ID() OVERRIDE {
return ChildProcessHostImpl::GenerateChildProcessUniqueId();
}
virtual bool OffTheRecord() OVERRIDE {
return false;
}
virtual ResourceContext* GetResourceContext() OVERRIDE {
return resource_context_;
}
virtual void SetPluginInfo(const WebPluginInfo& info) OVERRIDE {}
virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {}
virtual void OnSentPluginChannelRequest() OVERRIDE {}
virtual void OnChannelOpened(const IPC::ChannelHandle& handle) OVERRIDE {
ConnectToChannel(handle, false);
Release();
}
virtual void OnError() OVERRIDE {
LOG(ERROR) << "Couldn't open plugin channel";
SignalDone();
Release();
}
virtual void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
int* renderer_id) OVERRIDE {
*renderer_handle = base::kNullProcessHandle;
*renderer_id = 0;
}
virtual void OnPpapiChannelOpened(
const IPC::ChannelHandle& channel_handle,
base::ProcessId ,
int ) OVERRIDE {
if (!channel_handle.name.empty())
ConnectToChannel(channel_handle, true);
Release();
}
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
IPC_BEGIN_MESSAGE_MAP(Context, message)
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ClearSiteDataResult,
OnClearSiteDataResult)
IPC_MESSAGE_HANDLER(PpapiHostMsg_ClearSiteDataResult,
OnPpapiClearSiteDataResult)
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP()
return true;
}
virtual void OnChannelError() OVERRIDE {
if (is_removing_) {
NOTREACHED() << "Channel error";
SignalDone();
}
}
base::WaitableEvent* event() { return event_.get(); }
private:
friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
friend class base::DeleteHelper<Context>;
virtual ~Context() {}
IPC::Message* CreatePpapiClearSiteDataMsg(uint64 max_age) {
base::FilePath profile_path =
PepperFlashFileMessageFilter::GetDataDirName(browser_context_path_);
#if defined(OS_WIN)
base::FilePath plugin_data_path =
profile_path.Append(base::FilePath(base::UTF8ToUTF16(plugin_name_)));
#else
base::FilePath plugin_data_path =
profile_path.Append(base::FilePath(plugin_name_));
#endif
return new PpapiMsg_ClearSiteData(0u, plugin_data_path, std::string(),
kClearAllData, max_age);
}
void ConnectToChannel(const IPC::ChannelHandle& handle, bool is_ppapi) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!is_removing_)
return;
DCHECK(!channel_.get());
channel_.reset(new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this));
if (!channel_->Connect()) {
NOTREACHED() << "Couldn't connect to plugin";
SignalDone();
return;
}
uint64 max_age = begin_time_.is_null() ?
std::numeric_limits<uint64>::max() :
(base::Time::Now() - begin_time_).InSeconds();
IPC::Message* msg;
if (is_ppapi) {
msg = CreatePpapiClearSiteDataMsg(max_age);
} else {
msg = new PluginProcessMsg_ClearSiteData(
std::string(), kClearAllData, max_age);
}
if (!channel_->Send(msg)) {
NOTREACHED() << "Couldn't send ClearSiteData message";
SignalDone();
return;
}
}
void OnPpapiClearSiteDataResult(uint32 request_id, bool success) {
DCHECK_EQ(0u, request_id);
OnClearSiteDataResult(success);
}
void OnClearSiteDataResult(bool success) {
LOG_IF(ERROR, !success) << "ClearSiteData returned error";
UMA_HISTOGRAM_TIMES("ClearPluginData.time",
base::Time::Now() - remove_start_time_);
SignalDone();
}
void SignalDone() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (!is_removing_)
return;
is_removing_ = false;
event_->Signal();
}
scoped_ptr<base::WaitableEvent> event_;
base::Time remove_start_time_;
base::Time begin_time_;
bool is_removing_;
base::FilePath browser_context_path_;
ResourceContext* resource_context_;
std::string plugin_name_;
scoped_ptr<IPC::Channel> channel_;
};
PluginDataRemoverImpl::PluginDataRemoverImpl(BrowserContext* browser_context)
: mime_type_(kFlashPluginSwfMimeType),
browser_context_(browser_context) {
}
PluginDataRemoverImpl::~PluginDataRemoverImpl() {
}
base::WaitableEvent* PluginDataRemoverImpl::StartRemoving(
base::Time begin_time) {
DCHECK(!context_.get());
context_ = new Context(begin_time, browser_context_);
context_->Init(mime_type_);
return context_->event();
}
}