Skip to content

Commit

Permalink
Implement layer hosting for WebKit extension processes
Browse files Browse the repository at this point in the history
rdar://119381400
https://bugs.webkit.org/show_bug.cgi?id=266078

Reviewed by Andy Estes and Brent Fulgham.

Implement layer hosting for WebKit extension processes. In this implementation, the remote context is
represented by an object of type _SEHostable. In this implementation, the _SEHostable object is created
in the GPU process. The remote context is shared by extracting the context ID from the XPC representation
of the _SEHostable object, and sent to the UI process via the WebContent process as in the former
implementation. In the UI process, a _SEHostingHandle is created from the received context ID and
attached to the new view type we create in the UI process, _SEHostingView. Fencing is implemented with
the new object type _SEHostingUpdateCoordinator. This object is created in the UI process, and shared
with the GPU process from its XPC representation, which contains a Mach send right.

* Source/WebKit/GPUProcess/media/cocoa/RemoteMediaPlayerProxyCocoa.mm:
(WebKit::RemoteMediaPlayerProxy::mediaPlayerRenderingModeChanged):
(WebKit::RemoteMediaPlayerProxy::setVideoLayerSizeFenced):
* Source/WebKit/Platform/ExtraPrivateSymbolsForTAPI.h:
* Source/WebKit/Platform/cocoa/LayerHostingContext.h:
* Source/WebKit/Platform/cocoa/LayerHostingContext.mm:
(WebKit::LayerHostingContext::createForExternalHostingProcess):
(WebKit::LayerHostingContext::~LayerHostingContext):
(WebKit::LayerHostingContext::setRootLayer):
(WebKit::LayerHostingContext::rootLayer const):
(WebKit::LayerHostingContext::contextID const):
(WebKit::LayerHostingContext::setFencePort):
(WebKit::LayerHostingContext::xpcRepresentation const):
(WebKit::LayerHostingContext::commit):
* Source/WebKit/Platform/spi/Cocoa/ExtensionKitSPI.h:
* Source/WebKit/Shared/Cocoa/ExtensionKitSoftLink.h:
* Source/WebKit/Shared/Cocoa/ExtensionKitSoftLink.mm:
* Source/WebKit/Shared/Cocoa/WKProcessExtension.mm:
* Source/WebKit/UIProcess/Cocoa/VideoPresentationManagerProxy.mm:
(-[WKLayerHostView dealloc]):
(WebKit::VideoPresentationManagerProxy::createLayerHostViewWithID):
(WebKit::VideoPresentationManagerProxy::setVideoLayerFrame):

Canonical link: https://commits.webkit.org/272703@main
  • Loading branch information
pvollan committed Jan 5, 2024
1 parent dd3ee10 commit b674f6c
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@

auto* layer = m_player->platformLayer();
if (layer && !m_inlineLayerHostingContext) {
m_inlineLayerHostingContext = LayerHostingContext::createForExternalHostingProcess();
LayerHostingContextOptions contextOptions;
#if USE(EXTENSIONKIT)
contextOptions.useHostable = true;
#endif
m_inlineLayerHostingContext = LayerHostingContext::createForExternalHostingProcess(contextOptions);
IntSize presentationSize = enclosingIntRect(FloatRect(layer.frame)).size();
m_webProcessConnection->send(Messages::MediaPlayerPrivateRemote::LayerHostingContextIdChanged(m_inlineLayerHostingContext->contextID(), presentationSize), m_id);
for (auto& request : std::exchange(m_layerHostingContextIDRequests, { }))
Expand Down Expand Up @@ -102,6 +106,11 @@
setVideoLayerSizeIfPossible(size);

m_player->setVideoLayerSizeFenced(size, WTFMove(machSendRight));

#if USE(EXTENSIONKIT)
if (m_inlineLayerHostingContext)
m_inlineLayerHostingContext->commit();
#endif
}

void RemoteMediaPlayerProxy::mediaPlayerOnNewVideoFrameMetadata(VideoFrameMetadata&& metadata, RetainPtr<CVPixelBufferRef>&& buffer)
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/Platform/ExtraPrivateSymbolsForTAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ void GPUServiceInitializer();

void ExtensionEventHandler(xpc_connection_t);

#if USE(EXTENSIONKIT)
// Declared in WKProcessExtension.h for use in extension targets. Must be declared in project
// headers because the extension targets cannot import the entire WebKit module (rdar://119162443).
@interface WKGrant : NSObject
@end

@interface WKProcessExtension : NSObject
@end
#endif

#ifdef __cplusplus
}
Expand Down
18 changes: 18 additions & 0 deletions Source/WebKit/Platform/cocoa/LayerHostingContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,17 @@

#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
#include <wtf/OSObjectPtr.h>
#include <wtf/RetainPtr.h>

