OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/plugin_data_remover.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/command_line.h" | |
9 #include "base/message_loop_proxy.h" | |
10 #include "base/metrics/histogram.h" | |
11 #include "base/synchronization/waitable_event.h" | |
12 #include "base/version.h" | |
13 #include "chrome/browser/plugin_prefs.h" | |
14 #include "chrome/browser/profiles/profile.h" | |
15 #include "chrome/common/chrome_switches.h" | |
16 #include "content/browser/plugin_service.h" | |
17 #include "content/common/plugin_messages.h" | |
18 #include "content/public/browser/browser_thread.h" | |
19 #include "webkit/plugins/npapi/plugin_group.h" | |
20 | |
21 #if defined(OS_POSIX) | |
22 #include "ipc/ipc_channel_posix.h" | |
23 #endif | |
24 | |
25 using content::BrowserThread; | |
26 | |
27 namespace { | |
28 | |
29 const char kFlashMimeType[] = "application/x-shockwave-flash"; | |
30 // The minimum Flash Player version that implements NPP_ClearSiteData. | |
31 const char kMinFlashVersion[] = "10.3"; | |
32 const int64 kRemovalTimeoutMs = 10000; | |
33 const uint64 kClearAllData = 0; | |
34 | |
35 } // namespace | |
36 | |
37 PluginDataRemover::PluginDataRemover(Profile* profile) | |
38 : mime_type_(kFlashMimeType), | |
39 is_removing_(false), | |
40 context_(profile->GetResourceContext()), | |
41 event_(new base::WaitableEvent(true, false)), | |
42 channel_(NULL) { | |
43 } | |
44 | |
45 PluginDataRemover::~PluginDataRemover() { | |
46 DCHECK(!is_removing_); | |
47 if (channel_) | |
48 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, channel_); | |
49 } | |
50 | |
51 base::WaitableEvent* PluginDataRemover::StartRemoving(base::Time begin_time) { | |
52 DCHECK(!is_removing_); | |
53 remove_start_time_ = base::Time::Now(); | |
54 begin_time_ = begin_time; | |
55 | |
56 is_removing_ = true; | |
57 | |
58 // Balanced in OnChannelOpened or OnError. Exactly one them will eventually be | |
59 // called, so we need to keep this object around until then. | |
60 AddRef(); | |
61 PluginService::GetInstance()->OpenChannelToNpapiPlugin( | |
62 0, 0, GURL(), GURL(), mime_type_, this); | |
63 | |
64 BrowserThread::PostDelayedTask( | |
65 BrowserThread::IO, | |
66 FROM_HERE, | |
67 base::Bind(&PluginDataRemover::OnTimeout, this), | |
68 kRemovalTimeoutMs); | |
69 | |
70 return event_.get(); | |
71 } | |
72 | |
73 void PluginDataRemover::Wait() { | |
74 base::Time start_time(base::Time::Now()); | |
75 if (is_removing_) | |
76 event_->Wait(); | |
77 UMA_HISTOGRAM_TIMES("ClearPluginData.wait_at_shutdown", | |
78 base::Time::Now() - start_time); | |
79 UMA_HISTOGRAM_TIMES("ClearPluginData.time_at_shutdown", | |
80 base::Time::Now() - remove_start_time_); | |
81 } | |
82 | |
83 int PluginDataRemover::ID() { | |
84 // Generate a unique identifier for this PluginProcessHostClient. | |
85 return ChildProcessInfo::GenerateChildProcessUniqueId(); | |
86 } | |
87 | |
88 bool PluginDataRemover::OffTheRecord() { | |
89 return false; | |
90 } | |
91 | |
92 const content::ResourceContext& PluginDataRemover::GetResourceContext() { | |
93 return context_; | |
94 } | |
95 | |
96 void PluginDataRemover::SetPluginInfo( | |
97 const webkit::WebPluginInfo& info) { | |
98 } | |
99 | |
100 void PluginDataRemover::OnFoundPluginProcessHost( | |
101 PluginProcessHost* host) { | |
102 } | |
103 | |
104 void PluginDataRemover::OnSentPluginChannelRequest() { | |
105 } | |
106 | |
107 void PluginDataRemover::OnChannelOpened(const IPC::ChannelHandle& handle) { | |
108 ConnectToChannel(handle); | |
109 // Balancing the AddRef call in StartRemoving. | |
110 Release(); | |
111 } | |
112 | |
113 void PluginDataRemover::ConnectToChannel(const IPC::ChannelHandle& handle) { | |
114 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
115 | |
116 // If we timed out, don't bother connecting. | |
117 if (!is_removing_) | |
118 return; | |
119 | |
120 DCHECK(!channel_); | |
121 channel_ = new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this); | |
122 if (!channel_->Connect()) { | |
123 NOTREACHED() << "Couldn't connect to plugin"; | |
124 SignalDone(); | |
125 return; | |
126 } | |
127 | |
128 if (!channel_->Send(new PluginMsg_ClearSiteData(std::string(), | |
129 kClearAllData, | |
130 begin_time_))) { | |
131 NOTREACHED() << "Couldn't send ClearSiteData message"; | |
132 SignalDone(); | |
133 return; | |
134 } | |
135 } | |
136 | |
137 void PluginDataRemover::OnError() { | |
138 LOG(DFATAL) << "Couldn't open plugin channel"; | |
139 SignalDone(); | |
140 // Balancing the AddRef call in StartRemoving. | |
141 Release(); | |
142 } | |
143 | |
144 void PluginDataRemover::OnClearSiteDataResult(bool success) { | |
145 LOG_IF(ERROR, !success) << "ClearSiteData returned error"; | |
146 UMA_HISTOGRAM_TIMES("ClearPluginData.time", | |
147 base::Time::Now() - remove_start_time_); | |
148 SignalDone(); | |
149 } | |
150 | |
151 void PluginDataRemover::OnTimeout() { | |
152 LOG_IF(ERROR, is_removing_) << "Timed out"; | |
153 SignalDone(); | |
154 } | |
155 | |
156 bool PluginDataRemover::OnMessageReceived(const IPC::Message& msg) { | |
157 IPC_BEGIN_MESSAGE_MAP(PluginDataRemover, msg) | |
158 IPC_MESSAGE_HANDLER(PluginHostMsg_ClearSiteDataResult, | |
159 OnClearSiteDataResult) | |
160 IPC_MESSAGE_UNHANDLED_ERROR() | |
161 IPC_END_MESSAGE_MAP() | |
162 | |
163 return true; | |
164 } | |
165 | |
166 void PluginDataRemover::OnChannelError() { | |
167 if (is_removing_) { | |
168 NOTREACHED() << "Channel error"; | |
169 SignalDone(); | |
170 } | |
171 } | |
172 | |
173 void PluginDataRemover::SignalDone() { | |
174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
175 if (!is_removing_) | |
176 return; | |
177 is_removing_ = false; | |
178 event_->Signal(); | |
179 } | |
180 | |
181 // static | |
182 bool PluginDataRemover::IsSupported(PluginPrefs* plugin_prefs) { | |
183 bool allow_wildcard = false; | |
184 std::vector<webkit::WebPluginInfo> plugins; | |
185 PluginService::GetInstance()->GetPluginInfoArray( | |
186 GURL(), kFlashMimeType, allow_wildcard, &plugins, NULL); | |
187 std::vector<webkit::WebPluginInfo>::iterator plugin = plugins.begin(); | |
188 if (plugin == plugins.end()) | |
189 return false; | |
190 scoped_ptr<Version> version( | |
191 webkit::npapi::PluginGroup::CreateVersionFromString(plugin->version)); | |
192 scoped_ptr<Version> min_version(Version::GetVersionFromString( | |
193 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
194 switches::kMinClearSiteDataFlashVersion))); | |
195 if (!min_version.get()) | |
196 min_version.reset(Version::GetVersionFromString(kMinFlashVersion)); | |
197 return plugin_prefs->IsPluginEnabled(*plugin) && | |
198 version.get() && | |
199 min_version->CompareTo(*version) == -1; | |
200 } | |
OLD | NEW |