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 "SessionTracker.h"
43#include "StatisticsData.h"
44#include "WebContextMessages.h"
45#include "WebCookieManager.h"
46#include <WebCore/Logging.h>
47#include <WebCore/MemoryPressureHandler.h>
48#include <WebCore/ResourceRequest.h>
49#include <WebCore/SessionID.h>
50#include <wtf/RunLoop.h>
51#include <wtf/text/CString.h>
52
53#if ENABLE(SEC_ITEM_SHIM)
54#include "SecItemShim.h"
55#endif
56
57using namespace WebCore;
58
59namespace WebKit {
60
61NetworkProcess& NetworkProcess::shared()
62{
63    static NeverDestroyed<NetworkProcess> networkProcess;
64    return networkProcess;
65}
66
67NetworkProcess::NetworkProcess()
68    : m_hasSetCacheModel(false)
69    , m_cacheModel(CacheModelDocumentViewer)
70#if PLATFORM(COCOA)
71    , m_clearCacheDispatchGroup(0)
72#endif
73{
74    NetworkProcessPlatformStrategies::initialize();
75
76    addSupplement<AuthenticationManager>();
77    addSupplement<WebCookieManager>();
78#if ENABLE(CUSTOM_PROTOCOLS)
79    addSupplement<CustomProtocolManager>();
80#endif
81}
82
83NetworkProcess::~NetworkProcess()
84{
85}
86
87AuthenticationManager& NetworkProcess::authenticationManager()
88{
89    return *supplement<AuthenticationManager>();
90}
91
92DownloadManager& NetworkProcess::downloadManager()
93{
94    static NeverDestroyed<DownloadManager> downloadManager(this);
95    return downloadManager;
96}
97
98void NetworkProcess::removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess* connection)
99{
100    size_t vectorIndex = m_webProcessConnections.find(connection);
101    ASSERT(vectorIndex != notFound);
102
103    m_webProcessConnections.remove(vectorIndex);
104}
105
106bool NetworkProcess::shouldTerminate()
107{
108    // Network process keeps session cookies and credentials, so it should never terminate (as long as UI process connection is alive).
109    return false;
110}
111
112void NetworkProcess::didReceiveMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder)
113{
114    if (messageReceiverMap().dispatchMessage(connection, decoder))
115        return;
116
117    didReceiveNetworkProcessMessage(connection, decoder);
118}
119
120void NetworkProcess::didReceiveSyncMessage(IPC::Connection* connection, IPC::MessageDecoder& decoder, std::unique_ptr<IPC::MessageEncoder>& replyEncoder)
121{
122    messageReceiverMap().dispatchSyncMessage(connection, decoder, replyEncoder);
123}
124
125void NetworkProcess::didClose(IPC::Connection*)
126{
127    // The UIProcess just exited.
128    RunLoop::current().stop();
129}
130
131void NetworkProcess::didReceiveInvalidMessage(IPC::Connection*, IPC::StringReference, IPC::StringReference)
132{
133    RunLoop::current().stop();
134}
135
136void NetworkProcess::didCreateDownload()
137{
138    disableTermination();
139}
140
141void NetworkProcess::didDestroyDownload()
142{
143    enableTermination();
144}
145
146IPC::Connection* NetworkProcess::downloadProxyConnection()
147{
148    return parentProcessConnection();
149}
150
151AuthenticationManager& NetworkProcess::downloadsAuthenticationManager()
152{
153    return authenticationManager();
154}
155
156void NetworkProcess::initializeNetworkProcess(const NetworkProcessCreationParameters& parameters)
157{
158    platformInitializeNetworkProcess(parameters);
159
160    WTF::setCurrentThreadIsUserInitiated();
161
162    memoryPressureHandler().setLowMemoryHandler(lowMemoryHandler);
163    memoryPressureHandler().install();
164
165    setCacheModel(static_cast<uint32_t>(parameters.cacheModel));
166
167#if PLATFORM(MAC) || USE(CFNETWORK)
168    SessionTracker::setIdentifierBase(parameters.uiProcessBundleIdentifier);
169#endif
170
171    // FIXME: instead of handling this here, a message should be sent later (scales to multiple sessions)
172    if (parameters.privateBrowsingEnabled)
173        RemoteNetworkingContext::ensurePrivateBrowsingSession(SessionID::legacyPrivateSessionID());
174
175    if (parameters.shouldUseTestingNetworkSession)
176        NetworkStorageSession::switchToNewTestingSession();
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->initialize(parameters);
182}
183
184void NetworkProcess::initializeConnection(IPC::Connection* connection)
185{
186    ChildProcess::initializeConnection(connection);
187
188#if ENABLE(SEC_ITEM_SHIM)
189    SecItemShim::shared().initializeConnection(connection);
190#endif
191
192    NetworkProcessSupplementMap::const_iterator it = m_supplements.begin();
193    NetworkProcessSupplementMap::const_iterator end = m_supplements.end();
194    for (; it != end; ++it)
195        it->value->initializeConnection(connection);
196}
197
198void NetworkProcess::createNetworkConnectionToWebProcess()
199{
200#if OS(DARWIN)
201    // Create the listening port.
202    mach_port_t listeningPort;
203    mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort);
204
205    // Create a listening connection.
206    RefPtr<NetworkConnectionToWebProcess> connection = NetworkConnectionToWebProcess::create(IPC::Connection::Identifier(listeningPort));
207    m_webProcessConnections.append(connection.release());
208
209    IPC::Attachment clientPort(listeningPort, MACH_MSG_TYPE_MAKE_SEND);
210    parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientPort), 0);
211#elif USE(UNIX_DOMAIN_SOCKETS)
212    IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
213
214    RefPtr<NetworkConnectionToWebProcess> connection = NetworkConnectionToWebProcess::create(socketPair.server);
215    m_webProcessConnections.append(connection.release());
216
217    IPC::Attachment clientSocket(socketPair.client);
218    parentProcessConnection()->send(Messages::NetworkProcessProxy::DidCreateNetworkConnectionToWebProcess(clientSocket), 0);
219#else
220    notImplemented();
221#endif
222}
223
224void NetworkProcess::ensurePrivateBrowsingSession(SessionID sessionID)
225{
226    RemoteNetworkingContext::ensurePrivateBrowsingSession(sessionID);
227}
228
229void NetworkProcess::destroyPrivateBrowsingSession(SessionID sessionID)
230{
231    SessionTracker::destroySession(sessionID);
232}
233
234void NetworkProcess::downloadRequest(uint64_t downloadID, const ResourceRequest& request)
235{
236    downloadManager().startDownload(downloadID, request);
237}
238
239void NetworkProcess::cancelDownload(uint64_t downloadID)
240{
241    downloadManager().cancelDownload(downloadID);
242}
243
244void NetworkProcess::setCacheModel(uint32_t cm)
245{
246    CacheModel cacheModel = static_cast<CacheModel>(cm);
247
248    if (!m_hasSetCacheModel || cacheModel != m_cacheModel) {
249        m_hasSetCacheModel = true;
250        m_cacheModel = cacheModel;
251        platformSetCacheModel(cacheModel);
252    }
253}
254
255void NetworkProcess::getNetworkProcessStatistics(uint64_t callbackID)
256{
257    NetworkResourceLoadScheduler& scheduler = NetworkProcess::shared().networkResourceLoadScheduler();
258
259    StatisticsData data;
260
261    data.statisticsNumbers.set("HostsPendingCount", scheduler.hostsPendingCount());
262    data.statisticsNumbers.set("HostsActiveCount", scheduler.hostsActiveCount());
263    data.statisticsNumbers.set("LoadsPendingCount", scheduler.loadsPendingCount());
264    data.statisticsNumbers.set("LoadsActiveCount", scheduler.loadsActiveCount());
265    data.statisticsNumbers.set("DownloadsActiveCount", shared().downloadManager().activeDownloadCount());
266    data.statisticsNumbers.set("OutstandingAuthenticationChallengesCount", shared().authenticationManager().outstandingAuthenticationChallengeCount());
267
268    parentProcessConnection()->send(Messages::WebContext::DidGetStatistics(data, callbackID), 0);
269}
270
271void NetworkProcess::terminate()
272{
273    platformTerminate();
274    ChildProcess::terminate();
275}
276
277void NetworkProcess::lowMemoryHandler(bool critical)
278{
279    platformLowMemoryHandler(critical);
280    WTF::releaseFastMallocFreeMemory();
281}
282
283#if !PLATFORM(COCOA)
284void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&)
285{
286}
287
288void NetworkProcess::initializeProcessName(const ChildProcessInitializationParameters&)
289{
290}
291
292void NetworkProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
293{
294}
295
296void NetworkProcess::platformLowMemoryHandler(bool)
297{
298}
299#endif
300
301} // namespace WebKit
302
303#endif // ENABLE(NETWORK_PROCESS)
304