1/*
2 * Copyright (C) 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 "NetworkConnectionToWebProcess.h"
28
29#include "BlobRegistrationData.h"
30#include "ConnectionStack.h"
31#include "NetworkBlobRegistry.h"
32#include "NetworkConnectionToWebProcessMessages.h"
33#include "NetworkProcess.h"
34#include "NetworkResourceLoadParameters.h"
35#include "NetworkResourceLoader.h"
36#include "NetworkResourceLoaderMessages.h"
37#include "RemoteNetworkingContext.h"
38#include <WebCore/BlobData.h>
39#include <WebCore/PlatformCookieJar.h>
40#include <WebCore/ResourceLoaderOptions.h>
41#include <WebCore/ResourceRequest.h>
42#include <WebCore/RunLoop.h>
43
44#if ENABLE(NETWORK_PROCESS)
45
46using namespace WebCore;
47
48namespace WebKit {
49
50PassRefPtr<NetworkConnectionToWebProcess> NetworkConnectionToWebProcess::create(CoreIPC::Connection::Identifier connectionIdentifier)
51{
52    return adoptRef(new NetworkConnectionToWebProcess(connectionIdentifier));
53}
54
55NetworkConnectionToWebProcess::NetworkConnectionToWebProcess(CoreIPC::Connection::Identifier connectionIdentifier)
56    : m_serialLoadingEnabled(false)
57{
58    m_connection = CoreIPC::Connection::createServerConnection(connectionIdentifier, this, RunLoop::main());
59    m_connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true);
60    m_connection->open();
61}
62
63NetworkConnectionToWebProcess::~NetworkConnectionToWebProcess()
64{
65}
66
67void NetworkConnectionToWebProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder)
68{
69    if (decoder.messageReceiverName() == Messages::NetworkConnectionToWebProcess::messageReceiverName()) {
70        didReceiveNetworkConnectionToWebProcessMessage(connection, decoder);
71        return;
72    }
73
74    if (decoder.messageReceiverName() == Messages::NetworkResourceLoader::messageReceiverName()) {
75        HashMap<ResourceLoadIdentifier, RefPtr<NetworkResourceLoader>>::iterator loaderIterator = m_networkResourceLoaders.find(decoder.destinationID());
76        if (loaderIterator != m_networkResourceLoaders.end())
77            loaderIterator->value->didReceiveNetworkResourceLoaderMessage(connection, decoder);
78        return;
79    }
80
81    ASSERT_NOT_REACHED();
82}
83
84void NetworkConnectionToWebProcess::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& reply)
85{
86    if (decoder.messageReceiverName() == Messages::NetworkConnectionToWebProcess::messageReceiverName()) {
87        didReceiveSyncNetworkConnectionToWebProcessMessage(connection, decoder, reply);
88        return;
89    }
90    ASSERT_NOT_REACHED();
91}
92
93void NetworkConnectionToWebProcess::didClose(CoreIPC::Connection*)
94{
95    // Protect ourself as we might be otherwise be deleted during this function.
96    RefPtr<NetworkConnectionToWebProcess> protector(this);
97
98    HashMap<ResourceLoadIdentifier, RefPtr<NetworkResourceLoader>>::iterator end = m_networkResourceLoaders.end();
99    for (HashMap<ResourceLoadIdentifier, RefPtr<NetworkResourceLoader>>::iterator i = m_networkResourceLoaders.begin(); i != end; ++i)
100        i->value->abort();
101
102    NetworkBlobRegistry::shared().connectionToWebProcessDidClose(this);
103
104    m_networkResourceLoaders.clear();
105
106    NetworkProcess::shared().removeNetworkConnectionToWebProcess(this);
107}
108
109void NetworkConnectionToWebProcess::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::StringReference, CoreIPC::StringReference)
110{
111}
112
113void NetworkConnectionToWebProcess::scheduleResourceLoad(const NetworkResourceLoadParameters& loadParameters)
114{
115    RefPtr<NetworkResourceLoader> loader = NetworkResourceLoader::create(loadParameters, this);
116    m_networkResourceLoaders.add(loadParameters.identifier, loader);
117    NetworkProcess::shared().networkResourceLoadScheduler().scheduleLoader(loader.get());
118}
119
120void NetworkConnectionToWebProcess::performSynchronousLoad(const NetworkResourceLoadParameters& loadParameters, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply> reply)
121{
122    RefPtr<NetworkResourceLoader> loader = NetworkResourceLoader::create(loadParameters, this, reply);
123    m_networkResourceLoaders.add(loadParameters.identifier, loader);
124    NetworkProcess::shared().networkResourceLoadScheduler().scheduleLoader(loader.get());
125}
126
127void NetworkConnectionToWebProcess::removeLoadIdentifier(ResourceLoadIdentifier identifier)
128{
129    RefPtr<NetworkResourceLoader> loader = m_networkResourceLoaders.take(identifier);
130
131    // It's possible we have no loader for this identifier if the NetworkProcess crashed and this was a respawned NetworkProcess.
132    if (!loader)
133        return;
134
135    // Abort the load now, as the WebProcess won't be able to respond to messages any more which might lead
136    // to leaked loader resources (connections, threads, etc).
137    loader->abort();
138}
139
140void NetworkConnectionToWebProcess::servePendingRequests(uint32_t resourceLoadPriority)
141{
142    NetworkProcess::shared().networkResourceLoadScheduler().servePendingRequests(static_cast<ResourceLoadPriority>(resourceLoadPriority));
143}
144
145void NetworkConnectionToWebProcess::setSerialLoadingEnabled(bool enabled)
146{
147    m_serialLoadingEnabled = enabled;
148}
149
150static NetworkStorageSession& storageSession(bool privateBrowsingEnabled)
151{
152    if (privateBrowsingEnabled) {
153        NetworkStorageSession* privateSession = RemoteNetworkingContext::privateBrowsingSession();
154        if (privateSession)
155            return *privateSession;
156        // Some requests with private browsing mode requested may still be coming shortly after NetworkProcess was told to destroy its session.
157        // FIXME: Find a way to track private browsing sessions more rigorously.
158        LOG_ERROR("Private browsing was requested, but there was no session for it. Please file a bug unless you just disabled private browsing, in which case it's an expected race.");
159    }
160    return NetworkStorageSession::defaultStorageSession();
161}
162
163void NetworkConnectionToWebProcess::startDownload(bool privateBrowsingEnabled, uint64_t downloadID, const ResourceRequest& request)
164{
165    // FIXME: Do something with the private browsing flag.
166    NetworkProcess::shared().downloadManager().startDownload(downloadID, request);
167}
168
169void NetworkConnectionToWebProcess::convertMainResourceLoadToDownload(uint64_t mainResourceLoadIdentifier, uint64_t downloadID, const ResourceRequest& request, const ResourceResponse& response)
170{
171    if (!mainResourceLoadIdentifier) {
172        NetworkProcess::shared().downloadManager().startDownload(downloadID, request);
173        return;
174    }
175
176    NetworkResourceLoader* loader = m_networkResourceLoaders.get(mainResourceLoadIdentifier);
177    NetworkProcess::shared().downloadManager().convertHandleToDownload(downloadID, loader->handle(), request, response);
178
179    // Unblock the URL connection operation queue.
180    loader->handle()->continueDidReceiveResponse();
181
182    loader->didConvertHandleToDownload();
183}
184
185void NetworkConnectionToWebProcess::cookiesForDOM(bool privateBrowsingEnabled, const KURL& firstParty, const KURL& url, String& result)
186{
187    result = WebCore::cookiesForDOM(storageSession(privateBrowsingEnabled), firstParty, url);
188}
189
190void NetworkConnectionToWebProcess::setCookiesFromDOM(bool privateBrowsingEnabled, const KURL& firstParty, const KURL& url, const String& cookieString)
191{
192    WebCore::setCookiesFromDOM(storageSession(privateBrowsingEnabled), firstParty, url, cookieString);
193}
194
195void NetworkConnectionToWebProcess::cookiesEnabled(bool privateBrowsingEnabled, const KURL& firstParty, const KURL& url, bool& result)
196{
197    result = WebCore::cookiesEnabled(storageSession(privateBrowsingEnabled), firstParty, url);
198}
199
200void NetworkConnectionToWebProcess::cookieRequestHeaderFieldValue(bool privateBrowsingEnabled, const KURL& firstParty, const KURL& url, String& result)
201{
202    result = WebCore::cookieRequestHeaderFieldValue(storageSession(privateBrowsingEnabled), firstParty, url);
203}
204
205void NetworkConnectionToWebProcess::getRawCookies(bool privateBrowsingEnabled, const KURL& firstParty, const KURL& url, Vector<Cookie>& result)
206{
207    WebCore::getRawCookies(storageSession(privateBrowsingEnabled), firstParty, url, result);
208}
209
210void NetworkConnectionToWebProcess::deleteCookie(bool privateBrowsingEnabled, const KURL& url, const String& cookieName)
211{
212    WebCore::deleteCookie(storageSession(privateBrowsingEnabled), url, cookieName);
213}
214
215void NetworkConnectionToWebProcess::registerBlobURL(const KURL& url, const BlobRegistrationData& data)
216{
217    Vector<RefPtr<SandboxExtension>> extensions;
218    for (size_t i = 0, count = data.sandboxExtensions().size(); i < count; ++i) {
219        if (RefPtr<SandboxExtension> extension = SandboxExtension::create(data.sandboxExtensions()[i]))
220            extensions.append(extension);
221    }
222
223    NetworkBlobRegistry::shared().registerBlobURL(this, url, data.releaseData(), extensions);
224}
225
226void NetworkConnectionToWebProcess::registerBlobURLFromURL(const KURL& url, const KURL& srcURL)
227{
228    NetworkBlobRegistry::shared().registerBlobURL(this, url, srcURL);
229}
230
231void NetworkConnectionToWebProcess::unregisterBlobURL(const KURL& url)
232{
233    NetworkBlobRegistry::shared().unregisterBlobURL(this, url);
234}
235
236} // namespace WebKit
237
238#endif // ENABLE(NETWORK_PROCESS)
239