[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[WebKit-https.git] / Source / WebKit / UIProcess / Cocoa / WebProcessProxyCocoa.mm
1 /*
2  * Copyright (C) 2014-2016 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 #import "config.h"
27 #import "WebProcessProxy.h"
28
29 #import "HighPerformanceGPUManager.h"
30 #import "Logging.h"
31 #import "ObjCObjectGraph.h"
32 #import "SandboxUtilities.h"
33 #import "WKBrowsingContextControllerInternal.h"
34 #import "WKBrowsingContextHandleInternal.h"
35 #import "WKTypeRefWrapper.h"
36 #import "WebProcessMessages.h"
37 #import "WebProcessPool.h"
38 #import <sys/sysctl.h>
39 #import <wtf/NeverDestroyed.h>
40 #import <wtf/spi/darwin/SandboxSPI.h>
41
42 namespace WebKit {
43
44 static const Seconds unexpectedActivityDuration = 10_s;
45
46 const HashSet<String>& WebProcessProxy::platformPathsWithAssumedReadAccess()
47 {
48     static NeverDestroyed<HashSet<String>> platformPathsWithAssumedReadAccess(std::initializer_list<String> {
49         [NSBundle bundleWithIdentifier:@"com.apple.WebCore"].resourcePath.stringByStandardizingPath,
50         [NSBundle bundleWithIdentifier:@"com.apple.WebKit"].resourcePath.stringByStandardizingPath
51     });
52
53     return platformPathsWithAssumedReadAccess;
54 }
55
56 RefPtr<ObjCObjectGraph> WebProcessProxy::transformHandlesToObjects(ObjCObjectGraph& objectGraph)
57 {
58     struct Transformer final : ObjCObjectGraph::Transformer {
59         Transformer(WebProcessProxy& webProcessProxy)
60             : m_webProcessProxy(webProcessProxy)
61         {
62         }
63
64         bool shouldTransformObject(id object) const override
65         {
66             if (dynamic_objc_cast<WKBrowsingContextHandle>(object))
67                 return true;
68
69             ALLOW_DEPRECATED_DECLARATIONS_BEGIN
70             if (dynamic_objc_cast<WKTypeRefWrapper>(object))
71                 return true;
72             ALLOW_DEPRECATED_DECLARATIONS_END
73             return false;
74         }
75
76         RetainPtr<id> transformObject(id object) const override
77         {
78             if (auto* handle = dynamic_objc_cast<WKBrowsingContextHandle>(object)) {
79                 if (auto* webPageProxy = m_webProcessProxy.webPage(handle.pageID)) {
80                     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
81                     return [WKBrowsingContextController _browsingContextControllerForPageRef:toAPI(webPageProxy)];
82                     ALLOW_DEPRECATED_DECLARATIONS_END
83                 }
84
85                 return [NSNull null];
86             }
87
88             ALLOW_DEPRECATED_DECLARATIONS_BEGIN
89             if (auto* wrapper = dynamic_objc_cast<WKTypeRefWrapper>(object))
90                 return adoptNS([[WKTypeRefWrapper alloc] initWithObject:toAPI(m_webProcessProxy.transformHandlesToObjects(toImpl(wrapper.object)).get())]);
91             ALLOW_DEPRECATED_DECLARATIONS_END
92             return object;
93         }
94
95         WebProcessProxy& m_webProcessProxy;
96     };
97
98     return ObjCObjectGraph::create(ObjCObjectGraph::transform(objectGraph.rootObject(), Transformer(*this)).get());
99 }
100
101 RefPtr<ObjCObjectGraph> WebProcessProxy::transformObjectsToHandles(ObjCObjectGraph& objectGraph)
102 {
103     struct Transformer final : ObjCObjectGraph::Transformer {
104         bool shouldTransformObject(id object) const override
105         {
106             ALLOW_DEPRECATED_DECLARATIONS_BEGIN
107             if (dynamic_objc_cast<WKBrowsingContextController>(object))
108                 return true;
109             if (dynamic_objc_cast<WKTypeRefWrapper>(object))
110                 return true;
111             ALLOW_DEPRECATED_DECLARATIONS_END
112             return false;
113         }
114
115         RetainPtr<id> transformObject(id object) const override
116         {
117             ALLOW_DEPRECATED_DECLARATIONS_BEGIN
118             if (auto* controller = dynamic_objc_cast<WKBrowsingContextController>(object))
119                 return controller.handle;
120             if (auto* wrapper = dynamic_objc_cast<WKTypeRefWrapper>(object))
121                 return adoptNS([[WKTypeRefWrapper alloc] initWithObject:toAPI(transformObjectsToHandles(toImpl(wrapper.object)).get())]);
122             ALLOW_DEPRECATED_DECLARATIONS_END
123             return object;
124         }
125     };
126
127     return ObjCObjectGraph::create(ObjCObjectGraph::transform(objectGraph.rootObject(), Transformer()).get());
128 }
129
130 bool WebProcessProxy::platformIsBeingDebugged() const
131 {
132     // If the UI process is sandboxed and lacks 'process-info-pidinfo', it cannot find out whether other processes are being debugged.
133     if (currentProcessIsSandboxed() && !!sandbox_check(getpid(), "process-info-pidinfo", SANDBOX_CHECK_NO_REPORT))
134         return false;
135
136     struct kinfo_proc info;
137     int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, processIdentifier() };
138     size_t size = sizeof(info);
139     if (sysctl(mib, WTF_ARRAY_LENGTH(mib), &info, &size, nullptr, 0) == -1)
140         return false;
141
142     return info.kp_proc.p_flag & P_TRACED;
143 }
144
145 static Vector<String>& mediaTypeCache()
146 {
147     ASSERT(RunLoop::isMain());
148     static NeverDestroyed<Vector<String>> typeCache;
149     return typeCache;
150 }
151
152 void WebProcessProxy::cacheMediaMIMETypes(const Vector<String>& types)
153 {
154     if (!mediaTypeCache().isEmpty())
155         return;
156
157     mediaTypeCache() = types;
158     for (auto& process : processPool().processes()) {
159         if (process != this)
160             cacheMediaMIMETypesInternal(types);
161     }
162 }
163
164 void WebProcessProxy::cacheMediaMIMETypesInternal(const Vector<String>& types)
165 {
166     if (!mediaTypeCache().isEmpty())
167         return;
168
169     mediaTypeCache() = types;
170     send(Messages::WebProcess::SetMediaMIMETypes(types), 0);
171 }
172
173 Vector<String> WebProcessProxy::mediaMIMETypes() const
174 {
175     return mediaTypeCache();
176 }
177
178 #if PLATFORM(MAC)
179 void WebProcessProxy::requestHighPerformanceGPU()
180 {
181     LOG(WebGL, "WebProcessProxy::requestHighPerformanceGPU()");
182     HighPerformanceGPUManager::singleton().addProcessRequiringHighPerformance(this);
183 }
184
185 void WebProcessProxy::releaseHighPerformanceGPU()
186 {
187     LOG(WebGL, "WebProcessProxy::releaseHighPerformanceGPU()");
188     HighPerformanceGPUManager::singleton().removeProcessRequiringHighPerformance(this);
189 }
190 #endif
191
192 #if PLATFORM(IOS_FAMILY)
193 void WebProcessProxy::processWasUnexpectedlyUnsuspended(CompletionHandler<void()>&& completion)
194 {
195     if (m_throttler.shouldBeRunnable()) {
196         // The process becoming unsuspended was not unexpected; it likely was notified of its running state
197         // before receiving a procsessDidResume() message from the UIProcess.
198         completion();
199         return;
200     }
201
202     // The WebProcess was awakened by something other than the UIProcess. Take out an assertion for a
203     // limited duration to allow whatever task needs to be accomplished time to complete.
204     RELEASE_LOG(ProcessSuspension, "%p - WebProcessProxy::processWasUnexpectedlyUnsuspended()", this);
205     auto backgroundActivityTimeoutHandler = [activityToken = m_throttler.backgroundActivityToken(), weakThis = makeWeakPtr(this)] {
206         RELEASE_LOG(ProcessSuspension, "%p - WebProcessProxy::processWasUnexpectedlyUnsuspended() - lambda, background activity timed out", weakThis.get());
207     };
208     m_unexpectedActivityTimer = makeUnique<WebCore::DeferrableOneShotTimer>(WTFMove(backgroundActivityTimeoutHandler), unexpectedActivityDuration);
209     completion();
210 }
211 #endif
212
213 }