1 /*
2 * Copyright (C) 2011 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "WebPluginSiteDataManager.h"
28
29 #include "ImmutableArray.h"
30 #include "PluginProcessManager.h"
31 #include "WebContext.h"
32 #include "WebProcessMessages.h"
33
34 using namespace WebCore;
35
36 namespace WebKit {
37
38 #if ENABLE(PLUGIN_PROCESS)
39 class WebPluginSiteDataManager::GetSitesWithDataState {
40 public:
GetSitesWithDataState(WebPluginSiteDataManager * webPluginSiteDataManager,uint64_t callbackID)41 explicit GetSitesWithDataState(WebPluginSiteDataManager* webPluginSiteDataManager, uint64_t callbackID)
42 : m_webPluginSiteDataManager(webPluginSiteDataManager)
43 , m_callbackID(callbackID)
44 , m_plugins(webPluginSiteDataManager->m_webContext->pluginInfoStore()->plugins())
45 {
46 }
47
getSitesWithDataForNextPlugin()48 void getSitesWithDataForNextPlugin()
49 {
50 if (m_plugins.isEmpty()) {
51 Vector<String> sites;
52 copyToVector(m_sites, sites);
53
54 m_webPluginSiteDataManager->didGetSitesWithDataForAllPlugins(sites, m_callbackID);
55 return;
56 }
57
58 PluginProcessManager::shared().getSitesWithData(m_plugins.last(), m_webPluginSiteDataManager, m_callbackID);
59 m_plugins.removeLast();
60 }
61
didGetSitesWithDataForSinglePlugin(const Vector<String> & sites)62 void didGetSitesWithDataForSinglePlugin(const Vector<String>& sites)
63 {
64 for (size_t i = 0; i < sites.size(); ++i)
65 m_sites.add(sites[i]);
66
67 getSitesWithDataForNextPlugin();
68 }
69
70 private:
71 WebPluginSiteDataManager* m_webPluginSiteDataManager;
72 uint64_t m_callbackID;
73 Vector<PluginInfoStore::Plugin> m_plugins;
74 HashSet<String> m_sites;
75 };
76
77 class WebPluginSiteDataManager::ClearSiteDataState {
78 public:
ClearSiteDataState(WebPluginSiteDataManager * webPluginSiteDataManager,const Vector<String> & sites,uint64_t flags,uint64_t maxAgeInSeconds,uint64_t callbackID)79 explicit ClearSiteDataState(WebPluginSiteDataManager* webPluginSiteDataManager, const Vector<String>& sites, uint64_t flags, uint64_t maxAgeInSeconds, uint64_t callbackID)
80 : m_webPluginSiteDataManager(webPluginSiteDataManager)
81 , m_sites(sites)
82 , m_flags(flags)
83 , m_maxAgeInSeconds(maxAgeInSeconds)
84 , m_callbackID(callbackID)
85 , m_plugins(webPluginSiteDataManager->m_webContext->pluginInfoStore()->plugins())
86 {
87 }
88
clearSiteDataForNextPlugin()89 void clearSiteDataForNextPlugin()
90 {
91 if (m_plugins.isEmpty()) {
92 m_webPluginSiteDataManager->didClearSiteDataForAllPlugins(m_callbackID);
93 return;
94 }
95
96 PluginProcessManager::shared().clearSiteData(m_plugins.last(), m_webPluginSiteDataManager, m_sites, m_flags, m_maxAgeInSeconds, m_callbackID);
97 m_plugins.removeLast();
98 }
99
didClearSiteDataForSinglePlugin()100 void didClearSiteDataForSinglePlugin()
101 {
102 clearSiteDataForNextPlugin();
103 }
104
105 private:
106 WebPluginSiteDataManager* m_webPluginSiteDataManager;
107 Vector<String> m_sites;
108 uint64_t m_flags;
109 uint64_t m_maxAgeInSeconds;
110 uint64_t m_callbackID;
111 Vector<PluginInfoStore::Plugin> m_plugins;
112 };
113 #endif // ENABLE(PLUGIN_PROCESS)
114
create(WebContext * webContext)115 PassRefPtr<WebPluginSiteDataManager> WebPluginSiteDataManager::create(WebContext* webContext)
116 {
117 return adoptRef(new WebPluginSiteDataManager(webContext));
118 }
119
WebPluginSiteDataManager(WebContext * webContext)120 WebPluginSiteDataManager::WebPluginSiteDataManager(WebContext* webContext)
121 : m_webContext(webContext)
122 {
123 }
124
~WebPluginSiteDataManager()125 WebPluginSiteDataManager::~WebPluginSiteDataManager()
126 {
127 ASSERT(m_arrayCallbacks.isEmpty());
128 ASSERT(m_voidCallbacks.isEmpty());
129 #if ENABLE(PLUGIN_PROCESS)
130 ASSERT(m_pendingGetSitesWithData.isEmpty());
131 ASSERT(m_pendingClearSiteData.isEmpty());
132 #endif
133 }
134
invalidate()135 void WebPluginSiteDataManager::invalidate()
136 {
137 invalidateCallbackMap(m_arrayCallbacks);
138
139 #if ENABLE(PLUGIN_PROCESS)
140 deleteAllValues(m_pendingGetSitesWithData);
141 m_pendingGetSitesWithData.clear();
142 deleteAllValues(m_pendingClearSiteData);
143 m_pendingClearSiteData.clear();
144 #endif
145 }
146
getSitesWithData(PassRefPtr<ArrayCallback> prpCallback)147 void WebPluginSiteDataManager::getSitesWithData(PassRefPtr<ArrayCallback> prpCallback)
148 {
149 RefPtr<ArrayCallback> callback = prpCallback;
150
151 if (!m_webContext) {
152 callback->invalidate();
153 return;
154 }
155
156 uint64_t callbackID = callback->callbackID();
157 m_arrayCallbacks.set(callbackID, callback.release());
158
159 #if ENABLE(PLUGIN_PROCESS)
160 ASSERT(!m_pendingGetSitesWithData.contains(callbackID));
161
162 GetSitesWithDataState* state = new GetSitesWithDataState(this, callbackID);
163 m_pendingGetSitesWithData.set(callbackID, state);
164 state->getSitesWithDataForNextPlugin();
165 #else
166 m_webContext->relaunchProcessIfNecessary();
167
168 Vector<String> pluginPaths;
169 m_webContext->pluginInfoStore()->getPluginPaths(pluginPaths);
170
171 // FIXME (Multi-WebProcess): When multi-process is enabled, we must always use a plug-in process for this,
172 // so this code should just be removed.
173 m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebProcess::GetSitesWithPluginData(pluginPaths, callbackID));
174 #endif
175 }
176
didGetSitesWithData(const Vector<String> & sites,uint64_t callbackID)177 void WebPluginSiteDataManager::didGetSitesWithData(const Vector<String>& sites, uint64_t callbackID)
178 {
179 RefPtr<ArrayCallback> callback = m_arrayCallbacks.take(callbackID);
180 if (!callback) {
181 // FIXME: Log error or assert.
182 return;
183 }
184
185 Vector<RefPtr<APIObject> > sitesWK(sites.size());
186
187 for (size_t i = 0; i < sites.size(); ++i)
188 sitesWK[i] = WebString::create(sites[i]);
189
190 RefPtr<ImmutableArray> resultArray = ImmutableArray::adopt(sitesWK);
191 callback->performCallbackWithReturnValue(resultArray.get());
192 }
193
clearSiteData(ImmutableArray * sites,uint64_t flags,uint64_t maxAgeInSeconds,PassRefPtr<VoidCallback> prpCallback)194 void WebPluginSiteDataManager::clearSiteData(ImmutableArray* sites, uint64_t flags, uint64_t maxAgeInSeconds, PassRefPtr<VoidCallback> prpCallback)
195 {
196 RefPtr<VoidCallback> callback = prpCallback;
197 if (!m_webContext) {
198 callback->invalidate();
199 return;
200 }
201
202 Vector<String> sitesVector;
203
204 // If the array is empty, don't do anything.
205 if (sites) {
206 if (!sites->size()) {
207 callback->performCallback();
208 return;
209 }
210
211 for (size_t i = 0; i < sites->size(); ++i) {
212 if (WebString* site = sites->at<WebString>(i))
213 sitesVector.append(site->string());
214 }
215 }
216
217 uint64_t callbackID = callback->callbackID();
218 m_voidCallbacks.set(callbackID, callback.release());
219
220 #if ENABLE(PLUGIN_PROCESS)
221 ASSERT(!m_pendingClearSiteData.contains(callbackID));
222
223 ClearSiteDataState* state = new ClearSiteDataState(this, sitesVector, flags, maxAgeInSeconds, callbackID);
224 m_pendingClearSiteData.set(callbackID, state);
225 state->clearSiteDataForNextPlugin();
226 #else
227
228 m_webContext->relaunchProcessIfNecessary();
229 Vector<String> pluginPaths;
230 m_webContext->pluginInfoStore()->getPluginPaths(pluginPaths);
231
232 // FIXME (Multi-WebProcess): When multi-process is enabled, we must always use a plug-in process for this,
233 // so this code should just be removed.
234 m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebProcess::ClearPluginSiteData(pluginPaths, sitesVector, flags, maxAgeInSeconds, callbackID));
235 #endif
236 }
237
didClearSiteData(uint64_t callbackID)238 void WebPluginSiteDataManager::didClearSiteData(uint64_t callbackID)
239 {
240 RefPtr<VoidCallback> callback = m_voidCallbacks.take(callbackID);
241 if (!callback) {
242 // FIXME: Log error or assert.
243 return;
244 }
245
246 callback->performCallback();
247 }
248
shouldTerminate(WebProcessProxy *) const249 bool WebPluginSiteDataManager::shouldTerminate(WebProcessProxy*) const
250 {
251 #if ENABLE(PLUGIN_PROCESS)
252 // When out of process plug-ins are enabled, the web process is not involved in fetching site data.
253 return true;
254 #else
255 return m_arrayCallbacks.isEmpty() && m_voidCallbacks.isEmpty();
256 #endif
257 }
258
259 #if ENABLE(PLUGIN_PROCESS)
didGetSitesWithDataForSinglePlugin(const Vector<String> & sites,uint64_t callbackID)260 void WebPluginSiteDataManager::didGetSitesWithDataForSinglePlugin(const Vector<String>& sites, uint64_t callbackID)
261 {
262 GetSitesWithDataState* state = m_pendingGetSitesWithData.get(callbackID);
263 ASSERT(state);
264
265 state->didGetSitesWithDataForSinglePlugin(sites);
266 }
267
didGetSitesWithDataForAllPlugins(const Vector<String> & sites,uint64_t callbackID)268 void WebPluginSiteDataManager::didGetSitesWithDataForAllPlugins(const Vector<String>& sites, uint64_t callbackID)
269 {
270 OwnPtr<GetSitesWithDataState> state = adoptPtr(m_pendingGetSitesWithData.take(callbackID));
271 ASSERT(state);
272
273 didGetSitesWithData(sites, callbackID);
274 }
275
didClearSiteDataForSinglePlugin(uint64_t callbackID)276 void WebPluginSiteDataManager::didClearSiteDataForSinglePlugin(uint64_t callbackID)
277 {
278 ClearSiteDataState* state = m_pendingClearSiteData.get(callbackID);
279 ASSERT(state);
280
281 state->didClearSiteDataForSinglePlugin();
282 }
283
didClearSiteDataForAllPlugins(uint64_t callbackID)284 void WebPluginSiteDataManager::didClearSiteDataForAllPlugins(uint64_t callbackID)
285 {
286 OwnPtr<ClearSiteDataState> state = adoptPtr(m_pendingClearSiteData.take(callbackID));
287 ASSERT(state);
288
289 didClearSiteData(callbackID);
290 }
291
292 #endif
293
294 } // namespace WebKit
295
296