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 |