blob: 43930ba1de7eb359783b1f0cafcdd7e72dd6bb75 [file] [log] [blame]
[email protected]5896fa042012-03-07 04:41:401// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]d8e682012011-11-17 18:31:542// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/plugin_data_remover_impl.h"
6
[email protected]c46cfe22012-09-27 22:11:557#include <limits>
8
[email protected]d8e682012011-11-17 18:31:549#include "base/bind.h"
10#include "base/metrics/histogram.h"
[email protected]fb441962013-05-08 05:35:2411#include "base/sequenced_task_runner_helpers.h"
[email protected]74ebfb12013-06-07 20:48:0012#include "base/strings/utf_string_conversions.h"
[email protected]d8e682012011-11-17 18:31:5413#include "base/synchronization/waitable_event.h"
14#include "base/version.h"
[email protected]76b70f92011-11-21 19:31:1415#include "content/browser/plugin_process_host.h"
[email protected]e67385f2011-12-21 06:00:5616#include "content/browser/plugin_service_impl.h"
[email protected]49511a72012-12-21 02:47:4217#include "content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h"
[email protected]4734d0b2011-12-03 07:10:4418#include "content/common/child_process_host_impl.h"
[email protected]872f3a92013-05-21 08:16:0819#include "content/common/plugin_process_messages.h"
[email protected]1bf0fb22012-04-12 21:44:1620#include "content/public/browser/browser_context.h"
[email protected]d8e682012011-11-17 18:31:5421#include "content/public/browser/browser_thread.h"
[email protected]73270292013-08-09 03:48:0722#include "content/public/common/content_constants.h"
[email protected]1bf0fb22012-04-12 21:44:1623#include "content/public/common/pepper_plugin_info.h"
[email protected]c3cdc732012-12-07 09:16:5624#include "ppapi/proxy/ppapi_messages.h"
[email protected]d8e682012011-11-17 18:31:5425
[email protected]1bf0fb22012-04-12 21:44:1626namespace content {
[email protected]d8e682012011-11-17 18:31:5427
28namespace {
29
[email protected]d8e682012011-11-17 18:31:5430// The minimum Flash Player version that implements NPP_ClearSiteData.
31const char kMinFlashVersion[] = "10.3";
32const int64 kRemovalTimeoutMs = 10000;
33const uint64 kClearAllData = 0;
34
35} // namespace
36
[email protected]d8e682012011-11-17 18:31:5437// static
[email protected]1bf0fb22012-04-12 21:44:1638PluginDataRemover* PluginDataRemover::Create(BrowserContext* browser_context) {
39 return new PluginDataRemoverImpl(browser_context);
[email protected]d8e682012011-11-17 18:31:5440}
41
42// static
[email protected]e3464242012-05-05 00:45:3843void PluginDataRemover::GetSupportedPlugins(
[email protected]d7bd3e52013-07-21 04:29:2044 std::vector<WebPluginInfo>* supported_plugins) {
[email protected]d8e682012011-11-17 18:31:5445 bool allow_wildcard = false;
[email protected]d7bd3e52013-07-21 04:29:2046 std::vector<WebPluginInfo> plugins;
[email protected]d8e682012011-11-17 18:31:5447 PluginService::GetInstance()->GetPluginInfoArray(
[email protected]c46cfe22012-09-27 22:11:5548 GURL(), kFlashPluginSwfMimeType, allow_wildcard, &plugins, NULL);
[email protected]c5e4a2222014-01-03 16:06:1349 Version min_version(kMinFlashVersion);
[email protected]d7bd3e52013-07-21 04:29:2050 for (std::vector<WebPluginInfo>::iterator it = plugins.begin();
[email protected]e3464242012-05-05 00:45:3851 it != plugins.end(); ++it) {
[email protected]c5e4a2222014-01-03 16:06:1352 Version version;
[email protected]d7bd3e52013-07-21 04:29:2053 WebPluginInfo::CreateVersionFromString(it->version, &version);
[email protected]12126d372012-07-11 18:40:5354 if (version.IsValid() && min_version.CompareTo(version) == -1)
[email protected]e3464242012-05-05 00:45:3855 supported_plugins->push_back(*it);
56 }
[email protected]d8e682012011-11-17 18:31:5457}
58
[email protected]76b70f92011-11-21 19:31:1459class PluginDataRemoverImpl::Context
60 : public PluginProcessHost::Client,
[email protected]1bf0fb22012-04-12 21:44:1661 public PpapiPluginProcessHost::BrokerClient,
[email protected]d84effeb2012-06-25 17:03:1062 public IPC::Listener,
[email protected]1464ce12011-12-08 11:14:3263 public base::RefCountedThreadSafe<Context,
64 BrowserThread::DeleteOnIOThread> {
[email protected]76b70f92011-11-21 19:31:1465 public:
[email protected]1bf0fb22012-04-12 21:44:1666 Context(base::Time begin_time, BrowserContext* browser_context)
[email protected]76b70f92011-11-21 19:31:1467 : event_(new base::WaitableEvent(true, false)),
68 begin_time_(begin_time),
69 is_removing_(false),
[email protected]1bf0fb22012-04-12 21:44:1670 browser_context_path_(browser_context->GetPath()),
[email protected]47f236d2013-06-13 13:42:3071 resource_context_(browser_context->GetResourceContext()) {
mostynb4c27d042015-03-18 21:47:4772 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]1464ce12011-12-08 11:14:3273 }
74
[email protected]1464ce12011-12-08 11:14:3275 void Init(const std::string& mime_type) {
[email protected]76b70f92011-11-21 19:31:1476 BrowserThread::PostTask(
77 BrowserThread::IO,
78 FROM_HERE,
[email protected]1464ce12011-12-08 11:14:3279 base::Bind(&Context::InitOnIOThread, this, mime_type));
[email protected]76b70f92011-11-21 19:31:1480 BrowserThread::PostDelayedTask(
81 BrowserThread::IO,
82 FROM_HERE,
83 base::Bind(&Context::OnTimeout, this),
[email protected]5896fa042012-03-07 04:41:4084 base::TimeDelta::FromMilliseconds(kRemovalTimeoutMs));
[email protected]76b70f92011-11-21 19:31:1485 }
86
[email protected]1464ce12011-12-08 11:14:3287 void InitOnIOThread(const std::string& mime_type) {
[email protected]1bf0fb22012-04-12 21:44:1688 PluginServiceImpl* plugin_service = PluginServiceImpl::GetInstance();
89
90 // Get the plugin file path.
[email protected]d7bd3e52013-07-21 04:29:2091 std::vector<WebPluginInfo> plugins;
[email protected]1bf0fb22012-04-12 21:44:1692 plugin_service->GetPluginInfoArray(
93 GURL(), mime_type, false, &plugins, NULL);
[email protected]2dec8ec2013-02-07 19:20:3494 base::FilePath plugin_path;
[email protected]1bf0fb22012-04-12 21:44:1695 if (!plugins.empty()) // May be empty for some tests.
96 plugin_path = plugins[0].path;
97
mostynb4c27d042015-03-18 21:47:4798 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]1464ce12011-12-08 11:14:3299 remove_start_time_ = base::Time::Now();
100 is_removing_ = true;
[email protected]1bf0fb22012-04-12 21:44:16101 // Balanced in On[Ppapi]ChannelOpened or OnError. Exactly one them will
102 // eventually be called, so we need to keep this object around until then.
[email protected]1464ce12011-12-08 11:14:32103 AddRef();
[email protected]1bf0fb22012-04-12 21:44:16104
105 PepperPluginInfo* pepper_info =
106 plugin_service->GetRegisteredPpapiPluginInfo(plugin_path);
107 if (pepper_info) {
[email protected]4cce3f3f2012-04-24 02:54:04108 plugin_name_ = pepper_info->name;
[email protected]1bf0fb22012-04-12 21:44:16109 // Use the broker since we run this function outside the sandbox.
[email protected]6be31d202013-02-01 18:20:54110 plugin_service->OpenChannelToPpapiBroker(0, plugin_path, this);
[email protected]1bf0fb22012-04-12 21:44:16111 } else {
112 plugin_service->OpenChannelToNpapiPlugin(
113 0, 0, GURL(), GURL(), mime_type, this);
114 }
[email protected]1464ce12011-12-08 11:14:32115 }
116
117 // Called when a timeout happens in order not to block the client
118 // indefinitely.
119 void OnTimeout() {
120 LOG_IF(ERROR, is_removing_) << "Timed out";
121 SignalDone();
[email protected]76b70f92011-11-21 19:31:14122 }
123
124 // PluginProcessHost::Client methods.
dchengc2282aa2014-10-21 12:07:58125 int ID() override {
[email protected]76b70f92011-11-21 19:31:14126 // Generate a unique identifier for this PluginProcessHostClient.
[email protected]4734d0b2011-12-03 07:10:44127 return ChildProcessHostImpl::GenerateChildProcessUniqueId();
[email protected]76b70f92011-11-21 19:31:14128 }
129
dchengc2282aa2014-10-21 12:07:58130 bool OffTheRecord() override { return false; }
[email protected]76b70f92011-11-21 19:31:14131
dchengc2282aa2014-10-21 12:07:58132 ResourceContext* GetResourceContext() override { return resource_context_; }
[email protected]76b70f92011-11-21 19:31:14133
dchengc2282aa2014-10-21 12:07:58134 void SetPluginInfo(const WebPluginInfo& info) override {}
[email protected]76b70f92011-11-21 19:31:14135
dchengc2282aa2014-10-21 12:07:58136 void OnFoundPluginProcessHost(PluginProcessHost* host) override {}
[email protected]76b70f92011-11-21 19:31:14137
dchengc2282aa2014-10-21 12:07:58138 void OnSentPluginChannelRequest() override {}
[email protected]76b70f92011-11-21 19:31:14139
dchengc2282aa2014-10-21 12:07:58140 void OnChannelOpened(const IPC::ChannelHandle& handle) override {
[email protected]1bf0fb22012-04-12 21:44:16141 ConnectToChannel(handle, false);
[email protected]76b70f92011-11-21 19:31:14142 // Balancing the AddRef call.
143 Release();
144 }
145
dchengc2282aa2014-10-21 12:07:58146 void OnError() override {
[email protected]791ce4ac2011-12-21 13:44:34147 LOG(ERROR) << "Couldn't open plugin channel";
[email protected]76b70f92011-11-21 19:31:14148 SignalDone();
149 // Balancing the AddRef call.
150 Release();
151 }
152
[email protected]1bf0fb22012-04-12 21:44:16153 // PpapiPluginProcessHost::BrokerClient implementation.
dchengc2282aa2014-10-21 12:07:58154 void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
155 int* renderer_id) override {
[email protected]54c23f12012-05-04 21:01:19156 *renderer_handle = base::kNullProcessHandle;
[email protected]1bf0fb22012-04-12 21:44:16157 *renderer_id = 0;
158 }
159
dchengc2282aa2014-10-21 12:07:58160 void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
161 base::ProcessId /* peer_pid */,
162 int /* child_id */) override {
[email protected]54c23f12012-05-04 21:01:19163 if (!channel_handle.name.empty())
[email protected]1bf0fb22012-04-12 21:44:16164 ConnectToChannel(channel_handle, true);
165
166 // Balancing the AddRef call.
167 Release();
168 }
169
[email protected]d84effeb2012-06-25 17:03:10170 // IPC::Listener methods.
dchengc2282aa2014-10-21 12:07:58171 bool OnMessageReceived(const IPC::Message& message) override {
[email protected]76b70f92011-11-21 19:31:14172 IPC_BEGIN_MESSAGE_MAP(Context, message)
[email protected]872f3a92013-05-21 08:16:08173 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ClearSiteDataResult,
[email protected]76b70f92011-11-21 19:31:14174 OnClearSiteDataResult)
[email protected]1bf0fb22012-04-12 21:44:16175 IPC_MESSAGE_HANDLER(PpapiHostMsg_ClearSiteDataResult,
[email protected]951ef0b2012-07-27 22:46:53176 OnPpapiClearSiteDataResult)
[email protected]76b70f92011-11-21 19:31:14177 IPC_MESSAGE_UNHANDLED_ERROR()
178 IPC_END_MESSAGE_MAP()
179
180 return true;
181 }
182
dchengc2282aa2014-10-21 12:07:58183 void OnChannelError() override {
[email protected]76b70f92011-11-21 19:31:14184 if (is_removing_) {
185 NOTREACHED() << "Channel error";
186 SignalDone();
187 }
188 }
189
[email protected]76b70f92011-11-21 19:31:14190 base::WaitableEvent* event() { return event_.get(); }
191
192 private:
[email protected]fb90c942012-04-27 23:40:50193 friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
194 friend class base::DeleteHelper<Context>;
dchengc2282aa2014-10-21 12:07:58195 ~Context() override {}
[email protected]fb90c942012-04-27 23:40:50196
[email protected]6d17f6392012-12-05 05:24:54197 IPC::Message* CreatePpapiClearSiteDataMsg(uint64 max_age) {
[email protected]2dec8ec2013-02-07 19:20:34198 base::FilePath profile_path =
[email protected]49511a72012-12-21 02:47:42199 PepperFlashFileMessageFilter::GetDataDirName(browser_context_path_);
[email protected]6d17f6392012-12-05 05:24:54200 // TODO(vtl): This "duplicates" logic in webkit/plugins/ppapi/file_path.cc
201 // (which prepends the plugin name to the relative part of the path
202 // instead, with the absolute, profile-dependent part being enforced by
203 // the browser).
204#if defined(OS_WIN)
[email protected]2dec8ec2013-02-07 19:20:34205 base::FilePath plugin_data_path =
[email protected]32956122013-12-25 07:29:24206 profile_path.Append(base::FilePath(base::UTF8ToUTF16(plugin_name_)));
[email protected]6d17f6392012-12-05 05:24:54207#else
[email protected]2dec8ec2013-02-07 19:20:34208 base::FilePath plugin_data_path =
209 profile_path.Append(base::FilePath(plugin_name_));
[email protected]6d17f6392012-12-05 05:24:54210#endif // defined(OS_WIN)
211 return new PpapiMsg_ClearSiteData(0u, plugin_data_path, std::string(),
212 kClearAllData, max_age);
213 }
[email protected]6d17f6392012-12-05 05:24:54214
tommyclie86b2982015-03-16 20:16:45215 // Connects the client side of a newly opened plugin channel.
[email protected]1bf0fb22012-04-12 21:44:16216 void ConnectToChannel(const IPC::ChannelHandle& handle, bool is_ppapi) {
mostynb4c27d042015-03-18 21:47:47217 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]76b70f92011-11-21 19:31:14218
219 // If we timed out, don't bother connecting.
220 if (!is_removing_)
221 return;
222
[email protected]1464ce12011-12-08 11:14:32223 DCHECK(!channel_.get());
[email protected]e482111a82014-05-30 03:58:59224 channel_ = IPC::Channel::CreateClient(handle, this);
[email protected]76b70f92011-11-21 19:31:14225 if (!channel_->Connect()) {
226 NOTREACHED() << "Couldn't connect to plugin";
227 SignalDone();
228 return;
229 }
230
[email protected]1bf0fb22012-04-12 21:44:16231 uint64 max_age = begin_time_.is_null() ?
232 std::numeric_limits<uint64>::max() :
233 (base::Time::Now() - begin_time_).InSeconds();
234
235 IPC::Message* msg;
236 if (is_ppapi) {
[email protected]6d17f6392012-12-05 05:24:54237 msg = CreatePpapiClearSiteDataMsg(max_age);
[email protected]1bf0fb22012-04-12 21:44:16238 } else {
[email protected]872f3a92013-05-21 08:16:08239 msg = new PluginProcessMsg_ClearSiteData(
240 std::string(), kClearAllData, max_age);
[email protected]1bf0fb22012-04-12 21:44:16241 }
242 if (!channel_->Send(msg)) {
[email protected]76b70f92011-11-21 19:31:14243 NOTREACHED() << "Couldn't send ClearSiteData message";
244 SignalDone();
245 return;
246 }
247 }
248
[email protected]951ef0b2012-07-27 22:46:53249 // Handles the PpapiHostMsg_ClearSiteDataResult message by delegating to the
[email protected]872f3a92013-05-21 08:16:08250 // PluginProcessHostMsg_ClearSiteDataResult handler.
[email protected]951ef0b2012-07-27 22:46:53251 void OnPpapiClearSiteDataResult(uint32 request_id, bool success) {
252 DCHECK_EQ(0u, request_id);
253 OnClearSiteDataResult(success);
254 }
255
[email protected]872f3a92013-05-21 08:16:08256 // Handles the PluginProcessHostMsg_ClearSiteDataResult message.
[email protected]76b70f92011-11-21 19:31:14257 void OnClearSiteDataResult(bool success) {
258 LOG_IF(ERROR, !success) << "ClearSiteData returned error";
259 UMA_HISTOGRAM_TIMES("ClearPluginData.time",
260 base::Time::Now() - remove_start_time_);
261 SignalDone();
262 }
263
[email protected]76b70f92011-11-21 19:31:14264 // Signals that we are finished with removing data (successful or not). This
265 // method is safe to call multiple times.
266 void SignalDone() {
mostynb4c27d042015-03-18 21:47:47267 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]76b70f92011-11-21 19:31:14268 if (!is_removing_)
269 return;
270 is_removing_ = false;
271 event_->Signal();
272 }
273
274 scoped_ptr<base::WaitableEvent> event_;
275 // The point in time when we start removing data.
276 base::Time remove_start_time_;
277 // The point in time from which on we remove data.
278 base::Time begin_time_;
279 bool is_removing_;
280
[email protected]1bf0fb22012-04-12 21:44:16281 // Path for the current profile. Must be retrieved on the UI thread from the
282 // browser context when we start so we can use it later on the I/O thread.
[email protected]2dec8ec2013-02-07 19:20:34283 base::FilePath browser_context_path_;
[email protected]1bf0fb22012-04-12 21:44:16284
285 // The resource context for the profile. Use only on the I/O thread.
286 ResourceContext* resource_context_;
[email protected]76b70f92011-11-21 19:31:14287
[email protected]4cce3f3f2012-04-24 02:54:04288 // The name of the plugin. Use only on the I/O thread.
289 std::string plugin_name_;
290
tommyclie86b2982015-03-16 20:16:45291 // The channel is NULL until we have opened a connection to the plugin
[email protected]76b70f92011-11-21 19:31:14292 // process.
[email protected]1464ce12011-12-08 11:14:32293 scoped_ptr<IPC::Channel> channel_;
[email protected]76b70f92011-11-21 19:31:14294};
295
296
[email protected]1bf0fb22012-04-12 21:44:16297PluginDataRemoverImpl::PluginDataRemoverImpl(BrowserContext* browser_context)
[email protected]c46cfe22012-09-27 22:11:55298 : mime_type_(kFlashPluginSwfMimeType),
[email protected]1bf0fb22012-04-12 21:44:16299 browser_context_(browser_context) {
[email protected]d8e682012011-11-17 18:31:54300}
301
302PluginDataRemoverImpl::~PluginDataRemoverImpl() {
[email protected]d8e682012011-11-17 18:31:54303}
304
305base::WaitableEvent* PluginDataRemoverImpl::StartRemoving(
306 base::Time begin_time) {
[email protected]76b70f92011-11-21 19:31:14307 DCHECK(!context_.get());
[email protected]1bf0fb22012-04-12 21:44:16308 context_ = new Context(begin_time, browser_context_);
[email protected]1464ce12011-12-08 11:14:32309 context_->Init(mime_type_);
[email protected]76b70f92011-11-21 19:31:14310 return context_->event();
[email protected]d8e682012011-11-17 18:31:54311}
[email protected]1bf0fb22012-04-12 21:44:16312
313} // namespace content