OBJC_CLASS CALayer;
OBJC_CLASS CAContext;

#if USE(EXTENSIONKIT)
OBJC_CLASS _SEHostable;
OBJC_CLASS _SEHostingUpdateCoordinator;
#endif

namespace WTF {
class MachSendRight;
}
Expand All @@ -45,6 +51,9 @@ struct LayerHostingContextOptions {
#if PLATFORM(IOS_FAMILY)
bool canShowWhileLocked { false };
#endif
#if USE(EXTENSIONKIT)
bool useHostable { false };
#endif
};

class LayerHostingContext {
Expand Down Expand Up @@ -96,13 +105,22 @@ class LayerHostingContext {
void updateCachedContextID(LayerHostingContextID);
LayerHostingContextID cachedContextID();

#if USE(EXTENSIONKIT)
OSObjectPtr<xpc_object_t> xpcRepresentation() const;
void commit();
#endif

private:
LayerHostingMode m_layerHostingMode;
// Denotes the contextID obtained from GPU process, should be returned
// for all calls to context ID in web process when UI side compositing
// is enabled. This is done to avoid making calls to CARenderServer from webprocess
LayerHostingContextID m_cachedContextID;
RetainPtr<CAContext> m_context;
#if USE(EXTENSIONKIT)
RetainPtr<_SEHostable> m_hostable;
RetainPtr<_SEHostingUpdateCoordinator> m_hostingUpdateCoordinator;
#endif
};

} // namespace WebKit
Expand Down
61 changes: 59 additions & 2 deletions Source/WebKit/Platform/cocoa/LayerHostingContext.mm
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@
#import <pal/spi/cocoa/QuartzCoreSPI.h>
#import <wtf/MachSendRight.h>

#if USE(EXTENSIONKIT)
#import "ExtensionKitSPI.h"

SOFT_LINK_FRAMEWORK_OPTIONAL(ServiceExtensions);
SOFT_LINK_CLASS_OPTIONAL(ServiceExtensions, _SEHostable);
SOFT_LINK_CLASS_OPTIONAL(ServiceExtensions, _SEHostingUpdateCoordinator);
#endif

