2fb5441360c40b9e40ebe411e6ea1592ce035518
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebCoreSupport / WebPlatformStrategies.cpp
1 /*
2  * Copyright (C) 2010, 2011, 2012 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 "WebPlatformStrategies.h"
28
29 #include "BlockingResponseMap.h"
30 #include "DataReference.h"
31 #include "NetworkResourceLoadParameters.h"
32 #include "PluginInfoStore.h"
33 #include "StorageNamespaceImpl.h"
34 #include "WebContextMessages.h"
35 #include "WebCookieManager.h"
36 #include "WebCoreArgumentCoders.h"
37 #include "WebErrors.h"
38 #include "WebPage.h"
39 #include "WebProcess.h"
40 #include "WebProcessProxyMessages.h"
41 #include <WebCore/Color.h>
42 #include <WebCore/KURL.h>
43 #include <WebCore/LoaderStrategy.h>
44 #include <WebCore/NetworkStorageSession.h>
45 #include <WebCore/NetworkingContext.h>
46 #include <WebCore/Page.h>
47 #include <WebCore/PageGroup.h>
48 #include <WebCore/PlatformCookieJar.h>
49 #include <WebCore/PlatformPasteboard.h>
50 #include <WebCore/ResourceError.h>
51 #include <WebCore/StorageNamespace.h>
52 #include <wtf/Atomics.h>
53
54 #if ENABLE(NETWORK_PROCESS)
55 #include "BlobRegistryProxy.h"
56 #include "NetworkConnectionToWebProcessMessages.h"
57 #include "NetworkProcessConnection.h"
58 #include "WebResourceLoadScheduler.h"
59 #endif
60
61 // FIXME: Remove this #ifdef once we don't need the ability to turn the feature off.
62 #define ENABLE_UI_PROCESS_STORAGE 1
63
64 using namespace WebCore;
65
66 namespace WebKit {
67
68 void WebPlatformStrategies::initialize()
69 {
70     DEFINE_STATIC_LOCAL(WebPlatformStrategies, platformStrategies, ());
71     setPlatformStrategies(&platformStrategies);
72 }
73
74 WebPlatformStrategies::WebPlatformStrategies()
75 #if ENABLE(NETSCAPE_PLUGIN_API)
76     : m_pluginCacheIsPopulated(false)
77     , m_shouldRefreshPlugins(false)
78 #endif // ENABLE(NETSCAPE_PLUGIN_API)
79 {
80 }
81
82 CookiesStrategy* WebPlatformStrategies::createCookiesStrategy()
83 {
84     return this;
85 }
86
87 DatabaseStrategy* WebPlatformStrategies::createDatabaseStrategy()
88 {
89     return this;
90 }
91
92 LoaderStrategy* WebPlatformStrategies::createLoaderStrategy()
93 {
94     return this;
95 }
96
97 PasteboardStrategy* WebPlatformStrategies::createPasteboardStrategy()
98 {
99     return this;
100 }
101
102 PluginStrategy* WebPlatformStrategies::createPluginStrategy()
103 {
104     return this;
105 }
106
107 SharedWorkerStrategy* WebPlatformStrategies::createSharedWorkerStrategy()
108 {
109     return this;
110 }
111
112 StorageStrategy* WebPlatformStrategies::createStorageStrategy()
113 {
114     return this;
115 }
116
117 VisitedLinkStrategy* WebPlatformStrategies::createVisitedLinkStrategy()
118 {
119     return this;
120 }
121
122 // CookiesStrategy
123
124 String WebPlatformStrategies::cookiesForDOM(const NetworkStorageSession& session, const KURL& firstParty, const KURL& url)
125 {
126 #if ENABLE(NETWORK_PROCESS)
127     if (WebProcess::shared().usesNetworkProcess()) {
128         String result;
129         if (!WebProcess::shared().networkConnection()->connection()->sendSync(Messages::NetworkConnectionToWebProcess::CookiesForDOM(session.isPrivateBrowsingSession(), firstParty, url), Messages::NetworkConnectionToWebProcess::CookiesForDOM::Reply(result), 0))
130             return String();
131         return result;
132     }
133 #endif
134
135     return WebCore::cookiesForDOM(session, firstParty, url);
136 }
137
138 void WebPlatformStrategies::setCookiesFromDOM(const NetworkStorageSession& session, const KURL& firstParty, const KURL& url, const String& cookieString)
139 {
140 #if ENABLE(NETWORK_PROCESS)
141     if (WebProcess::shared().usesNetworkProcess()) {
142         WebProcess::shared().networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::SetCookiesFromDOM(session.isPrivateBrowsingSession(), firstParty, url, cookieString), 0);
143         return;
144     }
145 #endif
146
147     WebCore::setCookiesFromDOM(session, firstParty, url, cookieString);
148 }
149
150 bool WebPlatformStrategies::cookiesEnabled(const NetworkStorageSession& session, const KURL& firstParty, const KURL& url)
151 {
152 #if ENABLE(NETWORK_PROCESS)
153     if (WebProcess::shared().usesNetworkProcess()) {
154         bool result;
155         if (!WebProcess::shared().networkConnection()->connection()->sendSync(Messages::NetworkConnectionToWebProcess::CookiesEnabled(session.isPrivateBrowsingSession(), firstParty, url), Messages::NetworkConnectionToWebProcess::CookiesEnabled::Reply(result), 0))
156             return false;
157         return result;
158     }
159 #endif
160
161     return WebCore::cookiesEnabled(session, firstParty, url);
162 }
163
164 String WebPlatformStrategies::cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const KURL& firstParty, const KURL& url)
165 {
166 #if ENABLE(NETWORK_PROCESS)
167     if (WebProcess::shared().usesNetworkProcess()) {
168         String result;
169         if (!WebProcess::shared().networkConnection()->connection()->sendSync(Messages::NetworkConnectionToWebProcess::CookieRequestHeaderFieldValue(session.isPrivateBrowsingSession(), firstParty, url), Messages::NetworkConnectionToWebProcess::CookieRequestHeaderFieldValue::Reply(result), 0))
170             return String();
171         return result;
172     }
173 #endif
174
175     return WebCore::cookieRequestHeaderFieldValue(session, firstParty, url);
176 }
177
178 bool WebPlatformStrategies::getRawCookies(const NetworkStorageSession& session, const KURL& firstParty, const KURL& url, Vector<Cookie>& rawCookies)
179 {
180 #if ENABLE(NETWORK_PROCESS)
181     if (WebProcess::shared().usesNetworkProcess()) {
182         if (!WebProcess::shared().networkConnection()->connection()->sendSync(Messages::NetworkConnectionToWebProcess::GetRawCookies(session.isPrivateBrowsingSession(), firstParty, url), Messages::NetworkConnectionToWebProcess::GetRawCookies::Reply(rawCookies), 0))
183             return false;
184         return true;
185     }
186 #endif
187
188     return WebCore::getRawCookies(session, firstParty, url, rawCookies);
189 }
190
191 void WebPlatformStrategies::deleteCookie(const NetworkStorageSession& session, const KURL& url, const String& cookieName)
192 {
193 #if ENABLE(NETWORK_PROCESS)
194     if (WebProcess::shared().usesNetworkProcess()) {
195         WebProcess::shared().networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::DeleteCookie(session.isPrivateBrowsingSession(), url, cookieName), 0);
196         return;
197     }
198 #endif
199
200     WebCore::deleteCookie(session, url, cookieName);
201 }
202
203 // DatabaseStrategy
204
205 #if ENABLE(SQL_DATABASE)
206 AbstractDatabaseServer* WebPlatformStrategies::getDatabaseServer()
207 {
208     return DatabaseStrategy::getDatabaseServer(); // Use the default for now.
209 }
210 #endif
211
212 // LoaderStrategy
213
214 #if ENABLE(NETWORK_PROCESS)
215 ResourceLoadScheduler* WebPlatformStrategies::resourceLoadScheduler()
216 {
217     static ResourceLoadScheduler* scheduler;
218     if (!scheduler) {
219         if (WebProcess::shared().usesNetworkProcess())
220             scheduler = &WebProcess::shared().webResourceLoadScheduler();
221         else
222             scheduler = WebCore::resourceLoadScheduler();
223     }
224     
225     return scheduler;
226 }
227
228 void WebPlatformStrategies::loadResourceSynchronously(NetworkingContext* context, unsigned long resourceLoadIdentifier, const ResourceRequest& request, StoredCredentials storedCredentials, ClientCredentialPolicy clientCredentialPolicy, ResourceError& error, ResourceResponse& response, Vector<char>& data)
229 {
230     if (!WebProcess::shared().usesNetworkProcess()) {
231         LoaderStrategy::loadResourceSynchronously(context, resourceLoadIdentifier, request, storedCredentials, clientCredentialPolicy, error, response, data);
232         return;
233     }
234
235     CoreIPC::DataReference dataReference;
236
237     NetworkResourceLoadParameters loadParameters;
238     loadParameters.identifier = resourceLoadIdentifier;
239     loadParameters.request = request;
240     loadParameters.priority = ResourceLoadPriorityHighest;
241     loadParameters.contentSniffingPolicy = SniffContent;
242     loadParameters.allowStoredCredentials = storedCredentials;
243     loadParameters.clientCredentialPolicy = clientCredentialPolicy;
244     loadParameters.inPrivateBrowsingMode = context->storageSession().isPrivateBrowsingSession();
245     loadParameters.shouldClearReferrerOnHTTPSToHTTPRedirect = context->shouldClearReferrerOnHTTPSToHTTPRedirect();
246
247     if (!WebProcess::shared().networkConnection()->connection()->sendSync(Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad(loadParameters), Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::Reply(error, response, dataReference), 0)) {
248         response = ResourceResponse();
249         error = internalError(request.url());
250         data.resize(0);
251
252         return;
253     }
254
255     data.resize(dataReference.size());
256     memcpy(data.data(), dataReference.data(), dataReference.size());
257 }
258
259 #if ENABLE(BLOB)
260 BlobRegistry* WebPlatformStrategies::createBlobRegistry()
261 {
262     if (!WebProcess::shared().usesNetworkProcess())
263         return LoaderStrategy::createBlobRegistry();
264     return new BlobRegistryProxy;    
265 }
266 #endif
267 #endif
268
269 // PluginStrategy
270
271 void WebPlatformStrategies::refreshPlugins()
272 {
273 #if ENABLE(NETSCAPE_PLUGIN_API)
274     m_cachedPlugins.clear();
275     m_pluginCacheIsPopulated = false;
276     m_shouldRefreshPlugins = true;
277
278     populatePluginCache();
279 #endif // ENABLE(NETSCAPE_PLUGIN_API)
280 }
281
282 void WebPlatformStrategies::getPluginInfo(const WebCore::Page*, Vector<WebCore::PluginInfo>& plugins)
283 {
284 #if ENABLE(NETSCAPE_PLUGIN_API)
285     populatePluginCache();
286     plugins = m_cachedPlugins;
287 #endif // ENABLE(NETSCAPE_PLUGIN_API)
288 }
289
290 #if ENABLE(NETSCAPE_PLUGIN_API)
291 void WebPlatformStrategies::populatePluginCache()
292 {
293     if (m_pluginCacheIsPopulated)
294         return;
295
296     ASSERT(m_cachedPlugins.isEmpty());
297     
298     // FIXME: Should we do something in case of error here?
299     if (!WebProcess::shared().connection()->sendSync(Messages::WebProcessProxy::GetPlugins(m_shouldRefreshPlugins), Messages::WebProcessProxy::GetPlugins::Reply(m_cachedPlugins), 0))
300         return;
301
302     m_shouldRefreshPlugins = false;
303     m_pluginCacheIsPopulated = true;
304 }
305 #endif // ENABLE(NETSCAPE_PLUGIN_API)
306
307 // SharedWorkerStrategy.
308
309 bool WebPlatformStrategies::isAvailable() const
310 {
311     // Shared workers do not work across multiple processes, and using network process is tied to multiple secondary process model.
312 #if ENABLE(NETWORK_PROCESS)
313     return WebProcess::shared().usesNetworkProcess();
314 #else
315     return true;
316 #endif
317 }
318
319 // StorageStrategy
320
321 PassRefPtr<StorageNamespace> WebPlatformStrategies::localStorageNamespace(PageGroup* pageGroup)
322 {
323 #if ENABLE(UI_PROCESS_STORAGE)
324     return StorageNamespaceImpl::createLocalStorageNamespace(pageGroup);
325 #else
326     return StorageStrategy::localStorageNamespace(pageGroup);
327 #endif
328 }
329
330 PassRefPtr<StorageNamespace> WebPlatformStrategies::transientLocalStorageNamespace(PageGroup* pageGroup, SecurityOrigin*securityOrigin)
331 {
332 #if ENABLE(UI_PROCESS_STORAGE)
333     // FIXME: This could be more clever and made to work across processes.
334     return StorageStrategy::sessionStorageNamespace(*pageGroup->pages().begin());
335 #else
336     return StorageStrategy::transientLocalStorageNamespace(pageGroup, securityOrigin);
337 #endif
338 }
339
340 PassRefPtr<StorageNamespace> WebPlatformStrategies::sessionStorageNamespace(Page* page)
341 {
342 #if ENABLE(UI_PROCESS_STORAGE)
343     return StorageNamespaceImpl::createSessionStorageNamespace(WebPage::fromCorePage(page));
344 #else
345     return StorageStrategy::sessionStorageNamespace(page);
346 #endif
347 }
348
349 // VisitedLinkStrategy
350
351 bool WebPlatformStrategies::isLinkVisited(Page*, LinkHash linkHash, const KURL&, const AtomicString&)
352 {
353     return WebProcess::shared().isLinkVisited(linkHash);
354 }
355
356 void WebPlatformStrategies::addVisitedLink(Page*, LinkHash linkHash)
357 {
358     WebProcess::shared().addVisitedLink(linkHash);
359 }
360
361 #if PLATFORM(MAC)
362 // PasteboardStrategy
363
364 void WebPlatformStrategies::getTypes(Vector<String>& types, const String& pasteboardName)
365 {
366     WebProcess::shared().connection()->sendSync(Messages::WebContext::GetPasteboardTypes(pasteboardName),
367                                                 Messages::WebContext::GetPasteboardTypes::Reply(types), 0);
368 }
369
370 PassRefPtr<WebCore::SharedBuffer> WebPlatformStrategies::bufferForType(const String& pasteboardType, const String& pasteboardName)
371 {
372     SharedMemory::Handle handle;
373     uint64_t size = 0;
374     WebProcess::shared().connection()->sendSync(Messages::WebContext::GetPasteboardBufferForType(pasteboardName, pasteboardType),
375                                                 Messages::WebContext::GetPasteboardBufferForType::Reply(handle, size), 0);
376     if (handle.isNull())
377         return 0;
378     RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::create(handle, SharedMemory::ReadOnly);
379     return SharedBuffer::create(static_cast<unsigned char *>(sharedMemoryBuffer->data()), size);
380 }
381
382 void WebPlatformStrategies::getPathnamesForType(Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName)
383 {
384     WebProcess::shared().connection()->sendSync(Messages::WebContext::GetPasteboardPathnamesForType(pasteboardName, pasteboardType),
385                                                 Messages::WebContext::GetPasteboardPathnamesForType::Reply(pathnames), 0);
386 }
387
388 String WebPlatformStrategies::stringForType(const String& pasteboardType, const String& pasteboardName)
389 {
390     String value;
391     WebProcess::shared().connection()->sendSync(Messages::WebContext::GetPasteboardStringForType(pasteboardName, pasteboardType),
392                                                 Messages::WebContext::GetPasteboardStringForType::Reply(value), 0);
393     return value;
394 }
395
396 void WebPlatformStrategies::copy(const String& fromPasteboard, const String& toPasteboard)
397 {
398     WebProcess::shared().connection()->send(Messages::WebContext::PasteboardCopy(fromPasteboard, toPasteboard), 0);
399 }
400
401 int WebPlatformStrategies::changeCount(const WTF::String &pasteboardName)
402 {
403     uint64_t changeCount;
404     WebProcess::shared().connection()->sendSync(Messages::WebContext::GetPasteboardChangeCount(pasteboardName),
405                                                 Messages::WebContext::GetPasteboardChangeCount::Reply(changeCount), 0);
406     return changeCount;
407 }
408
409 String WebPlatformStrategies::uniqueName()
410 {
411     String pasteboardName;
412     WebProcess::shared().connection()->sendSync(Messages::WebContext::GetPasteboardUniqueName(),
413                                                 Messages::WebContext::GetPasteboardUniqueName::Reply(pasteboardName), 0);
414     return pasteboardName;
415 }
416
417 Color WebPlatformStrategies::color(const String& pasteboardName)
418 {
419     Color color;
420     WebProcess::shared().connection()->sendSync(Messages::WebContext::GetPasteboardColor(pasteboardName),
421                                                 Messages::WebContext::GetPasteboardColor::Reply(color), 0);
422     return color;
423 }
424
425 KURL WebPlatformStrategies::url(const String& pasteboardName)
426 {
427     String urlString;
428     WebProcess::shared().connection()->sendSync(Messages::WebContext::GetPasteboardURL(pasteboardName),
429                                                 Messages::WebContext::GetPasteboardURL::Reply(urlString), 0);
430     return KURL(ParsedURLString, urlString);
431 }
432
433 void WebPlatformStrategies::addTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName)
434 {
435     WebProcess::shared().connection()->send(Messages::WebContext::AddPasteboardTypes(pasteboardName, pasteboardTypes), 0);
436 }
437
438 void WebPlatformStrategies::setTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName)
439 {
440     WebProcess::shared().connection()->send(Messages::WebContext::SetPasteboardTypes(pasteboardName, pasteboardTypes), 0);
441 }
442
443 void WebPlatformStrategies::setBufferForType(PassRefPtr<SharedBuffer> buffer, const String& pasteboardType, const String& pasteboardName)
444 {
445     SharedMemory::Handle handle;
446     if (buffer) {
447         RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::create(buffer->size());
448         memcpy(sharedMemoryBuffer->data(), buffer->data(), buffer->size());
449         sharedMemoryBuffer->createHandle(handle, SharedMemory::ReadOnly);
450     }
451     WebProcess::shared().connection()->send(Messages::WebContext::SetPasteboardBufferForType(pasteboardName, pasteboardType, handle, buffer ? buffer->size() : 0), 0);
452 }
453
454 void WebPlatformStrategies::setPathnamesForType(const Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName)
455 {
456     WebProcess::shared().connection()->send(Messages::WebContext::SetPasteboardPathnamesForType(pasteboardName, pasteboardType, pathnames), 0);
457 }
458
459 void WebPlatformStrategies::setStringForType(const String& string, const String& pasteboardType, const String& pasteboardName)
460 {
461     WebProcess::shared().connection()->send(Messages::WebContext::SetPasteboardStringForType(pasteboardName, pasteboardType, string), 0);
462 }
463 #endif
464
465 } // namespace WebKit