OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <limits> | 9 #include <limits> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/sequenced_task_runner_helpers.h" | 13 #include "base/sequenced_task_runner_helpers.h" |
14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
15 #include "base/synchronization/waitable_event.h" | 15 #include "base/synchronization/waitable_event.h" |
16 #include "base/version.h" | 16 #include "base/version.h" |
17 #include "build/build_config.h" | 17 #include "build/build_config.h" |
18 #include "content/browser/plugin_process_host.h" | |
19 #include "content/browser/plugin_service_impl.h" | 18 #include "content/browser/plugin_service_impl.h" |
20 #include "content/browser/renderer_host/pepper/pepper_flash_file_message_filter.
h" | 19 #include "content/browser/renderer_host/pepper/pepper_flash_file_message_filter.
h" |
21 #include "content/common/child_process_host_impl.h" | 20 #include "content/common/child_process_host_impl.h" |
22 #include "content/common/plugin_process_messages.h" | |
23 #include "content/public/browser/browser_context.h" | 21 #include "content/public/browser/browser_context.h" |
24 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
25 #include "content/public/common/child_process_host.h" | 23 #include "content/public/common/child_process_host.h" |
26 #include "content/public/common/content_constants.h" | 24 #include "content/public/common/content_constants.h" |
27 #include "content/public/common/pepper_plugin_info.h" | 25 #include "content/public/common/pepper_plugin_info.h" |
28 #include "ppapi/proxy/ppapi_messages.h" | 26 #include "ppapi/proxy/ppapi_messages.h" |
29 | 27 |
30 namespace content { | 28 namespace content { |
31 | 29 |
32 namespace { | 30 namespace { |
(...skipping 21 matching lines...) Expand all Loading... |
54 for (std::vector<WebPluginInfo>::iterator it = plugins.begin(); | 52 for (std::vector<WebPluginInfo>::iterator it = plugins.begin(); |
55 it != plugins.end(); ++it) { | 53 it != plugins.end(); ++it) { |
56 Version version; | 54 Version version; |
57 WebPluginInfo::CreateVersionFromString(it->version, &version); | 55 WebPluginInfo::CreateVersionFromString(it->version, &version); |
58 if (version.IsValid() && min_version.CompareTo(version) == -1) | 56 if (version.IsValid() && min_version.CompareTo(version) == -1) |
59 supported_plugins->push_back(*it); | 57 supported_plugins->push_back(*it); |
60 } | 58 } |
61 } | 59 } |
62 | 60 |
63 class PluginDataRemoverImpl::Context | 61 class PluginDataRemoverImpl::Context |
64 : public PluginProcessHost::Client, | 62 : public PpapiPluginProcessHost::BrokerClient, |
65 public PpapiPluginProcessHost::BrokerClient, | |
66 public IPC::Listener, | 63 public IPC::Listener, |
67 public base::RefCountedThreadSafe<Context, | 64 public base::RefCountedThreadSafe<Context, |
68 BrowserThread::DeleteOnIOThread> { | 65 BrowserThread::DeleteOnIOThread> { |
69 public: | 66 public: |
70 Context(base::Time begin_time, BrowserContext* browser_context) | 67 Context(base::Time begin_time, BrowserContext* browser_context) |
71 : event_(new base::WaitableEvent(true, false)), | 68 : event_(new base::WaitableEvent(true, false)), |
72 begin_time_(begin_time), | 69 begin_time_(begin_time), |
73 is_removing_(false), | 70 is_removing_(false), |
74 browser_context_path_(browser_context->GetPath()), | 71 browser_context_path_(browser_context->GetPath()) { |
75 resource_context_(browser_context->GetResourceContext()) { | |
76 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 72 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
77 } | 73 } |
78 | 74 |
79 void Init(const std::string& mime_type) { | 75 void Init(const std::string& mime_type) { |
80 BrowserThread::PostTask( | 76 BrowserThread::PostTask( |
81 BrowserThread::IO, | 77 BrowserThread::IO, |
82 FROM_HERE, | 78 FROM_HERE, |
83 base::Bind(&Context::InitOnIOThread, this, mime_type)); | 79 base::Bind(&Context::InitOnIOThread, this, mime_type)); |
84 BrowserThread::PostDelayedTask( | 80 BrowserThread::PostDelayedTask( |
85 BrowserThread::IO, | 81 BrowserThread::IO, |
(...skipping 11 matching lines...) Expand all Loading... |
97 GURL(), mime_type, false, &plugins, NULL); | 93 GURL(), mime_type, false, &plugins, NULL); |
98 | 94 |
99 if (plugins.empty()) { | 95 if (plugins.empty()) { |
100 // May be empty for some tests and on the CrOS login OOBE screen. | 96 // May be empty for some tests and on the CrOS login OOBE screen. |
101 event_->Signal(); | 97 event_->Signal(); |
102 return; | 98 return; |
103 } | 99 } |
104 | 100 |
105 base::FilePath plugin_path = plugins[0].path; | 101 base::FilePath plugin_path = plugins[0].path; |
106 | 102 |
| 103 PepperPluginInfo* pepper_info = |
| 104 plugin_service->GetRegisteredPpapiPluginInfo(plugin_path); |
| 105 if (!pepper_info) { |
| 106 event_->Signal(); |
| 107 return; |
| 108 } |
| 109 |
107 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 110 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
108 remove_start_time_ = base::Time::Now(); | 111 remove_start_time_ = base::Time::Now(); |
109 is_removing_ = true; | 112 is_removing_ = true; |
110 // Balanced in On[Ppapi]ChannelOpened or OnError. Exactly one them will | 113 |
111 // eventually be called, so we need to keep this object around until then. | 114 // Balanced in OnPpapiChannelOpened. |
112 AddRef(); | 115 AddRef(); |
113 | 116 plugin_name_ = pepper_info->name; |
114 PepperPluginInfo* pepper_info = | 117 // Use the broker since we run this function outside the sandbox. |
115 plugin_service->GetRegisteredPpapiPluginInfo(plugin_path); | 118 plugin_service->OpenChannelToPpapiBroker(0, plugin_path, this); |
116 if (pepper_info) { | |
117 plugin_name_ = pepper_info->name; | |
118 // Use the broker since we run this function outside the sandbox. | |
119 plugin_service->OpenChannelToPpapiBroker(0, plugin_path, this); | |
120 } else { | |
121 plugin_service->OpenChannelToNpapiPlugin( | |
122 0, 0, GURL(), GURL(), mime_type, this); | |
123 } | |
124 } | 119 } |
125 | 120 |
126 // Called when a timeout happens in order not to block the client | 121 // Called when a timeout happens in order not to block the client |
127 // indefinitely. | 122 // indefinitely. |
128 void OnTimeout() { | 123 void OnTimeout() { |
129 LOG_IF(ERROR, is_removing_) << "Timed out"; | 124 LOG_IF(ERROR, is_removing_) << "Timed out"; |
130 SignalDone(); | 125 SignalDone(); |
131 } | 126 } |
132 | 127 |
133 // PluginProcessHost::Client methods. | |
134 int ID() override { | |
135 // Generate a unique identifier for this PluginProcessHostClient. | |
136 return ChildProcessHostImpl::GenerateChildProcessUniqueId(); | |
137 } | |
138 | |
139 bool OffTheRecord() override { return false; } | 128 bool OffTheRecord() override { return false; } |
140 | 129 |
141 ResourceContext* GetResourceContext() override { return resource_context_; } | |
142 | |
143 void SetPluginInfo(const WebPluginInfo& info) override {} | |
144 | |
145 void OnFoundPluginProcessHost(PluginProcessHost* host) override {} | |
146 | |
147 void OnSentPluginChannelRequest() override {} | |
148 | |
149 void OnChannelOpened(const IPC::ChannelHandle& handle) override { | |
150 ConnectToChannel(handle, false); | |
151 // Balancing the AddRef call. | |
152 Release(); | |
153 } | |
154 | |
155 void OnError() override { | |
156 LOG(ERROR) << "Couldn't open plugin channel"; | |
157 SignalDone(); | |
158 // Balancing the AddRef call. | |
159 Release(); | |
160 } | |
161 | |
162 // PpapiPluginProcessHost::BrokerClient implementation. | 130 // PpapiPluginProcessHost::BrokerClient implementation. |
163 void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle, | 131 void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle, |
164 int* renderer_id) override { | 132 int* renderer_id) override { |
165 *renderer_handle = base::kNullProcessHandle; | 133 *renderer_handle = base::kNullProcessHandle; |
166 *renderer_id = 0; | 134 *renderer_id = 0; |
167 } | 135 } |
168 | 136 |
169 void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle, | 137 void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle, |
170 base::ProcessId /* peer_pid */, | 138 base::ProcessId /* peer_pid */, |
171 int /* child_id */) override { | 139 int /* child_id */) override { |
172 if (!channel_handle.name.empty()) | 140 if (!channel_handle.name.empty()) |
173 ConnectToChannel(channel_handle, true); | 141 ConnectToChannel(channel_handle); |
174 | 142 |
175 // Balancing the AddRef call. | 143 // Balancing the AddRef call. |
176 Release(); | 144 Release(); |
177 } | 145 } |
178 | 146 |
179 // IPC::Listener methods. | 147 // IPC::Listener methods. |
180 bool OnMessageReceived(const IPC::Message& message) override { | 148 bool OnMessageReceived(const IPC::Message& message) override { |
181 IPC_BEGIN_MESSAGE_MAP(Context, message) | 149 IPC_BEGIN_MESSAGE_MAP(Context, message) |
182 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ClearSiteDataResult, | |
183 OnClearSiteDataResult) | |
184 IPC_MESSAGE_HANDLER(PpapiHostMsg_ClearSiteDataResult, | 150 IPC_MESSAGE_HANDLER(PpapiHostMsg_ClearSiteDataResult, |
185 OnPpapiClearSiteDataResult) | 151 OnPpapiClearSiteDataResult) |
186 IPC_MESSAGE_UNHANDLED_ERROR() | 152 IPC_MESSAGE_UNHANDLED_ERROR() |
187 IPC_END_MESSAGE_MAP() | 153 IPC_END_MESSAGE_MAP() |
188 | 154 |
189 return true; | 155 return true; |
190 } | 156 } |
191 | 157 |
192 void OnChannelError() override { | 158 void OnChannelError() override { |
193 if (is_removing_) { | 159 if (is_removing_) { |
(...skipping 21 matching lines...) Expand all Loading... |
215 profile_path.Append(base::FilePath(base::UTF8ToUTF16(plugin_name_))); | 181 profile_path.Append(base::FilePath(base::UTF8ToUTF16(plugin_name_))); |
216 #else | 182 #else |
217 base::FilePath plugin_data_path = | 183 base::FilePath plugin_data_path = |
218 profile_path.Append(base::FilePath(plugin_name_)); | 184 profile_path.Append(base::FilePath(plugin_name_)); |
219 #endif // defined(OS_WIN) | 185 #endif // defined(OS_WIN) |
220 return new PpapiMsg_ClearSiteData(0u, plugin_data_path, std::string(), | 186 return new PpapiMsg_ClearSiteData(0u, plugin_data_path, std::string(), |
221 kClearAllData, max_age); | 187 kClearAllData, max_age); |
222 } | 188 } |
223 | 189 |
224 // Connects the client side of a newly opened plugin channel. | 190 // Connects the client side of a newly opened plugin channel. |
225 void ConnectToChannel(const IPC::ChannelHandle& handle, bool is_ppapi) { | 191 void ConnectToChannel(const IPC::ChannelHandle& handle) { |
226 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 192 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
227 | 193 |
228 // If we timed out, don't bother connecting. | 194 // If we timed out, don't bother connecting. |
229 if (!is_removing_) | 195 if (!is_removing_) |
230 return; | 196 return; |
231 | 197 |
232 DCHECK(!channel_.get()); | 198 DCHECK(!channel_.get()); |
233 channel_ = IPC::Channel::CreateClient(handle, this); | 199 channel_ = IPC::Channel::CreateClient(handle, this); |
234 if (!channel_->Connect()) { | 200 if (!channel_->Connect()) { |
235 NOTREACHED() << "Couldn't connect to plugin"; | 201 NOTREACHED() << "Couldn't connect to plugin"; |
236 SignalDone(); | 202 SignalDone(); |
237 return; | 203 return; |
238 } | 204 } |
239 | 205 |
240 uint64_t max_age = begin_time_.is_null() | 206 uint64_t max_age = begin_time_.is_null() |
241 ? std::numeric_limits<uint64_t>::max() | 207 ? std::numeric_limits<uint64_t>::max() |
242 : (base::Time::Now() - begin_time_).InSeconds(); | 208 : (base::Time::Now() - begin_time_).InSeconds(); |
243 | 209 |
244 IPC::Message* msg; | 210 IPC::Message* msg = CreatePpapiClearSiteDataMsg(max_age); |
245 if (is_ppapi) { | |
246 msg = CreatePpapiClearSiteDataMsg(max_age); | |
247 } else { | |
248 msg = new PluginProcessMsg_ClearSiteData( | |
249 std::string(), kClearAllData, max_age); | |
250 } | |
251 if (!channel_->Send(msg)) { | 211 if (!channel_->Send(msg)) { |
252 NOTREACHED() << "Couldn't send ClearSiteData message"; | 212 NOTREACHED() << "Couldn't send ClearSiteData message"; |
253 SignalDone(); | 213 SignalDone(); |
254 return; | 214 return; |
255 } | 215 } |
256 } | 216 } |
257 | 217 |
258 // Handles the PpapiHostMsg_ClearSiteDataResult message by delegating to the | 218 // Handles the PpapiHostMsg_ClearSiteDataResult message. |
259 // PluginProcessHostMsg_ClearSiteDataResult handler. | |
260 void OnPpapiClearSiteDataResult(uint32_t request_id, bool success) { | 219 void OnPpapiClearSiteDataResult(uint32_t request_id, bool success) { |
261 DCHECK_EQ(0u, request_id); | 220 DCHECK_EQ(0u, request_id); |
262 OnClearSiteDataResult(success); | |
263 } | |
264 | |
265 // Handles the PluginProcessHostMsg_ClearSiteDataResult message. | |
266 void OnClearSiteDataResult(bool success) { | |
267 LOG_IF(ERROR, !success) << "ClearSiteData returned error"; | 221 LOG_IF(ERROR, !success) << "ClearSiteData returned error"; |
268 UMA_HISTOGRAM_TIMES("ClearPluginData.time", | 222 UMA_HISTOGRAM_TIMES("ClearPluginData.time", |
269 base::Time::Now() - remove_start_time_); | 223 base::Time::Now() - remove_start_time_); |
270 SignalDone(); | 224 SignalDone(); |
271 } | 225 } |
272 | 226 |
273 // Signals that we are finished with removing data (successful or not). This | 227 // Signals that we are finished with removing data (successful or not). This |
274 // method is safe to call multiple times. | 228 // method is safe to call multiple times. |
275 void SignalDone() { | 229 void SignalDone() { |
276 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 230 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
277 if (!is_removing_) | 231 if (!is_removing_) |
278 return; | 232 return; |
279 is_removing_ = false; | 233 is_removing_ = false; |
280 event_->Signal(); | 234 event_->Signal(); |
281 } | 235 } |
282 | 236 |
283 scoped_ptr<base::WaitableEvent> event_; | 237 scoped_ptr<base::WaitableEvent> event_; |
284 // The point in time when we start removing data. | 238 // The point in time when we start removing data. |
285 base::Time remove_start_time_; | 239 base::Time remove_start_time_; |
286 // The point in time from which on we remove data. | 240 // The point in time from which on we remove data. |
287 base::Time begin_time_; | 241 base::Time begin_time_; |
288 bool is_removing_; | 242 bool is_removing_; |
289 | 243 |
290 // Path for the current profile. Must be retrieved on the UI thread from the | 244 // Path for the current profile. Must be retrieved on the UI thread from the |
291 // browser context when we start so we can use it later on the I/O thread. | 245 // browser context when we start so we can use it later on the I/O thread. |
292 base::FilePath browser_context_path_; | 246 base::FilePath browser_context_path_; |
293 | 247 |
294 // The resource context for the profile. Use only on the I/O thread. | |
295 ResourceContext* resource_context_; | |
296 | |
297 // The name of the plugin. Use only on the I/O thread. | 248 // The name of the plugin. Use only on the I/O thread. |
298 std::string plugin_name_; | 249 std::string plugin_name_; |
299 | 250 |
300 // The channel is NULL until we have opened a connection to the plugin | 251 // The channel is NULL until we have opened a connection to the plugin |
301 // process. | 252 // process. |
302 scoped_ptr<IPC::Channel> channel_; | 253 scoped_ptr<IPC::Channel> channel_; |
303 }; | 254 }; |
304 | 255 |
305 | 256 |
306 PluginDataRemoverImpl::PluginDataRemoverImpl(BrowserContext* browser_context) | 257 PluginDataRemoverImpl::PluginDataRemoverImpl(BrowserContext* browser_context) |
307 : mime_type_(kFlashPluginSwfMimeType), | 258 : mime_type_(kFlashPluginSwfMimeType), |
308 browser_context_(browser_context) { | 259 browser_context_(browser_context) { |
309 } | 260 } |
310 | 261 |
311 PluginDataRemoverImpl::~PluginDataRemoverImpl() { | 262 PluginDataRemoverImpl::~PluginDataRemoverImpl() { |
312 } | 263 } |
313 | 264 |
314 base::WaitableEvent* PluginDataRemoverImpl::StartRemoving( | 265 base::WaitableEvent* PluginDataRemoverImpl::StartRemoving( |
315 base::Time begin_time) { | 266 base::Time begin_time) { |
316 DCHECK(!context_.get()); | 267 DCHECK(!context_.get()); |
317 context_ = new Context(begin_time, browser_context_); | 268 context_ = new Context(begin_time, browser_context_); |
318 context_->Init(mime_type_); | 269 context_->Init(mime_type_); |
319 return context_->event(); | 270 return context_->event(); |
320 } | 271 } |
321 | 272 |
322 } // namespace content | 273 } // namespace content |
OLD | NEW |