namespace WebKit {

std::unique_ptr<LayerHostingContext> LayerHostingContext::createForPort(const MachSendRight& serverPort)
Expand Down Expand Up @@ -60,13 +68,20 @@
#if PLATFORM(IOS_FAMILY) && !PLATFORM(MACCATALYST)
// Use a very large display ID to ensure that the context is never put on-screen
// without being explicitly parented. See <rdar://problem/16089267> for details.
layerHostingContext->m_context = [CAContext remoteContextWithOptions:@{
auto contextOptions = @{
kCAContextSecure: @(options.canShowWhileLocked),
#if HAVE(CORE_ANIMATION_RENDER_SERVER)
kCAContextIgnoresHitTest : @YES,
kCAContextDisplayId : @10000
#endif
}];
};
#if USE(EXTENSIONKIT)
if (options.useHostable && [get_SEHostableClass() respondsToSelector:@selector(createHostableWithOptions:error:)]) {
layerHostingContext->m_hostable = [get_SEHostableClass() createHostableWithOptions:contextOptions error:nil];
return layerHostingContext;
}
#endif
layerHostingContext->m_context = [CAContext remoteContextWithOptions:contextOptions];
#elif !PLATFORM(MACCATALYST)
[CAContext setAllowsCGSConnections:NO];
layerHostingContext->m_context = [CAContext remoteContextWithOptions:@{
Expand Down Expand Up @@ -112,20 +127,37 @@

LayerHostingContext::~LayerHostingContext()
{
#if USE(EXTENSIONKIT)
[m_hostingUpdateCoordinator commit];
#endif
}

void LayerHostingContext::setRootLayer(CALayer *rootLayer)
{
#if USE(EXTENSIONKIT)
if (m_hostable) {
[m_hostable setLayer:rootLayer];
return;
}
#endif
[m_context setLayer:rootLayer];
}

CALayer *LayerHostingContext::rootLayer() const
{
#if USE(EXTENSIONKIT)
if (m_hostable)
return [m_hostable layer];
#endif
return [m_context layer];
}

LayerHostingContextID LayerHostingContext::contextID() const
{
#if USE(EXTENSIONKIT)
if (auto xpcDictionary = xpcRepresentation())
return xpc_dictionary_get_uint64(xpcDictionary.get(), "cid");
#endif
return [m_context contextId];
}

Expand Down Expand Up @@ -158,6 +190,16 @@

void LayerHostingContext::setFencePort(mach_port_t fencePort)
{
#if USE(EXTENSIONKIT)
if (m_hostable) {
auto xpcRepresentation = adoptOSObject(xpc_dictionary_create(nullptr, nullptr, 0));
xpc_dictionary_set_mach_send(xpcRepresentation.get(), "p", fencePort);
[m_hostingUpdateCoordinator commit];
m_hostingUpdateCoordinator = adoptNS([alloc_SEHostingUpdateCoordinatorInstance() initFromXPCRepresentation:xpcRepresentation.get()]);
[m_hostingUpdateCoordinator addHostable:m_hostable.get()];
return;
}
#endif
[m_context setFencePort:fencePort];
}

Expand All @@ -176,4 +218,19 @@
return m_cachedContextID;
}

#if USE(EXTENSIONKIT)
OSObjectPtr<xpc_object_t> LayerHostingContext::xpcRepresentation() const
{
if (!m_hostable)
return nullptr;
return [[m_hostable handle] xpcRepresentation];
}

void LayerHostingContext::commit()
{
[m_hostingUpdateCoordinator commit];
m_hostingUpdateCoordinator = nullptr;
}
#endif

} // namespace WebKit
31 changes: 31 additions & 0 deletions Source/WebKit/Platform/spi/Cocoa/ExtensionKitSPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@

#if USE(EXTENSIONKIT)

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

#if __has_include(<ServiceExtensions/ServiceExtensions_Private.h>)
#import <ServiceExtensions/ServiceExtensions_Private.h>
#else
Expand Down Expand Up @@ -102,6 +105,8 @@ NS_ASSUME_NONNULL_END

#endif

NS_ASSUME_NONNULL_BEGIN

@interface _SECapability (SPI)
- (BOOL)setActive:(BOOL)active;
+ (instancetype)mediaWithWebsite:(NSString *)website;
Expand All @@ -111,4 +116,30 @@ NS_ASSUME_NONNULL_END
@property (nonatomic, readonly) NSString *mediaEnvironment;
@end

@interface _SEHostingHandle: NSObject
-(instancetype)initFromXPCRepresentation:(xpc_object_t)xpcRepresentation;
-(xpc_object_t)xpcRepresentation;
@end

@interface _SEHostable: NSObject
+(_SEHostable*)createHostableWithOptions:(NSDictionary*)dict error:(NSError**)error;
@property (nonatomic, readonly) _SEHostingHandle* handle;
@property (nonatomic, strong) CALayer *layer;
@end

@interface _SEHostingView: UIView
@property (nonatomic, retain) _SEHostingHandle* handle;
@end

@interface _SEHostingUpdateCoordinator : NSObject
-(instancetype)init;
-(instancetype)initFromXPCRepresentation:(xpc_object_t)xpcRepresentation;
-(xpc_object_t)xpcRepresentation;
-(void)addHostable:(_SEHostable*)hostable;
-(void)addHostingView:(_SEHostingView*)hostingView;
-(void)commit;
@end

NS_ASSUME_NONNULL_END

#endif // USE(EXTENSIONKIT)
4 changes: 4 additions & 0 deletions Source/WebKit/Shared/Cocoa/ExtensionKitSoftLink.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,9 @@
SOFT_LINK_FRAMEWORK_FOR_HEADER(WebKit, ServiceExtensions)

SOFT_LINK_CLASS_FOR_HEADER(WebKit, _SECapability)
SOFT_LINK_CLASS_FOR_HEADER(WebKit, _SEHostable)
SOFT_LINK_CLASS_FOR_HEADER(WebKit, _SEHostingHandle)
SOFT_LINK_CLASS_FOR_HEADER(WebKit, _SEHostingUpdateCoordinator)
SOFT_LINK_CLASS_FOR_HEADER(WebKit, _SEHostingView)

#endif // USE(EXTENSIONKIT)
4 changes: 4 additions & 0 deletions Source/WebKit/Shared/Cocoa/ExtensionKitSoftLink.mm
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,9 @@
SOFT_LINK_FRAMEWORK_FOR_SOURCE(WebKit, ServiceExtensions)

SOFT_LINK_CLASS_FOR_SOURCE(WebKit, ServiceExtensions, _SECapability)
SOFT_LINK_CLASS_FOR_SOURCE(WebKit, ServiceExtensions, _SEHostable)
SOFT_LINK_CLASS_FOR_SOURCE(WebKit, ServiceExtensions, _SEHostingHandle)
SOFT_LINK_CLASS_FOR_SOURCE(WebKit, ServiceExtensions, _SEHostingUpdateCoordinator)
SOFT_LINK_CLASS_FOR_SOURCE(WebKit, ServiceExtensions, _SEHostingView)

#endif // USE(EXTENSIONKIT)
4 changes: 4 additions & 0 deletions Source/WebKit/Shared/Cocoa/WKProcessExtension.mm
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
*/

#import "config.h"

#if USE(EXTENSIONKIT)
#import "WKProcessExtension.h"

#import <wtf/RetainPtr.h>
Expand Down Expand Up @@ -57,3 +59,5 @@ - (void)lockdownSandbox:(NSString*)version
{
}
@end

#endif // USE(EXTENSIONKIT)
53 changes: 51 additions & 2 deletions Source/WebKit/UIProcess/Cocoa/VideoPresentationManagerProxy.mm
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#import "VideoPresentationManagerProxyMessages.h"
#import "WKVideoView.h"
#import "WebPageProxy.h"
#import "WebProcessPool.h"
#import "WebProcessProxy.h"
#import <QuartzCore/CoreAnimation.h>
#import <WebCore/MediaPlayerEnums.h>
Expand All @@ -58,6 +59,10 @@
#import <pal/spi/cocoa/AVKitSPI.h>
#endif

#if USE(EXTENSIONKIT)
#import "ExtensionKitSoftlink.h"
#endif

@interface WKLayerHostView : PlatformView
@property (nonatomic, assign) uint32_t contextID;
@end
Expand All @@ -66,6 +71,11 @@ @implementation WKLayerHostView {
#if PLATFORM(IOS_FAMILY)
WeakObjCPtr<UIWindow> _window;
#endif
#if USE(EXTENSIONKIT)
@public
RetainPtr<_SEHostingView> _hostingView;
RetainPtr<_SEHostingUpdateCoordinator> _hostingUpdateCoordinator;
#endif
}

#if PLATFORM(IOS_FAMILY)
Expand All @@ -79,6 +89,14 @@ - (CALayer *)makeBackingLayer
}
#endif

