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 "NetworkProcess.h"
28
29#if ENABLE(NETWORK_PROCESS)
30
31#include "ArgumentCoders.h"
32#include "Attachment.h"
33#include "AuthenticationManager.h"
34#include "CustomProtocolManager.h"
35#include "Logging.h"
36#include "NetworkConnectionToWebProcess.h"
37#include "NetworkProcessCreationParameters.h"
38#include "NetworkProcessPlatformStrategies.h"
39#include "NetworkProcessProxyMessages.h"
40#include "NetworkResourceLoader.h"
41#include "RemoteNetworkingContext.h"
42#include "StatisticsData.h"
43#include "WebContextMessages.h"
44#include "WebCookieManager.h"
45#include <WebCore/InitializeLogging.h>
46#include <WebCore/ResourceRequest.h>
47#include <WebCore/RunLoop.h>
48#include <wtf/text/CString.h>
49
50#if USE(SECURITY_FRAMEWORK)
51#include "SecItemShim.h"
52#endif
53
54using namespace WebCore;
55
56namespace WebKit {
57
58NetworkProcess& NetworkProcess::shared()
59{
60    DEFINE_STATIC_LOCAL(NetworkProcess, networkProcess, ());
61    return networkProcess;
62}
63
64NetworkProcess::NetworkProcess()
65    : m_hasSetCacheModel(false)
66    , m_cacheModel(CacheModelDocumentViewer)
67#if PLATFORM(MAC)
68    , m_clearCacheDispatchGroup(0)
69#endif
70{
71    NetworkProcessPlatformStrategies::initialize();
72
73    addSupplement<AuthenticationManager>();
74    addSupplement<WebCookieManager>();
75    addSupplement<CustomProtocolManager>();
76}
77
78NetworkProcess::~NetworkProcess()
79{
80}
81
82AuthenticationManager& NetworkProcess::authenticationManager()
83{
84    return *supplement<AuthenticationManager>();
85}
86
87DownloadManager& NetworkProcess::downloadManager()
88{
89    DEFINE_STATIC_LOCAL(DownloadManager, downloadManager, (this));
90    return downloadManager;
91}
92
93void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess* connection)
94{
95    size_t vectorIndex = m_webProcessConnections.find(connection);
96    ASSERT(vectorIndex != notFound);
97
98    m_webProcessConnections.remove(vectorIndex);
99}
100
101bool NetworkProcess::shouldTerminate()
102{
103    // Network process keeps session cookies and credentials, so it should never terminate (as long as UI process connection is alive).
104    return false;
105}
106
107void NetworkProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder)
108{
109    if (messageReceiverMap().dispatchMessage(connection, decoder))
110        return;
111
112    didReceiveNetworkProcessMessage(connection, decoder);
113}
114
115void NetworkProcess::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& replyEncoder)
116{
117    messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder);
118}
119
120void NetworkProcess::didClose(CoreIPC::Connection*)
121{
122    // The UIProcess just exited.
123    RunLoop::current()->stop();
124}
125
126void NetworkProcess::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::StringReference, CoreIPC::StringReference)
127{
128    RunLoop::current()->stop();
129}
130
131void NetworkProcess::didCreateDownload()
132{
133    disableTermination();
134}
135
136void NetworkProcess::didDestroyDownload()
137{
138    enableTermination();
139}
140
141CoreIPC::Connection* NetworkProcess::downloadProxyConnection()
142{
143    return parentProcessConnection();
144}
145
146AuthenticationManager& NetworkProcess::downloadsAuthenticationManager()
147{
148    return authenticationManager();
149}
150
151void NetworkProcess::initializeNetworkProcess(const NetworkProcessCreationParameters& parameters)
152{
153    platformInitializeNetworkProcess(parameters);
154
155    setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
156
157#if PLATFORM(MAC) || USE(CFNETWORK)
158    RemoteNetworkingContext::setPrivateBrowsingStorageSessionIdentifierBase(parameters.uiProcessBundleIdentifier);
159#endif
160
161    if (parameters.privateBrowsingEnabled)
162        RemoteNetworkingContext::ensurePrivateBrowsingSession();
163
164    NetworkProcessSupplementMap::const_iterator it = m_supplements.begin();
165    NetworkProcessSupplementMap::const_iterator end = m_supplements.end();
166    for (; it != end; ++it)
167        it->value->initialize(parameters);
168}
169
170void NetworkProcess::initializeConnection(CoreIPC::Connection* connection)
171{
172    ChildProcess::initializeConnection(connection);
173
174#if USE(SECURITY_FRAMEWORK)
175    SecItemShim::shared().initializeConnection(connection);
176#endif
177
178    NetworkProcessSupplementMap::const_iterator it = m_supplements.begin();
179    NetworkProcessSupplementMap::const_iterator end = m_supplements.end();
180    for (; it != end; ++it)
181        it->value->initializeConnection(connection);
182}
183
184void NetworkProcess::createNetworkConnectionToWebProcess()
185{
186#if PLATFORM(MAC)
187    // Create the listening port.
188    mach_port_t listeningPort;
189    mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
190
191    // Create a listening connection.
192    RefPtr<NetworkConnectionToWebProcess> connection = NetworkConnectionToWebProcess::create(CoreIPC::Connection::Identifier(listeningPort));
193    m_webProcessConnections.append(connection.release());
194
195    CoreIPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
196    parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0);
197#else
198    notImplemented();
199#endif
200}
201
202void NetworkProcess::ensurePrivateBrowsingSession()
203{
204    RemoteNetworkingContext::ensurePrivateBrowsingSession();
205}
206
207void NetworkProcess::destroyPrivateBrowsingSession()
208{
209    RemoteNetworkingContext::destroyPrivateBrowsingSession();
210}
211
212void NetworkProcess::downloadRequest(uint64_t downloadID, const ResourceRequest& request)
213{
214    downloadManager().startDownload(downloadID, request);
215}
216
217void NetworkProcess::cancelDownload(uint64_t downloadID)
218{
219    downloadManager().cancelDownload(downloadID);
220}
221
222void NetworkProcess::setCacheModel(uint32_t cm)
223{
224    CacheModel cacheModel = static_cast<CacheModel>(cm);
225
226    if (!m_hasSetCacheModel || cacheModel != m_cacheModel) {
227        m_hasSetCacheModel = true;
228        m_cacheModel = cacheModel;
229        platformSetCacheModel(cacheModel);
230    }
231}
232
233void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
234{
235    NetworkResourceLoadScheduler& scheduler = NetworkProcess::shared().networkResourceLoadScheduler();
236
237    StatisticsData data;
238
239    data.statisticsNumbers.set("HostsPendingCount", scheduler.hostsPendingCount());
240    data.statisticsNumbers.set("HostsActiveCount", scheduler.hostsActiveCount());
241    data.statisticsNumbers.set("LoadsPendingCount", scheduler.loadsPendingCount());
242    data.statisticsNumbers.set("LoadsActiveCount", scheduler.loadsActiveCount());
243    data.statisticsNumbers.set("DownloadsActiveCount", shared().downloadManager().activeDownloadCount());
244    data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", shared().authenticationManager().outstandingAuthenticationChallengeCount());
245
246    parentProcessConnection()->send(Messages::WebContext::DidGetStatistics(data, callbackID), 0);
247}
248
249void NetworkProcess::terminate()
250{
251    platformTerminate();
252    ChildProcess::terminate();
253}
254
255#if !PLATFORM(MAC)
256void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&)
257{
258}
259
260void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters&)
261{
262}
263
264void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
265{
266}
267#endif
268
269} // namespace WebKit
270
271#endif // ENABLE(NETWORK_PROCESS)
272