172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// found in the LICENSE file.
4201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/plugin_data_remover.h"
6201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/command_line.h"
8201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "base/message_loop_proxy.h"
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/metrics/histogram.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/synchronization/waitable_event.h"
1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/version.h"
1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/common/chrome_switches.h"
13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/plugin_service.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/plugin_messages.h"
1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "webkit/plugins/npapi/plugin_group.h"
1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "webkit/plugins/npapi/plugin_list.h"
18201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
19201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#if defined(OS_POSIX)
20201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "ipc/ipc_channel_posix.h"
21201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#endif
22201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
23201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochnamespace {
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst char* kFlashMimeType = "application/x-shockwave-flash";
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// The minimum Flash Player version that implements NPP_ClearSiteData.
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst char* kMinFlashVersion = "10.3";
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst int64 kRemovalTimeoutMs = 10000;
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst uint64 kClearAllData = 0;
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}  // namespace
32201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
33201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochPluginDataRemover::PluginDataRemover()
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : mime_type_(kFlashMimeType),
3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      is_removing_(false),
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      event_(new base::WaitableEvent(true, false)),
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      channel_(NULL) {
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
39201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
40201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochPluginDataRemover::~PluginDataRemover() {
4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(!is_removing_);
4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (channel_)
4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, channel_);
44201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
45201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbase::WaitableEvent* PluginDataRemover::StartRemoving(base::Time begin_time) {
4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(!is_removing_);
4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  remove_start_time_ = base::Time::Now();
49201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  begin_time_ = begin_time;
50201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  is_removing_ = true;
52201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Balanced in OnChannelOpened or OnError. Exactly one them will eventually be
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // called, so we need to keep this object around until then.
5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  AddRef();
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  PluginService::GetInstance()->OpenChannelToNpapiPlugin(
5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      0, 0, GURL(), mime_type_, this);
58201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
59201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  BrowserThread::PostDelayedTask(
60201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      BrowserThread::IO,
61201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      FROM_HERE,
6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      NewRunnableMethod(this, &PluginDataRemover::OnTimeout),
6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      kRemovalTimeoutMs);
6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return event_.get();
6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid PluginDataRemover::Wait() {
6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::Time start_time(base::Time::Now());
7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool result = true;
7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (is_removing_)
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    result = event_->Wait();
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  UMA_HISTOGRAM_TIMES("ClearPluginData.wait_at_shutdown",
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                      base::Time::Now() - start_time);
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  UMA_HISTOGRAM_TIMES("ClearPluginData.time_at_shutdown",
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                      base::Time::Now() - remove_start_time_);
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(result) << "Error waiting for plugin process";
78201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
79201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
80201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochint PluginDataRemover::ID() {
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Generate a unique identifier for this PluginProcessHostClient.
82201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return ChildProcessInfo::GenerateChildProcessUniqueId();
83201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
84201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
85201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool PluginDataRemover::OffTheRecord() {
86201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return false;
87201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
88201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid PluginDataRemover::SetPluginInfo(
9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const webkit::npapi::WebPluginInfo& info) {
91201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
92201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
93201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PluginDataRemover::OnChannelOpened(const IPC::ChannelHandle& handle) {
9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ConnectToChannel(handle);
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Balancing the AddRef call in StartRemoving.
9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  Release();
9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid PluginDataRemover::ConnectToChannel(const IPC::ChannelHandle& handle) {
100201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // If we timed out, don't bother connecting.
10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!is_removing_)
10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return;
10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
106201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(!channel_);
10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  channel_ = new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this);
108201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!channel_->Connect()) {
10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NOTREACHED() << "Couldn't connect to plugin";
110201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    SignalDone();
111201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
112201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
113201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!channel_->Send(new PluginMsg_ClearSiteData(std::string(),
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                  kClearAllData,
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                  begin_time_))) {
11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NOTREACHED() << "Couldn't send ClearSiteData message";
118201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    SignalDone();
11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
120201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
121201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
122201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
123201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PluginDataRemover::OnError() {
12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  LOG(DFATAL) << "Couldn't open plugin channel";
125201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SignalDone();
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Balancing the AddRef call in StartRemoving.
12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  Release();
128201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
129201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
130201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PluginDataRemover::OnClearSiteDataResult(bool success) {
13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  LOG_IF(DFATAL, !success) << "ClearSiteData returned error";
13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UMA_HISTOGRAM_TIMES("ClearPluginData.time",
13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                      base::Time::Now() - remove_start_time_);
134201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SignalDone();
135201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
136201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
137201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PluginDataRemover::OnTimeout() {
13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  LOG_IF(DFATAL, is_removing_) << "Timed out";
139201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SignalDone();
140201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
141201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
14221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool PluginDataRemover::OnMessageReceived(const IPC::Message& msg) {
143201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  IPC_BEGIN_MESSAGE_MAP(PluginDataRemover, msg)
144201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    IPC_MESSAGE_HANDLER(PluginHostMsg_ClearSiteDataResult,
145201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        OnClearSiteDataResult)
146201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    IPC_MESSAGE_UNHANDLED_ERROR()
147201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  IPC_END_MESSAGE_MAP()
14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return true;
150201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
151201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
152201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PluginDataRemover::OnChannelError() {
15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (is_removing_) {
15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NOTREACHED() << "Channel error";
15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SignalDone();
15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
157201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
158201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
159201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid PluginDataRemover::SignalDone() {
160201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
16121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!is_removing_)
162201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
16321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  is_removing_ = false;
16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  event_->Signal();
16521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// static
16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool PluginDataRemover::IsSupported() {
16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  bool allow_wildcard = false;
17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  webkit::npapi::WebPluginInfo plugin;
17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::string mime_type;
17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!webkit::npapi::PluginList::Singleton()->GetPluginInfo(
17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          GURL(), kFlashMimeType, allow_wildcard, &plugin, &mime_type)) {
17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return false;
17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  scoped_ptr<Version> version(
17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      webkit::npapi::PluginGroup::CreateVersionFromString(plugin.version));
17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  scoped_ptr<Version> min_version(Version::GetVersionFromString(
18072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          switches::kMinClearSiteDataFlashVersion)));
18272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!min_version.get())
18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    min_version.reset(Version::GetVersionFromString(kMinFlashVersion));
18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return webkit::npapi::IsPluginEnabled(plugin) &&
18521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         version.get() &&
18621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         min_version->CompareTo(*version) == -1;
187201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
188