| Index: content/browser/plugin_data_remover_impl.cc
|
| ===================================================================
|
| --- content/browser/plugin_data_remover_impl.cc (revision 110950)
|
| +++ content/browser/plugin_data_remover_impl.cc (working copy)
|
| @@ -8,6 +8,7 @@
|
| #include "base/metrics/histogram.h"
|
| #include "base/synchronization/waitable_event.h"
|
| #include "base/version.h"
|
| +#include "content/browser/plugin_process_host.h"
|
| #include "content/browser/plugin_service.h"
|
| #include "content/common/plugin_messages.h"
|
| #include "content/public/browser/browser_thread.h"
|
| @@ -54,137 +55,185 @@
|
|
|
| }
|
|
|
| -PluginDataRemoverImpl::PluginDataRemoverImpl(
|
| - const content::ResourceContext& resource_context)
|
| - : mime_type_(kFlashMimeType),
|
| - is_starting_process_(false),
|
| - is_removing_(false),
|
| - context_(resource_context),
|
| - event_(new base::WaitableEvent(true, false)),
|
| - channel_(NULL),
|
| - ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
|
| -}
|
| +class PluginDataRemoverImpl::Context
|
| + : public PluginProcessHost::Client,
|
| + public IPC::Channel::Listener,
|
| + public base::RefCountedThreadSafe<Context> {
|
| + public:
|
| + Context(const std::string& mime_type,
|
| + base::Time begin_time,
|
| + const content::ResourceContext& resource_context)
|
| + : event_(new base::WaitableEvent(true, false)),
|
| + begin_time_(begin_time),
|
| + is_removing_(false),
|
| + resource_context_(resource_context),
|
| + channel_(NULL) {
|
| + // Balanced in OnChannelOpened or OnError. Exactly one them will eventually
|
| + // be called, so we need to keep this object around until then.
|
| + AddRef();
|
| + remove_start_time_ = base::Time::Now();
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&Context::Init, this, mime_type));
|
|
|
| -PluginDataRemoverImpl::~PluginDataRemoverImpl() {
|
| - if (is_starting_process_)
|
| - PluginService::GetInstance()->CancelOpenChannelToNpapiPlugin(this);
|
| - DCHECK(!is_removing_);
|
| - if (channel_)
|
| - BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, channel_);
|
| -}
|
| + BrowserThread::PostDelayedTask(
|
| + BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&Context::OnTimeout, this),
|
| + kRemovalTimeoutMs);
|
| + }
|
|
|
| -base::WaitableEvent* PluginDataRemoverImpl::StartRemoving(
|
| - base::Time begin_time) {
|
| - DCHECK(!is_removing_);
|
| - remove_start_time_ = base::Time::Now();
|
| - begin_time_ = begin_time;
|
| + virtual ~Context() {
|
| + if (channel_)
|
| + BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, channel_);
|
| + }
|
|
|
| - is_starting_process_ = true;
|
| - is_removing_ = true;
|
| - PluginService::GetInstance()->OpenChannelToNpapiPlugin(
|
| - 0, 0, GURL(), GURL(), mime_type_, this);
|
| + // PluginProcessHost::Client methods.
|
| + virtual int ID() OVERRIDE {
|
| + // Generate a unique identifier for this PluginProcessHostClient.
|
| + return ChildProcessInfo::GenerateChildProcessUniqueId();
|
| + }
|
|
|
| - BrowserThread::PostDelayedTask(
|
| - BrowserThread::IO,
|
| - FROM_HERE,
|
| - base::Bind(&PluginDataRemoverImpl::OnTimeout, weak_factory_.GetWeakPtr()),
|
| - kRemovalTimeoutMs);
|
| + virtual bool OffTheRecord() OVERRIDE {
|
| + return false;
|
| + }
|
|
|
| - return event_.get();
|
| -}
|
| + virtual const content::ResourceContext& GetResourceContext() OVERRIDE {
|
| + return resource_context_;
|
| + }
|
|
|
| -int PluginDataRemoverImpl::ID() {
|
| - // Generate a unique identifier for this PluginProcessHostClient.
|
| - return ChildProcessInfo::GenerateChildProcessUniqueId();
|
| -}
|
| + virtual void SetPluginInfo(const webkit::WebPluginInfo& info) OVERRIDE {
|
| + }
|
|
|
| -bool PluginDataRemoverImpl::OffTheRecord() {
|
| - return false;
|
| -}
|
| + virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {
|
| + }
|
|
|
| -const content::ResourceContext& PluginDataRemoverImpl::GetResourceContext() {
|
| - return context_;
|
| -}
|
| + virtual void OnSentPluginChannelRequest() OVERRIDE {
|
| + }
|
|
|
| -void PluginDataRemoverImpl::SetPluginInfo(
|
| - const webkit::WebPluginInfo& info) {
|
| -}
|
| + virtual void OnChannelOpened(const IPC::ChannelHandle& handle) OVERRIDE {
|
| + ConnectToChannel(handle);
|
| + // Balancing the AddRef call.
|
| + Release();
|
| + }
|
|
|
| -void PluginDataRemoverImpl::OnFoundPluginProcessHost(
|
| - PluginProcessHost* host) {
|
| -}
|
| + virtual void OnError() OVERRIDE {
|
| + LOG(DFATAL) << "Couldn't open plugin channel";
|
| + SignalDone();
|
| + // Balancing the AddRef call.
|
| + Release();
|
| + }
|
|
|
| -void PluginDataRemoverImpl::OnSentPluginChannelRequest() {
|
| -}
|
| + // IPC::Channel::Listener methods.
|
| + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
|
| + IPC_BEGIN_MESSAGE_MAP(Context, message)
|
| + IPC_MESSAGE_HANDLER(PluginHostMsg_ClearSiteDataResult,
|
| + OnClearSiteDataResult)
|
| + IPC_MESSAGE_UNHANDLED_ERROR()
|
| + IPC_END_MESSAGE_MAP()
|
|
|
| -void PluginDataRemoverImpl::OnChannelOpened(const IPC::ChannelHandle& handle) {
|
| - is_starting_process_ = false;
|
| - ConnectToChannel(handle);
|
| -}
|
| + return true;
|
| + }
|
|
|
| -void PluginDataRemoverImpl::ConnectToChannel(const IPC::ChannelHandle& handle) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + virtual void OnChannelError() OVERRIDE {
|
| + if (is_removing_) {
|
| + NOTREACHED() << "Channel error";
|
| + SignalDone();
|
| + }
|
| + }
|
|
|
| - // If we timed out, don't bother connecting.
|
| - if (!is_removing_)
|
| - return;
|
|
|
| - DCHECK(!channel_);
|
| - channel_ = new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this);
|
| - if (!channel_->Connect()) {
|
| - NOTREACHED() << "Couldn't connect to plugin";
|
| + base::WaitableEvent* event() { return event_.get(); }
|
| +
|
| + private:
|
| + // Initialize on the IO thread.
|
| + void Init(const std::string& mime_type) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + is_removing_ = true;
|
| + PluginService::GetInstance()->OpenChannelToNpapiPlugin(
|
| + 0, 0, GURL(), GURL(), mime_type, this);
|
| + }
|
| +
|
| + // Connects the client side of a newly opened plug-in channel.
|
| + void ConnectToChannel(const IPC::ChannelHandle& handle) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| +
|
| + // If we timed out, don't bother connecting.
|
| + if (!is_removing_)
|
| + return;
|
| +
|
| + DCHECK(!channel_);
|
| + channel_ = new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this);
|
| + if (!channel_->Connect()) {
|
| + NOTREACHED() << "Couldn't connect to plugin";
|
| + SignalDone();
|
| + return;
|
| + }
|
| +
|
| + if (!channel_->Send(new PluginMsg_ClearSiteData(std::string(),
|
| + kClearAllData,
|
| + begin_time_))) {
|
| + NOTREACHED() << "Couldn't send ClearSiteData message";
|
| + SignalDone();
|
| + return;
|
| + }
|
| + }
|
| +
|
| + // Handles the PluginHostMsg_ClearSiteDataResult message.
|
| + void OnClearSiteDataResult(bool success) {
|
| + LOG_IF(ERROR, !success) << "ClearSiteData returned error";
|
| + UMA_HISTOGRAM_TIMES("ClearPluginData.time",
|
| + base::Time::Now() - remove_start_time_);
|
| SignalDone();
|
| - return;
|
| }
|
|
|
| - if (!channel_->Send(new PluginMsg_ClearSiteData(std::string(),
|
| - kClearAllData,
|
| - begin_time_))) {
|
| - NOTREACHED() << "Couldn't send ClearSiteData message";
|
| + // Called when a timeout happens in order not to block the client
|
| + // indefinitely.
|
| + void OnTimeout() {
|
| + LOG_IF(ERROR, is_removing_) << "Timed out";
|
| SignalDone();
|
| - return;
|
| }
|
| -}
|
|
|
| -void PluginDataRemoverImpl::OnError() {
|
| - LOG(DFATAL) << "Couldn't open plugin channel";
|
| - SignalDone();
|
| -}
|
| + // Signals that we are finished with removing data (successful or not). This
|
| + // method is safe to call multiple times.
|
| + void SignalDone() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + if (!is_removing_)
|
| + return;
|
| + is_removing_ = false;
|
| + event_->Signal();
|
| + }
|
|
|
| -void PluginDataRemoverImpl::OnClearSiteDataResult(bool success) {
|
| - LOG_IF(ERROR, !success) << "ClearSiteData returned error";
|
| - UMA_HISTOGRAM_TIMES("ClearPluginData.time",
|
| - base::Time::Now() - remove_start_time_);
|
| - SignalDone();
|
| -}
|
| + scoped_ptr<base::WaitableEvent> event_;
|
| + // The point in time when we start removing data.
|
| + base::Time remove_start_time_;
|
| + // The point in time from which on we remove data.
|
| + base::Time begin_time_;
|
| + bool is_removing_;
|
|
|
| -void PluginDataRemoverImpl::OnTimeout() {
|
| - LOG_IF(ERROR, is_removing_) << "Timed out";
|
| - SignalDone();
|
| -}
|
| + // The resource context for the profile.
|
| + const content::ResourceContext& resource_context_;
|
|
|
| -bool PluginDataRemoverImpl::OnMessageReceived(const IPC::Message& msg) {
|
| - IPC_BEGIN_MESSAGE_MAP(PluginDataRemoverImpl, msg)
|
| - IPC_MESSAGE_HANDLER(PluginHostMsg_ClearSiteDataResult,
|
| - OnClearSiteDataResult)
|
| - IPC_MESSAGE_UNHANDLED_ERROR()
|
| - IPC_END_MESSAGE_MAP()
|
| + // We own the channel, but it's used on the IO thread, so it needs to be
|
| + // deleted there. It's NULL until we have opened a connection to the plug-in
|
| + // process.
|
| + IPC::Channel* channel_;
|
| +};
|
|
|
| - return true;
|
| +
|
| +PluginDataRemoverImpl::PluginDataRemoverImpl(
|
| + const content::ResourceContext& resource_context)
|
| + : mime_type_(kFlashMimeType),
|
| + resource_context_(resource_context) {
|
| }
|
|
|
| -void PluginDataRemoverImpl::OnChannelError() {
|
| - is_starting_process_ = false;
|
| - if (is_removing_) {
|
| - NOTREACHED() << "Channel error";
|
| - SignalDone();
|
| - }
|
| +PluginDataRemoverImpl::~PluginDataRemoverImpl() {
|
| }
|
|
|
| -void PluginDataRemoverImpl::SignalDone() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| - if (!is_removing_)
|
| - return;
|
| - is_removing_ = false;
|
| - event_->Signal();
|
| +base::WaitableEvent* PluginDataRemoverImpl::StartRemoving(
|
| + base::Time begin_time) {
|
| + DCHECK(!context_.get());
|
| + context_ = new Context(mime_type_, begin_time, resource_context_);
|
| + return context_->event();
|
| }
|
|
|