Chromium Code Reviews| Index: chrome/browser/plugin_data_remover.cc |
| diff --git a/chrome/browser/plugin_data_remover.cc b/chrome/browser/plugin_data_remover.cc |
| index 4415c5f3d6d8755ea962180410c6f424ff245b20..5bb81960c0a993561a59b2b74870ca3e5ced26fe 100644 |
| --- a/chrome/browser/plugin_data_remover.cc |
| +++ b/chrome/browser/plugin_data_remover.cc |
| @@ -4,63 +4,118 @@ |
| #include "chrome/browser/plugin_data_remover.h" |
| +#include "base/metrics/histogram.h" |
| #include "base/message_loop_proxy.h" |
| +#include "base/version.h" |
| #include "chrome/browser/browser_thread.h" |
| +#include "chrome/browser/plugin_process_host.h" |
| #include "chrome/browser/plugin_service.h" |
| #include "chrome/common/plugin_messages.h" |
| #include "ipc/ipc_channel.h" |
| +#include "webkit/glue/plugins/plugin_group.h" |
| +#include "webkit/glue/plugins/plugin_list.h" |
| #if defined(OS_POSIX) |
| #include "ipc/ipc_channel_posix.h" |
| #endif |
| namespace { |
| -const std::string flash_mime_type = "application/x-shockwave-flash"; |
| +const char* flash_mime_type = "application/x-shockwave-flash"; |
| +// TODO(bauerb): Update minimum required Flash version as soon as there is one |
| +// implementing the API. |
| +const char* min_flash_version = "100"; |
| const int64 timeout_ms = 10000; |
|
jam
2010/12/13 22:41:27
can you prefix globals with "g_"
|
| -} |
| +} // namespace |
| + |
| +class PluginDataRemover::Internal |
| + : public base::RefCountedThreadSafe<Internal>, |
| + public PluginProcessHost::Client { |
| + public: |
| + explicit Internal(PluginDataRemover* remover) : remover_(remover) { |
| + // We increase our reference count until either OnChannelOpened or OnError |
| + // is called. |
| + AddRef(); |
| + } |
| + ~Internal() { |
| + DCHECK(!remover_); |
| + } |
| + |
| + void Invalidate() { |
| + remover_ = NULL; |
| + } |
| + |
| + virtual int ID() { |
| + // Generate an ID for the browser process. |
| + return ChildProcessInfo::GenerateChildProcessUniqueId(); |
| + } |
| + |
| + virtual bool OffTheRecord() { |
| + return false; |
| + } |
| + |
| + virtual void SetPluginInfo(const WebPluginInfo& info) { } |
| + |
| + virtual void OnChannelOpened(const IPC::ChannelHandle& handle) { |
| + if (remover_) |
| + remover_->OnChannelOpened(handle); |
| + Release(); |
| + } |
| + |
| + virtual void OnError() { |
| + if (remover_) { |
| + LOG(DFATAL) << "Couldn't open plugin channel"; |
| + remover_->SignalDone(); |
| + } |
| + Release(); |
| + } |
| + |
| + void OnTimeout() { |
| + if (remover_) { |
| + LOG(DFATAL) << "Timed out"; |
| + remover_->SignalDone(); |
| + } |
| + } |
| + |
| + private: |
| + PluginDataRemover* remover_; |
| +}; |
| PluginDataRemover::PluginDataRemover() |
| - : channel_(NULL), |
| - method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| -} |
| + : is_removing_(false), |
| + channel_(NULL) { } |
| PluginDataRemover::~PluginDataRemover() { |
| - DCHECK(!done_task_.get()); |
| - if (!BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, channel_)) |
| - delete channel_; |
| + DCHECK(!is_removing_); |
| + if (channel_) |
| + BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, channel_); |
| } |
| void PluginDataRemover::StartRemoving(base::Time begin_time, Task* done_task) { |
| DCHECK(!done_task_.get()); |
| + DCHECK(!is_removing_); |
| + remove_start_time_ = base::Time::Now(); |
| begin_time_ = begin_time; |
| message_loop_ = base::MessageLoopProxy::CreateForCurrentThread(); |
| done_task_.reset(done_task); |
| + is_removing_ = true; |
| + internal_ = make_scoped_refptr(new Internal(this)); |
| PluginService::GetInstance()->OpenChannelToPlugin( |
| - GURL(), flash_mime_type, this); |
| + GURL(), |
| + flash_mime_type, |
| + internal_); |
| BrowserThread::PostDelayedTask( |
| BrowserThread::IO, |
| FROM_HERE, |
| - method_factory_.NewRunnableMethod(&PluginDataRemover::OnTimeout), |
| + NewRunnableMethod(internal_.get(), &Internal::OnTimeout), |
| timeout_ms); |
| } |
| -int PluginDataRemover::ID() { |
| - // Generate an ID for the browser process. |
| - return ChildProcessInfo::GenerateChildProcessUniqueId(); |
| -} |
| - |
| -bool PluginDataRemover::OffTheRecord() { |
| - return false; |
| -} |
| - |
| -void PluginDataRemover::SetPluginInfo(const WebPluginInfo& info) { |
| -} |
| - |
| void PluginDataRemover::OnChannelOpened(const IPC::ChannelHandle& handle) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| DCHECK(!channel_); |
| #if defined(OS_POSIX) |
| // If we received a ChannelHandle, register it now. |
| @@ -69,30 +124,23 @@ void PluginDataRemover::OnChannelOpened(const IPC::ChannelHandle& handle) { |
| #endif |
| channel_ = new IPC::Channel(handle.name, IPC::Channel::MODE_CLIENT, this); |
| if (!channel_->Connect()) { |
| - NOTREACHED() << "Couldn't connect to plugin"; |
| + LOG(DFATAL) << "Couldn't connect to plugin"; |
| SignalDone(); |
| return; |
| } |
| if (!channel_->Send( |
| new PluginMsg_ClearSiteData(0, std::string(), begin_time_))) { |
| - NOTREACHED() << "Couldn't send ClearSiteData message"; |
| + LOG(DFATAL) << "Couldn't send ClearSiteData message"; |
| SignalDone(); |
| } |
| } |
| -void PluginDataRemover::OnError() { |
| - NOTREACHED() << "Couldn't open plugin channel"; |
| - SignalDone(); |
| -} |
| - |
| void PluginDataRemover::OnClearSiteDataResult(bool success) { |
| - DCHECK(success) << "ClearSiteData returned error"; |
| - SignalDone(); |
| -} |
| - |
| -void PluginDataRemover::OnTimeout() { |
| - NOTREACHED() << "Timed out"; |
| + if (!success) |
| + LOG(DFATAL) << "ClearSiteData returned error"; |
| + UMA_HISTOGRAM_TIMES("ClearPluginData.time", |
| + base::Time::Now() - remove_start_time_); |
| SignalDone(); |
| } |
| @@ -105,14 +153,39 @@ void PluginDataRemover::OnMessageReceived(const IPC::Message& msg) { |
| } |
| void PluginDataRemover::OnChannelError() { |
| - NOTREACHED() << "Channel error"; |
| + LOG(DFATAL) << "Channel error"; |
| SignalDone(); |
| } |
| void PluginDataRemover::SignalDone() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| - if (!done_task_.get()) |
| + if (!is_removing_) |
| return; |
| - message_loop_->PostTask(FROM_HERE, done_task_.release()); |
| - message_loop_ = NULL; |
| + is_removing_ = false; |
| + if (done_task_.get()) { |
| + message_loop_->PostTask(FROM_HERE, done_task_.release()); |
| + message_loop_ = NULL; |
| + } |
| + internal_->Invalidate(); |
| +} |
| + |
| +// static |
| +bool PluginDataRemover::IsSupported() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + bool allow_wildcard = false; |
| + WebPluginInfo plugin; |
| + std::string mime_type; |
| + if (!NPAPI::PluginList::Singleton()->GetPluginInfo(GURL(), |
| + flash_mime_type, |
| + allow_wildcard, |
| + &plugin, |
| + &mime_type)) |
| + return false; |
| + scoped_ptr<Version> version( |
| + PluginGroup::CreateVersionFromString(plugin.version)); |
| + scoped_ptr<Version> min_version( |
| + Version::GetVersionFromString(min_flash_version)); |
| + return plugin.enabled && |
| + version.get() |
| + && min_version->CompareTo(*version) == -1; |
| } |