| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/browser/plugin_data_remover_impl.h" | 5 #include "content/browser/plugin_data_remover_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 9 #include "base/synchronization/waitable_event.h" | 9 #include "base/synchronization/waitable_event.h" |
| 10 #include "base/version.h" | 10 #include "base/version.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 if (rv) | 53 if (rv) |
| 54 *plugin = *plugin_it; | 54 *plugin = *plugin_it; |
| 55 return rv; | 55 return rv; |
| 56 } | 56 } |
| 57 | 57 |
| 58 } | 58 } |
| 59 | 59 |
| 60 class PluginDataRemoverImpl::Context | 60 class PluginDataRemoverImpl::Context |
| 61 : public PluginProcessHost::Client, | 61 : public PluginProcessHost::Client, |
| 62 public IPC::Channel::Listener, | 62 public IPC::Channel::Listener, |
| 63 public base::RefCountedThreadSafe<Context> { | 63 public base::RefCountedThreadSafe<Context, |
| 64 BrowserThread::DeleteOnIOThread> { |
| 64 public: | 65 public: |
| 65 Context(const std::string& mime_type, | 66 Context(base::Time begin_time, |
| 66 base::Time begin_time, | |
| 67 const content::ResourceContext& resource_context) | 67 const content::ResourceContext& resource_context) |
| 68 : event_(new base::WaitableEvent(true, false)), | 68 : event_(new base::WaitableEvent(true, false)), |
| 69 begin_time_(begin_time), | 69 begin_time_(begin_time), |
| 70 is_removing_(false), | 70 is_removing_(false), |
| 71 resource_context_(resource_context), | 71 resource_context_(resource_context), |
| 72 channel_(NULL) { | 72 channel_(NULL) { |
| 73 // Balanced in OnChannelOpened or OnError. Exactly one them will eventually | 73 } |
| 74 // be called, so we need to keep this object around until then. | 74 |
| 75 AddRef(); | 75 virtual ~Context() { |
| 76 remove_start_time_ = base::Time::Now(); | 76 } |
| 77 |
| 78 void Init(const std::string& mime_type) { |
| 77 BrowserThread::PostTask( | 79 BrowserThread::PostTask( |
| 78 BrowserThread::IO, | 80 BrowserThread::IO, |
| 79 FROM_HERE, | 81 FROM_HERE, |
| 80 base::Bind(&Context::Init, this, mime_type)); | 82 base::Bind(&Context::InitOnIOThread, this, mime_type)); |
| 81 | |
| 82 BrowserThread::PostDelayedTask( | 83 BrowserThread::PostDelayedTask( |
| 83 BrowserThread::IO, | 84 BrowserThread::IO, |
| 84 FROM_HERE, | 85 FROM_HERE, |
| 85 base::Bind(&Context::OnTimeout, this), | 86 base::Bind(&Context::OnTimeout, this), |
| 86 kRemovalTimeoutMs); | 87 kRemovalTimeoutMs); |
| 87 } | 88 } |
| 88 | 89 |
| 89 virtual ~Context() { | 90 // Initialize on the IO thread. |
| 90 if (channel_) | 91 void InitOnIOThread(const std::string& mime_type) { |
| 91 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, channel_); | 92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 93 remove_start_time_ = base::Time::Now(); |
| 94 is_removing_ = true; |
| 95 // Balanced in OnChannelOpened or OnError. Exactly one them will eventually |
| 96 // be called, so we need to keep this object around until then. |
| 97 AddRef(); |
| 98 PluginService::GetInstance()->OpenChannelToNpapiPlugin( |
| 99 0, 0, GURL(), GURL(), mime_type, this); |
| 100 } |
| 101 |
| 102 // Called when a timeout happens in order not to block the client |
| 103 // indefinitely. |
| 104 void OnTimeout() { |
| 105 LOG_IF(ERROR, is_removing_) << "Timed out"; |
| 106 SignalDone(); |
| 92 } | 107 } |
| 93 | 108 |
| 94 // PluginProcessHost::Client methods. | 109 // PluginProcessHost::Client methods. |
| 95 virtual int ID() OVERRIDE { | 110 virtual int ID() OVERRIDE { |
| 96 // Generate a unique identifier for this PluginProcessHostClient. | 111 // Generate a unique identifier for this PluginProcessHostClient. |
| 97 return ChildProcessHostImpl::GenerateChildProcessUniqueId(); | 112 return ChildProcessHostImpl::GenerateChildProcessUniqueId(); |
| 98 } | 113 } |
| 99 | 114 |
| 100 virtual bool OffTheRecord() OVERRIDE { | 115 virtual bool OffTheRecord() OVERRIDE { |
| 101 return false; | 116 return false; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 return true; | 153 return true; |
| 139 } | 154 } |
| 140 | 155 |
| 141 virtual void OnChannelError() OVERRIDE { | 156 virtual void OnChannelError() OVERRIDE { |
| 142 if (is_removing_) { | 157 if (is_removing_) { |
| 143 NOTREACHED() << "Channel error"; | 158 NOTREACHED() << "Channel error"; |
| 144 SignalDone(); | 159 SignalDone(); |
| 145 } | 160 } |
| 146 } | 161 } |
| 147 | 162 |
| 148 | |
| 149 base::WaitableEvent* event() { return event_.get(); } | 163 base::WaitableEvent* event() { return event_.get(); } |
| 150 | 164 |
| 151 private: | 165 private: |
| 152 // Initialize on the IO thread. | |
| 153 void Init(const std::string& mime_type) { | |
| 154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 155 is_removing_ = true; | |
| 156 PluginService::GetInstance()->OpenChannelToNpapiPlugin( | |
| 157 0, 0, GURL(), GURL(), mime_type, this); | |
| 158 } | |
| 159 | |
| 160 // Connects the client side of a newly opened plug-in channel. | 166 // Connects the client side of a newly opened plug-in channel. |
| 161 void ConnectToChannel(const IPC::ChannelHandle& handle) { | 167 void ConnectToChannel(const IPC::ChannelHandle& handle) { |
| 162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 163 | 169 |
| 164 // If we timed out, don't bother connecting. | 170 // If we timed out, don't bother connecting. |
| 165 if (!is_removing_) | 171 if (!is_removing_) |
| 166 return; | 172 return; |
| 167 | 173 |
| 168 DCHECK(!channel_); | 174 DCHECK(!channel_.get()); |
| 169 channel_ = new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this); | 175 channel_.reset(new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this)); |
| 170 if (!channel_->Connect()) { | 176 if (!channel_->Connect()) { |
| 171 NOTREACHED() << "Couldn't connect to plugin"; | 177 NOTREACHED() << "Couldn't connect to plugin"; |
| 172 SignalDone(); | 178 SignalDone(); |
| 173 return; | 179 return; |
| 174 } | 180 } |
| 175 | 181 |
| 176 if (!channel_->Send(new PluginMsg_ClearSiteData(std::string(), | 182 if (!channel_->Send(new PluginMsg_ClearSiteData(std::string(), |
| 177 kClearAllData, | 183 kClearAllData, |
| 178 begin_time_))) { | 184 begin_time_))) { |
| 179 NOTREACHED() << "Couldn't send ClearSiteData message"; | 185 NOTREACHED() << "Couldn't send ClearSiteData message"; |
| 180 SignalDone(); | 186 SignalDone(); |
| 181 return; | 187 return; |
| 182 } | 188 } |
| 183 } | 189 } |
| 184 | 190 |
| 185 // Handles the PluginHostMsg_ClearSiteDataResult message. | 191 // Handles the PluginHostMsg_ClearSiteDataResult message. |
| 186 void OnClearSiteDataResult(bool success) { | 192 void OnClearSiteDataResult(bool success) { |
| 187 LOG_IF(ERROR, !success) << "ClearSiteData returned error"; | 193 LOG_IF(ERROR, !success) << "ClearSiteData returned error"; |
| 188 UMA_HISTOGRAM_TIMES("ClearPluginData.time", | 194 UMA_HISTOGRAM_TIMES("ClearPluginData.time", |
| 189 base::Time::Now() - remove_start_time_); | 195 base::Time::Now() - remove_start_time_); |
| 190 SignalDone(); | 196 SignalDone(); |
| 191 } | 197 } |
| 192 | 198 |
| 193 // Called when a timeout happens in order not to block the client | |
| 194 // indefinitely. | |
| 195 void OnTimeout() { | |
| 196 LOG_IF(ERROR, is_removing_) << "Timed out"; | |
| 197 SignalDone(); | |
| 198 } | |
| 199 | |
| 200 // Signals that we are finished with removing data (successful or not). This | 199 // Signals that we are finished with removing data (successful or not). This |
| 201 // method is safe to call multiple times. | 200 // method is safe to call multiple times. |
| 202 void SignalDone() { | 201 void SignalDone() { |
| 203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 204 if (!is_removing_) | 203 if (!is_removing_) |
| 205 return; | 204 return; |
| 206 is_removing_ = false; | 205 is_removing_ = false; |
| 207 event_->Signal(); | 206 event_->Signal(); |
| 208 } | 207 } |
| 209 | 208 |
| 210 scoped_ptr<base::WaitableEvent> event_; | 209 scoped_ptr<base::WaitableEvent> event_; |
| 211 // The point in time when we start removing data. | 210 // The point in time when we start removing data. |
| 212 base::Time remove_start_time_; | 211 base::Time remove_start_time_; |
| 213 // The point in time from which on we remove data. | 212 // The point in time from which on we remove data. |
| 214 base::Time begin_time_; | 213 base::Time begin_time_; |
| 215 bool is_removing_; | 214 bool is_removing_; |
| 216 | 215 |
| 217 // The resource context for the profile. | 216 // The resource context for the profile. |
| 218 const content::ResourceContext& resource_context_; | 217 const content::ResourceContext& resource_context_; |
| 219 | 218 |
| 220 // We own the channel, but it's used on the IO thread, so it needs to be | 219 // The channel is NULL until we have opened a connection to the plug-in |
| 221 // deleted there. It's NULL until we have opened a connection to the plug-in | |
| 222 // process. | 220 // process. |
| 223 IPC::Channel* channel_; | 221 scoped_ptr<IPC::Channel> channel_; |
| 224 }; | 222 }; |
| 225 | 223 |
| 226 | 224 |
| 227 PluginDataRemoverImpl::PluginDataRemoverImpl( | 225 PluginDataRemoverImpl::PluginDataRemoverImpl( |
| 228 const content::ResourceContext& resource_context) | 226 const content::ResourceContext& resource_context) |
| 229 : mime_type_(kFlashMimeType), | 227 : mime_type_(kFlashMimeType), |
| 230 resource_context_(resource_context) { | 228 resource_context_(resource_context) { |
| 231 } | 229 } |
| 232 | 230 |
| 233 PluginDataRemoverImpl::~PluginDataRemoverImpl() { | 231 PluginDataRemoverImpl::~PluginDataRemoverImpl() { |
| 234 } | 232 } |
| 235 | 233 |
| 236 base::WaitableEvent* PluginDataRemoverImpl::StartRemoving( | 234 base::WaitableEvent* PluginDataRemoverImpl::StartRemoving( |
| 237 base::Time begin_time) { | 235 base::Time begin_time) { |
| 238 DCHECK(!context_.get()); | 236 DCHECK(!context_.get()); |
| 239 context_ = new Context(mime_type_, begin_time, resource_context_); | 237 context_ = new Context(begin_time, resource_context_); |
| 238 context_->Init(mime_type_); |
| 240 return context_->event(); | 239 return context_->event(); |
| 241 } | 240 } |
| OLD | NEW |