#if USE(EXTENSIONKIT)
- (void)dealloc
{
[_hostingUpdateCoordinator commit];
[super dealloc];
}
#endif

- (uint32_t)contextID {
return [[self layerHost] contextId];
}
Expand Down Expand Up @@ -718,7 +736,25 @@ - (BOOL)prefersStatusBarHidden
[view layer].frame = CGRectMake(0, 0, initialSize.width(), initialSize.height());
}

#if USE(EXTENSIONKIT)
if (!view->_hostingView) {
auto pid = m_page->process().processPool().gpuProcess()->processID();
auto xpcRepresentation = adoptOSObject(xpc_dictionary_create(nullptr, nullptr, 0));
xpc_dictionary_set_uint64(xpcRepresentation.get(), "pid", pid);
xpc_dictionary_set_uint64(xpcRepresentation.get(), "cid", videoLayerID);
auto handle = adoptNS([alloc_SEHostingHandleInstance() initFromXPCRepresentation:xpcRepresentation.get()]);
auto hostingView = adoptNS([[_SEHostingView alloc] init]);
[hostingView setHandle:handle.get()];
view->_hostingView = hostingView;
[view addSubview:hostingView.get()];

[hostingView layer].masksToBounds = NO;
[hostingView layer].name = @"WKLayerHostView layer";
[hostingView layer].frame = CGRectMake(0, 0, initialSize.width(), initialSize.height());
}
#else
[view setContextID:videoLayerID];
#endif

interface->setupCaptionsLayer([view layer], initialSize);

Expand Down Expand Up @@ -1177,10 +1213,23 @@ - (BOOL)prefersStatusBarHidden

auto& [model, interface] = ensureModelAndInterface(contextId);
interface->setCaptionsFrame(CGRectMake(0, 0, frame.width(), frame.height()));
MachSendRight fenceSendRight;
#if PLATFORM(IOS_FAMILY)
auto fenceSendRight = MachSendRight::adopt([UIWindow _synchronizeDrawingAcrossProcesses]);
#if USE(EXTENSIONKIT)
RetainPtr<WKLayerHostView> view = static_cast<WKLayerHostView*>(model->layerHostView());
if (view && view->_hostingView) {
if (!view->_hostingUpdateCoordinator) {
auto hostingUpdateCoordinator = adoptNS([alloc_SEHostingUpdateCoordinatorInstance() init]);
[hostingUpdateCoordinator addHostingView:view->_hostingView.get()];
view->_hostingUpdateCoordinator = hostingUpdateCoordinator;
}
OSObjectPtr<xpc_object_t> xpcRepresentationHostingCoordinator = [view->_hostingUpdateCoordinator xpcRepresentation];
fenceSendRight = MachSendRight::adopt(xpc_dictionary_copy_mach_send(xpcRepresentationHostingCoordinator.get(), "p"));
}
#else
fenceSendRight = MachSendRight::adopt([UIWindow _synchronizeDrawingAcrossProcesses]);
#endif // USE(EXTENSIONKIT)
#else
MachSendRight fenceSendRight;
if (DrawingAreaProxy* drawingArea = m_page->drawingArea())
fenceSendRight = drawingArea->createFence();
#endif
Expand Down

0 comments on commit b674f6c

Please sign in to comment.