1/*
2 * Copyright (C) 2010-2017 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#pragma once
27
28#include "APIUserInitiatedAction.h"
29#include "AuxiliaryProcessProxy.h"
30#include "BackgroundProcessResponsivenessTimer.h"
31#include "MessageReceiverMap.h"
32#include "PluginInfoStore.h"
33#include "ProcessLauncher.h"
34#include "ProcessTerminationReason.h"
35#include "ProcessThrottler.h"
36#include "ProcessThrottlerClient.h"
37#include "ResponsivenessTimer.h"
38#include "VisibleWebPageCounter.h"
39#include "WebConnectionToWebProcess.h"
40#include "WebProcessProxyMessages.h"
41#include <WebCore/MessagePortChannelProvider.h>
42#include <WebCore/MessagePortIdentifier.h>
43#include <WebCore/PageIdentifier.h>
44#include <WebCore/ProcessIdentifier.h>
45#include <WebCore/RegistrableDomain.h>
46#include <WebCore/SharedStringHash.h>
47#include <memory>
48#include <pal/SessionID.h>
49#include <wtf/Forward.h>
50#include <wtf/HashMap.h>
51#include <wtf/HashSet.h>
52#include <wtf/RefCounted.h>
53#include <wtf/RefPtr.h>
54
55namespace API {
56class Navigation;
57class PageConfiguration;
58}
59
60namespace WebCore {
61class DeferrableOneShotTimer;
62class ResourceRequest;
63struct PluginInfo;
64struct SecurityOriginData;
65}
66
67namespace WebKit {
68
69class NetworkProcessProxy;
70class ObjCObjectGraph;
71class PageClient;
72class ProvisionalPageProxy;
73class UserMediaCaptureManagerProxy;
74class VisitedLinkStore;
75class WebBackForwardListItem;
76class WebFrameProxy;
77class WebPageGroup;
78class WebPageProxy;
79class WebProcessPool;
80class WebUserContentControllerProxy;
81class WebsiteDataStore;
82enum class WebsiteDataType;
83struct WebNavigationDataStore;
84struct WebPageCreationParameters;
85struct WebsiteData;
86
87#if PLATFORM(IOS_FAMILY)
88enum ForegroundWebProcessCounterType { };
89typedef RefCounter<ForegroundWebProcessCounterType> ForegroundWebProcessCounter;
90typedef ForegroundWebProcessCounter::Token ForegroundWebProcessToken;
91enum BackgroundWebProcessCounterType { };
92typedef RefCounter<BackgroundWebProcessCounterType> BackgroundWebProcessCounter;
93typedef BackgroundWebProcessCounter::Token BackgroundWebProcessToken;
94#endif
95
96enum class AllowProcessCaching { No, Yes };
97
98class WebProcessProxy : public AuxiliaryProcessProxy, public ResponsivenessTimer::Client, public ThreadSafeRefCounted<WebProcessProxy>, public CanMakeWeakPtr<WebProcessProxy>, private ProcessThrottlerClient {
99public:
100 typedef HashMap<uint64_t, RefPtr<WebFrameProxy>> WebFrameProxyMap;
101 typedef HashMap<WebCore::PageIdentifier, WebPageProxy*> WebPageProxyMap;
102 typedef HashMap<uint64_t, RefPtr<API::UserInitiatedAction>> UserInitiatedActionMap;
103
104 enum class IsPrewarmed {
105 No,
106 Yes
107 };
108
109 enum class ShouldLaunchProcess : bool { No, Yes };
110
111 static Ref<WebProcessProxy> create(WebProcessPool&, WebsiteDataStore*, IsPrewarmed, ShouldLaunchProcess = ShouldLaunchProcess::Yes);
112 ~WebProcessProxy();
113
114 static void forWebPagesWithOrigin(PAL::SessionID, const WebCore::SecurityOriginData&, const Function<void(WebPageProxy&)>&);
115
116 WebConnection* webConnection() const { return m_webConnection.get(); }
117
118 unsigned suspendedPageCount() const { return m_suspendedPageCount; }
119 void incrementSuspendedPageCount();
120 void decrementSuspendedPageCount();
121
122 WebProcessPool& processPool() const;
123
124 WebCore::RegistrableDomain registrableDomain() const { return m_registrableDomain.valueOr(WebCore::RegistrableDomain { }); }
125 void setIsInProcessCache(bool);
126 bool isInProcessCache() const { return m_isInProcessCache; }
127
128 WebsiteDataStore& websiteDataStore() const { ASSERT(m_websiteDataStore); return *m_websiteDataStore; }
129 void setWebsiteDataStore(WebsiteDataStore&);
130
131 static WebProcessProxy* processForIdentifier(WebCore::ProcessIdentifier);
132 static WebPageProxy* webPage(WebCore::PageIdentifier);
133 Ref<WebPageProxy> createWebPage(PageClient&, Ref<API::PageConfiguration>&&);
134
135 enum class BeginsUsingDataStore : bool { No, Yes };
136 void addExistingWebPage(WebPageProxy&, BeginsUsingDataStore);
137
138 enum class EndsUsingDataStore : bool { No, Yes };
139 void removeWebPage(WebPageProxy&, EndsUsingDataStore);
140
141 void addProvisionalPageProxy(ProvisionalPageProxy& provisionalPage) { ASSERT(!m_provisionalPages.contains(&provisionalPage)); m_provisionalPages.add(&provisionalPage); }
142 void removeProvisionalPageProxy(ProvisionalPageProxy& provisionalPage) { ASSERT(m_provisionalPages.contains(&provisionalPage)); m_provisionalPages.remove(&provisionalPage); }
143
144 typename WebPageProxyMap::ValuesConstIteratorRange pages() const { return m_pageMap.values(); }
145 unsigned pageCount() const { return m_pageMap.size(); }
146 unsigned provisionalPageCount() const { return m_provisionalPages.size(); }
147 unsigned visiblePageCount() const { return m_visiblePageCounter.value(); }
148
149 void activePagesDomainsForTesting(CompletionHandler<void(Vector<String>&&)>&&); // This is what is reported to ActivityMonitor.
150
151 virtual bool isServiceWorkerProcess() const { return false; }
152
153 void didCreateWebPageInProcess(WebCore::PageIdentifier);
154
155 void addVisitedLinkStoreUser(VisitedLinkStore&, WebCore::PageIdentifier);
156 void removeVisitedLinkStoreUser(VisitedLinkStore&, WebCore::PageIdentifier);
157
158 void addWebUserContentControllerProxy(WebUserContentControllerProxy&, WebPageCreationParameters&);
159 void didDestroyWebUserContentControllerProxy(WebUserContentControllerProxy&);
160
161 RefPtr<API::UserInitiatedAction> userInitiatedActivity(uint64_t);
162
163 ResponsivenessTimer& responsivenessTimer() { return m_responsivenessTimer; }
164 bool isResponsive() const;
165
166 WebFrameProxy* webFrame(uint64_t) const;
167 bool canCreateFrame(uint64_t frameID) const;
168 void frameCreated(uint64_t, WebFrameProxy&);
169 void disconnectFramesFromPage(WebPageProxy*); // Including main frame.
170 size_t frameCountInPage(WebPageProxy*) const; // Including main frame.
171
172 VisibleWebPageToken visiblePageToken() const;
173
174 void updateTextCheckerState();
175
176 void willAcquireUniversalFileReadSandboxExtension() { m_mayHaveUniversalFileReadSandboxExtension = true; }
177 void assumeReadAccessToBaseURL(WebPageProxy&, const String&);
178 bool hasAssumedReadAccessToURL(const URL&) const;
179
180 bool checkURLReceivedFromWebProcess(const String&);
181 bool checkURLReceivedFromWebProcess(const URL&);
182
183 static bool fullKeyboardAccessEnabled();
184
185 void didSaveToPageCache();
186 void releasePageCache();
187
188 void fetchWebsiteData(PAL::SessionID, OptionSet<WebsiteDataType>, CompletionHandler<void(WebsiteData)>&&);
189 void deleteWebsiteData(PAL::SessionID, OptionSet<WebsiteDataType>, WallTime modifiedSince, CompletionHandler<void()>&&);
190 void deleteWebsiteDataForOrigins(PAL::SessionID, OptionSet<WebsiteDataType>, const Vector<WebCore::SecurityOriginData>&, CompletionHandler<void()>&&);
191
192#if ENABLE(RESOURCE_LOAD_STATISTICS)
193 static void notifyPageStatisticsAndDataRecordsProcessed();
194 static void notifyPageStatisticsTelemetryFinished(API::Object* messageBody);
195
196 static void notifyWebsiteDataDeletionForRegistrableDomainsFinished();
197 static void notifyWebsiteDataScanForRegistrableDomainsFinished();
198#endif
199
200 void enableSuddenTermination();
201 void disableSuddenTermination();
202 bool isSuddenTerminationEnabled() { return !m_numberOfTimesSuddenTerminationWasDisabled; }
203
204 void requestTermination(ProcessTerminationReason);
205
206 void stopResponsivenessTimer();
207
208 RefPtr<API::Object> transformHandlesToObjects(API::Object*);
209 static RefPtr<API::Object> transformObjectsToHandles(API::Object*);
210
211#if PLATFORM(COCOA)
212 RefPtr<ObjCObjectGraph> transformHandlesToObjects(ObjCObjectGraph&);
213 static RefPtr<ObjCObjectGraph> transformObjectsToHandles(ObjCObjectGraph&);
214#endif
215
216 void windowServerConnectionStateChanged();
217
218 void processReadyToSuspend();
219 void didCancelProcessSuspension();
220
221 void setIsHoldingLockedFiles(bool);
222
223 ProcessThrottler& throttler() { return m_throttler; }
224
225 void isResponsive(CompletionHandler<void(bool isWebProcessResponsive)>&&);
226 void isResponsiveWithLazyStop();
227 void didReceiveMainThreadPing();
228 void didReceiveBackgroundResponsivenessPing();
229
230 void memoryPressureStatusChanged(bool isUnderMemoryPressure) { m_isUnderMemoryPressure = isUnderMemoryPressure; }
231 bool isUnderMemoryPressure() const { return m_isUnderMemoryPressure; }
232 void didExceedInactiveMemoryLimitWhileActive();
233
234 void processTerminated();
235
236 void didExceedCPULimit();
237 void didExceedActiveMemoryLimit();
238 void didExceedInactiveMemoryLimit();
239
240 void checkProcessLocalPortForActivity(const WebCore::MessagePortIdentifier&, CompletionHandler<void(WebCore::MessagePortChannelProvider::HasActivity)>&&);
241
242 void didCommitProvisionalLoad() { m_hasCommittedAnyProvisionalLoads = true; }
243 bool hasCommittedAnyProvisionalLoads() const { return m_hasCommittedAnyProvisionalLoads; }
244
245#if PLATFORM(WATCHOS)
246 void takeBackgroundActivityTokenForFullscreenInput();
247 void releaseBackgroundActivityTokenForFullscreenInput();
248#endif
249
250 bool isPrewarmed() const { return m_isPrewarmed; }
251 void markIsNoLongerInPrewarmedPool();
252
253#if PLATFORM(COCOA)
254 Vector<String> mediaMIMETypes();
255 void cacheMediaMIMETypes(const Vector<String>&);
256#endif
257
258#if PLATFORM(MAC)
259 void requestHighPerformanceGPU();
260 void releaseHighPerformanceGPU();
261#endif
262
263#if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
264 void startDisplayLink(unsigned observerID, uint32_t displayID);
265 void stopDisplayLink(unsigned observerID, uint32_t displayID);
266#endif
267
268 // Called when the web process has crashed or we know that it will terminate soon.
269 // Will potentially cause the WebProcessProxy object to be freed.
270 void shutDown();
271 void maybeShutDown(AllowProcessCaching = AllowProcessCaching::Yes);
272
273 void didStartProvisionalLoadForMainFrame(const URL&);
274
275 // ProcessThrottlerClient
276 void sendProcessWillSuspendImminently() override;
277 void sendPrepareToSuspend() override;
278 void sendCancelPrepareToSuspend() override;
279 void sendProcessDidResume() override;
280 void didSetAssertionState(AssertionState) override;
281
282#if PLATFORM(COCOA)
283 enum SandboxExtensionType : uint32_t {
284 None = 0,
285 Video = 1 << 0,
286 Audio = 1 << 1
287 };
288
289 typedef uint32_t MediaCaptureSandboxExtensions;
290
291 bool hasVideoCaptureExtension() const { return m_mediaCaptureSandboxExtensions & Video; }
292 void grantVideoCaptureExtension() { m_mediaCaptureSandboxExtensions |= Video; }
293 void revokeVideoCaptureExtension() { m_mediaCaptureSandboxExtensions &= ~Video; }
294
295 bool hasAudioCaptureExtension() const { return m_mediaCaptureSandboxExtensions & Audio; }
296 void grantAudioCaptureExtension() { m_mediaCaptureSandboxExtensions |= Audio; }
297 void revokeAudioCaptureExtension() { m_mediaCaptureSandboxExtensions &= ~Audio; }
298#endif
299
300#if PLATFORM(IOS_FAMILY)
301 void unblockAccessibilityServerIfNeeded();
302#endif
303
304#if PLATFORM(IOS_FAMILY)
305 void processWasUnexpectedlyUnsuspended(CompletionHandler<void()>&&);
306#endif
307
308 void webPageMediaStateDidChange(WebPageProxy&);
309
310protected:
311 static WebCore::PageIdentifier generatePageID();
312 WebProcessProxy(WebProcessPool&, WebsiteDataStore*, IsPrewarmed);
313
314 // AuxiliaryProcessProxy
315 void getLaunchOptions(ProcessLauncher::LaunchOptions&) override;
316 void platformGetLaunchOptions(ProcessLauncher::LaunchOptions&) override;
317 void connectionWillOpen(IPC::Connection&) override;
318 void processWillShutDown(IPC::Connection&) override;
319
320 // ProcessLauncher::Client
321 void didFinishLaunching(ProcessLauncher*, IPC::Connection::Identifier) override;
322
323#if PLATFORM(COCOA)
324 void cacheMediaMIMETypesInternal(const Vector<String>&);
325#endif
326
327 bool isJITEnabled() const final;
328
329 void validateFreezerStatus();
330
331private:
332 // IPC message handlers.
333 void updateBackForwardItem(const BackForwardListItemState&);
334 void didDestroyFrame(uint64_t);
335 void didDestroyUserGestureToken(uint64_t);
336
337 bool canBeAddedToWebProcessCache() const;
338 void shouldTerminate(CompletionHandler<void(bool)>&&);
339
340 void createNewMessagePortChannel(const WebCore::MessagePortIdentifier& port1, const WebCore::MessagePortIdentifier& port2);
341 void entangleLocalPortInThisProcessToRemote(const WebCore::MessagePortIdentifier& local, const WebCore::MessagePortIdentifier& remote);
342 void messagePortDisentangled(const WebCore::MessagePortIdentifier&);
343 void messagePortClosed(const WebCore::MessagePortIdentifier&);
344 void takeAllMessagesForPort(const WebCore::MessagePortIdentifier&, uint64_t messagesCallbackIdentifier);
345 void postMessageToRemote(WebCore::MessageWithMessagePorts&&, const WebCore::MessagePortIdentifier&);
346 void checkRemotePortForActivity(const WebCore::MessagePortIdentifier, uint64_t callbackIdentifier);
347 void didDeliverMessagePortMessages(uint64_t messageBatchIdentifier);
348 void didCheckProcessLocalPortForActivity(uint64_t callbackIdentifier, bool isLocallyReachable);
349
350 bool hasProvisionalPageWithID(WebCore::PageIdentifier) const;
351 bool isAllowedToUpdateBackForwardItem(WebBackForwardListItem&) const;
352
353 // Plugins
354#if ENABLE(NETSCAPE_PLUGIN_API)
355 void getPlugins(bool refresh, CompletionHandler<void(Vector<WebCore::PluginInfo>&& plugins, Vector<WebCore::PluginInfo>&& applicationPlugins, Optional<Vector<WebCore::SupportedPluginIdentifier>>&&)>&&);
356#endif // ENABLE(NETSCAPE_PLUGIN_API)
357#if ENABLE(NETSCAPE_PLUGIN_API)
358 void getPluginProcessConnection(uint64_t pluginProcessToken, Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply&&);
359#endif
360 void getNetworkProcessConnection(Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply&&);
361
362 bool platformIsBeingDebugged() const;
363 bool shouldAllowNonValidInjectedCode() const;
364
365 static const HashSet<String>& platformPathsWithAssumedReadAccess();
366
367 void updateBackgroundResponsivenessTimer();
368
369 void processDidTerminateOrFailedToLaunch();
370
371 bool isReleaseLoggingAllowed() const;
372
373 // IPC::Connection::Client
374 friend class WebConnectionToWebProcess;
375 void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
376 void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&) override;
377 void didClose(IPC::Connection&) override;
378 void didReceiveInvalidMessage(IPC::Connection&, IPC::StringReference messageReceiverName, IPC::StringReference messageName) override;
379
380 // ResponsivenessTimer::Client
381 void didBecomeUnresponsive() override;
382 void didBecomeResponsive() override;
383 void willChangeIsResponsive() override;
384 void didChangeIsResponsive() override;
385 bool mayBecomeUnresponsive() override;
386
387 // Implemented in generated WebProcessProxyMessageReceiver.cpp
388 void didReceiveWebProcessProxyMessage(IPC::Connection&, IPC::Decoder&);
389 void didReceiveSyncWebProcessProxyMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&);
390
391 bool canTerminateAuxiliaryProcess();
392
393 void didCollectPrewarmInformation(const WebCore::RegistrableDomain&, const WebCore::PrewarmInformation&);
394
395 void logDiagnosticMessageForResourceLimitTermination(const String& limitKey);
396
397 enum class IsWeak { No, Yes };
398 template<typename T> class WeakOrStrongPtr {
399 public:
400 WeakOrStrongPtr(T& object, IsWeak isWeak)
401 : m_isWeak(isWeak)
402 , m_weakObject(makeWeakPtr(object))
403 {
404 updateStrongReference();
405 }
406
407 void setIsWeak(IsWeak isWeak)
408 {
409 m_isWeak = isWeak;
410 updateStrongReference();
411 }
412
413 T* get() const { return m_weakObject.get(); }
414 T* operator->() const { return m_weakObject.get(); }
415 T& operator*() const { return *m_weakObject; }
416 explicit operator bool() const { return !!m_weakObject; }
417
418 private:
419 void updateStrongReference()
420 {
421 m_strongObject = m_isWeak == IsWeak::Yes ? nullptr : m_weakObject.get();
422 }
423
424 IsWeak m_isWeak;
425 WeakPtr<T> m_weakObject;
426 RefPtr<T> m_strongObject;
427 };
428
429 ResponsivenessTimer m_responsivenessTimer;
430 BackgroundProcessResponsivenessTimer m_backgroundResponsivenessTimer;
431
432 RefPtr<WebConnectionToWebProcess> m_webConnection;
433 WeakOrStrongPtr<WebProcessPool> m_processPool; // Pre-warmed and cached processes do not hold a strong reference to their pool.
434
435 bool m_mayHaveUniversalFileReadSandboxExtension; // True if a read extension for "/" was ever granted - we don't track whether WebProcess still has it.
436 HashSet<String> m_localPathsWithAssumedReadAccess;
437
438 WebPageProxyMap m_pageMap;
439 WebFrameProxyMap m_frameMap;
440 HashSet<ProvisionalPageProxy*> m_provisionalPages;
441 UserInitiatedActionMap m_userInitiatedActionMap;
442
443 HashMap<VisitedLinkStore*, HashSet<WebCore::PageIdentifier>> m_visitedLinkStoresWithUsers;
444 HashSet<WebUserContentControllerProxy*> m_webUserContentControllerProxies;
445
446 int m_numberOfTimesSuddenTerminationWasDisabled;
447 ProcessThrottler m_throttler;
448 ProcessThrottler::BackgroundActivityToken m_tokenForHoldingLockedFiles;
449#if PLATFORM(IOS_FAMILY)
450 ForegroundWebProcessToken m_foregroundToken;
451 BackgroundWebProcessToken m_backgroundToken;
452 bool m_hasSentMessageToUnblockAccessibilityServer { false };
453 std::unique_ptr<WebCore::DeferrableOneShotTimer> m_unexpectedActivityTimer;
454#endif
455
456 HashMap<String, uint64_t> m_pageURLRetainCountMap;
457
458 Optional<WebCore::RegistrableDomain> m_registrableDomain;
459 bool m_isInProcessCache { false };
460
461 enum class NoOrMaybe { No, Maybe } m_isResponsive;
462 Vector<CompletionHandler<void(bool webProcessIsResponsive)>> m_isResponsiveCallbacks;
463
464 VisibleWebPageCounter m_visiblePageCounter;
465
466 RefPtr<WebsiteDataStore> m_websiteDataStore;
467
468 bool m_isUnderMemoryPressure { false };
469
470#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
471 std::unique_ptr<UserMediaCaptureManagerProxy> m_userMediaCaptureManagerProxy;
472#endif
473
474 HashSet<WebCore::MessagePortIdentifier> m_processEntangledPorts;
475 HashMap<uint64_t, Function<void()>> m_messageBatchDeliveryCompletionHandlers;
476 HashMap<uint64_t, CompletionHandler<void(WebCore::MessagePortChannelProvider::HasActivity)>> m_localPortActivityCompletionHandlers;
477
478 unsigned m_suspendedPageCount { 0 };
479 bool m_hasCommittedAnyProvisionalLoads { false };
480 bool m_isPrewarmed;
481 bool m_hasAudibleWebPage { false };
482
483#if PLATFORM(WATCHOS)
484 ProcessThrottler::BackgroundActivityToken m_backgroundActivityTokenForFullscreenFormControls;
485#endif
486
487#if PLATFORM(COCOA)
488 MediaCaptureSandboxExtensions m_mediaCaptureSandboxExtensions { SandboxExtensionType::None };
489#endif
490};
491
492} // namespace WebKit
493