Enable library validation on the Web Content service
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Jan 2018 23:30:23 +0000 (23:30 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Jan 2018 23:30:23 +0000 (23:30 +0000)
Part 1 of https://bugs.webkit.org/show_bug.cgi?id=172365
<rdar://problem/26470661>

Reviewed by David Kilzer.

This makes the Web Content process signed with the Library Validation flag in production
builds. Because doing so would prevent engineering builds of Apple apps that use an
injected bundle from working, this also adds a Development version of the service, which
does not enforce Library Validation. The UI process chooses to use the Development service
iff it would need to load an injected bundle that is not part of the OS.

* Configurations/DebugRelease.xcconfig: Disable Library Validation in engineering builds.

* Configurations/WebContentService.Development.xcconfig: Added. Like the normal service, but
  only installed when WebKit is installed in the OS, and uses a Development variant.

* Configurations/WebContentService.xcconfig: For the Development variant, append
  ".Development" to the product name, which is also the service identifier. Enable Library
  Validation for the Normal variant of the service when WK_LIBRARY_VALIDATION_ENABLED allows
  it.

* UIProcess/Launcher/ProcessLauncher.h: Add nonValidInjectedCodeAllowed member to
  LaunchOptions, false by default.

* UIProcess/Launcher/mac/ProcessLauncherMac.mm:
(WebKit::serviceName): Use the Development variant if nonValidInjectedCodeAllowed is true.

* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::getLaunchOptions): Initialize nonValidInjectedCodeAllowed using
   the new shouldAllowNonValidInjectedCode().
(WebKit::WebProcessProxy::shouldAllowNonValidInjectedCode const): Generic implementation
  that returns false.
* UIProcess/WebProcessProxy.h: Declared shouldAllowNonValidInjectedCode.
* UIProcess/mac/WebProcessProxyMac.mm:
(WebKit::WebProcessProxy::shouldAllowNonValidInjectedCode const): Return true if this is
  system WebKit with a non-system injected bundle.

* WebKit.xcodeproj/project.pbxproj: Added new service target.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@227582 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/ChangeLog
Source/WebKit/Configurations/DebugRelease.xcconfig
Source/WebKit/Configurations/WebContentService.Development.xcconfig [new file with mode: 0644]
Source/WebKit/Configurations/WebContentService.xcconfig
Source/WebKit/UIProcess/Launcher/ProcessLauncher.h
Source/WebKit/UIProcess/Launcher/mac/ProcessLauncherMac.mm
Source/WebKit/UIProcess/WebProcessProxy.cpp
Source/WebKit/UIProcess/WebProcessProxy.h
Source/WebKit/UIProcess/mac/WebProcessProxyMac.mm
Source/WebKit/WebKit.xcodeproj/project.pbxproj

index 006010b..62512b8 100644 (file)
@@ -1,3 +1,45 @@
+2018-01-24  Dan Bernstein  <mitz@apple.com>
+
+        Enable library validation on the Web Content service
+        Part 1 of https://bugs.webkit.org/show_bug.cgi?id=172365
+        <rdar://problem/26470661>
+
+        Reviewed by David Kilzer.
+
+        This makes the Web Content process signed with the Library Validation flag in production
+        builds. Because doing so would prevent engineering builds of Apple apps that use an
+        injected bundle from working, this also adds a Development version of the service, which
+        does not enforce Library Validation. The UI process chooses to use the Development service
+        iff it would need to load an injected bundle that is not part of the OS.
+
+        * Configurations/DebugRelease.xcconfig: Disable Library Validation in engineering builds.
+
+        * Configurations/WebContentService.Development.xcconfig: Added. Like the normal service, but
+          only installed when WebKit is installed in the OS, and uses a Development variant.
+
+        * Configurations/WebContentService.xcconfig: For the Development variant, append
+          ".Development" to the product name, which is also the service identifier. Enable Library
+          Validation for the Normal variant of the service when WK_LIBRARY_VALIDATION_ENABLED allows
+          it.
+
+        * UIProcess/Launcher/ProcessLauncher.h: Add nonValidInjectedCodeAllowed member to
+          LaunchOptions, false by default.
+
+        * UIProcess/Launcher/mac/ProcessLauncherMac.mm:
+        (WebKit::serviceName): Use the Development variant if nonValidInjectedCodeAllowed is true.
+
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::getLaunchOptions): Initialize nonValidInjectedCodeAllowed using
+           the new shouldAllowNonValidInjectedCode().
+        (WebKit::WebProcessProxy::shouldAllowNonValidInjectedCode const): Generic implementation
+          that returns false.
+        * UIProcess/WebProcessProxy.h: Declared shouldAllowNonValidInjectedCode.
+        * UIProcess/mac/WebProcessProxyMac.mm:
+        (WebKit::WebProcessProxy::shouldAllowNonValidInjectedCode const): Return true if this is
+          system WebKit with a non-system injected bundle.
+
+        * WebKit.xcodeproj/project.pbxproj: Added new service target.
+
 2018-01-24  Chris Dumez  <cdumez@apple.com>
 
         Add a IPC::SendSyncOption indicating we should not process incoming IPC while waiting for the sync reply
index b9f9bc2..f3eee6d 100644 (file)
@@ -47,6 +47,7 @@ WK_RELOCATABLE_FRAMEWORKS = YES;
 WK_XPC_SERVICE_SUFFIX[sdk=macosx*] = .Development;
 WK_XPC_SERVICE_SUFFIX[sdk=*simulator*] = .Development;
 
+WK_LIBRARY_VALIDATION_ENABLED = NO;
 WK_WEBCONTENT_SERVICE_NEEDS_XPC_DOMAIN_EXTENSION_ENTITLEMENT = NO;
 WK_WEBCONTENT_SERVICE_NEEDS_VERSIONED_FRAMEWORK_PATH_LDFLAG[sdk=macosx*] = YES;
 
diff --git a/Source/WebKit/Configurations/WebContentService.Development.xcconfig b/Source/WebKit/Configurations/WebContentService.Development.xcconfig
new file mode 100644 (file)
index 0000000..3825c26
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright (C) 2018 Apple Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+
+#include "WebContentService.xcconfig"
+
+SKIP_INSTALL = YES;
+SKIP_INSTALL[sdk=macosx*] = $(WK_RELOCATABLE_FRAMEWORKS);
+
+WK_XPC_SERVICE_VARIANT = Development;
index 74fe3c5..eb5ec17 100644 (file)
@@ -27,9 +27,13 @@ WK_XPC_SERVICE_IOS_ENTITLEMENTS_BASE = WebContent-iOS;
 
 CODE_SIGN_ENTITLEMENTS[sdk=macosx*] = $(CODE_SIGN_ENTITLEMENTS_OSX_WITH_XPC_DOMAIN_EXTENSION_$(WK_WEBCONTENT_SERVICE_NEEDS_XPC_DOMAIN_EXTENSION_ENTITLEMENT));
 CODE_SIGN_ENTITLEMENTS_OSX_WITH_XPC_DOMAIN_EXTENSION_YES = Configurations/WebContent-OSX.entitlements;
-OTHER_CODE_SIGN_FLAGS[sdk=macosx*] = $(WK_XPC_DOMAIN_EXTENSION_CODE_SIGN_FLAGS);
+OTHER_CODE_SIGN_FLAGS[sdk=macosx*] = $(WK_LIBRARY_VALIDATION_CODE_SIGN_FLAGS);
+
+PRODUCT_NAME = $(PRODUCT_NAME_$(WK_XPC_SERVICE_VARIANT));
+PRODUCT_NAME_ = $(PRODUCT_NAME_Normal);
+PRODUCT_NAME_Normal = com.apple.WebKit.WebContent;
+PRODUCT_NAME_Development = com.apple.WebKit.WebContent.Development;
 
-PRODUCT_NAME = com.apple.WebKit.WebContent;
 PRODUCT_BUNDLE_IDENTIFIER = $(PRODUCT_NAME);
 INFOPLIST_FILE[sdk=iphone*] = WebProcess/EntryPoint/mac/XPCService/WebContentService/Info-iOS.plist;
 INFOPLIST_FILE[sdk=macosx*] = WebProcess/EntryPoint/mac/XPCService/WebContentService/Info-OSX.plist;
@@ -42,13 +46,20 @@ WK_WEBCONTENT_SERVICE_NEEDS_XPC_DOMAIN_EXTENSION_ENTITLEMENT_ = $(WK_WEBCONTENT_
 WK_WEBCONTENT_SERVICE_NEEDS_XPC_DOMAIN_EXTENSION_ENTITLEMENT_NO = $(WK_WEBCONTENT_SERVICE_NEEDS_XPC_DOMAIN_EXTENSION_ENTITLEMENT);
 WK_WEBCONTENT_SERVICE_NEEDS_XPC_DOMAIN_EXTENSION_ENTITLEMENT_YES = $(WK_RELOCATABLE_FRAMEWORKS);
 
+WK_LIBRARY_VALIDATION_ENABLED = $(WK_LIBRARY_VALIDATION_ENABLED_$(WK_EMPTY_$(WK_LIBRARY_VALIDATION_ENABLED)));
+WK_LIBRARY_VALIDATION_ENABLED_ = $(WK_LIBRARY_VALIDATION_ENABLED_NO);
+WK_LIBRARY_VALIDATION_ENABLED_NO = $(WK_LIBRARY_VALIDATION_ENABLED);
+WK_LIBRARY_VALIDATION_ENABLED_YES = YES;
+
 WK_WEBCONTENT_SERVICE_NEEDS_VERSIONED_FRAMEWORK_PATH_LDFLAG = $(WK_WEBCONTENT_SERVICE_NEEDS_VERSIONED_FRAMEWORK_PATH_LDFLAG_$(WK_EMPTY_$(WK_WEBCONTENT_SERVICE_NEEDS_VERSIONED_FRAMEWORK_PATH_LDFLAG)));
 WK_WEBCONTENT_SERVICE_NEEDS_VERSIONED_FRAMEWORK_PATH_LDFLAG_ = $(WK_WEBCONTENT_SERVICE_NEEDS_VERSIONED_FRAMEWORK_PATH_LDFLAG_NO);
 WK_WEBCONTENT_SERVICE_NEEDS_VERSIONED_FRAMEWORK_PATH_LDFLAG_NO = $(WK_WEBCONTENT_SERVICE_NEEDS_VERSIONED_FRAMEWORK_PATH_LDFLAG);
 WK_WEBCONTENT_SERVICE_NEEDS_VERSIONED_FRAMEWORK_PATH_LDFLAG_YES = $(USE_STAGING_INSTALL_PATH);
 
-WK_XPC_DOMAIN_EXTENSION_CODE_SIGN_FLAGS = $(WK_XPC_DOMAIN_EXTENSION_CODE_SIGN_FLAGS_$(WK_WEBCONTENT_SERVICE_NEEDS_XPC_DOMAIN_EXTENSION_ENTITLEMENT));
-WK_XPC_DOMAIN_EXTENSION_CODE_SIGN_FLAGS_YES = -o library;
+WK_LIBRARY_VALIDATION_CODE_SIGN_FLAGS = $(WK_LIBRARY_VALIDATION_CODE_SIGN_FLAGS_$(WK_XPC_SERVICE_VARIANT));
+WK_LIBRARY_VALIDATION_CODE_SIGN_FLAGS_ = $(WK_LIBRARY_VALIDATION_CODE_SIGN_FLAGS_Normal);
+WK_LIBRARY_VALIDATION_CODE_SIGN_FLAGS_Normal = $(WK_LIBRARY_VALIDATION_CODE_SIGN_FLAGS_$(WK_LIBRARY_VALIDATION_ENABLED));
+WK_LIBRARY_VALIDATION_CODE_SIGN_FLAGS_YES = -o library;
 
 RUNLOOP_TYPE[sdk=macosx*] = NSRunLoop;
 RUNLOOP_TYPE[sdk=macosx10.13*] = _NSApplicationMain;
index 30bebf3..de4635c 100644 (file)
@@ -60,6 +60,7 @@ public:
         ProcessType processType;
         WebCore::ProcessIdentifier processIdentifier;
         HashMap<String, String> extraInitializationData;
+        bool nonValidInjectedCodeAllowed { false };
 
 #if ENABLE(DEVELOPER_MODE) && (PLATFORM(GTK) || PLATFORM(WPE))
         String processCmdPrefix;
index f8420f6..6d34627 100644 (file)
@@ -51,7 +51,7 @@ static const char* serviceName(const ProcessLauncher::LaunchOptions& launchOptio
 {
     switch (launchOptions.processType) {
     case ProcessLauncher::ProcessType::Web:
-        return "com.apple.WebKit.WebContent";
+        return launchOptions.nonValidInjectedCodeAllowed ? "com.apple.WebKit.WebContent.Development" : "com.apple.WebKit.WebContent";
     case ProcessLauncher::ProcessType::Network:
         return "com.apple.WebKit.Networking";
     case ProcessLauncher::ProcessType::Storage:
index 4bb9ce5..0451561 100644 (file)
@@ -167,6 +167,8 @@ void WebProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOpt
         }
         launchOptions.extraInitializationData.add(ASCIILiteral("OverrideLanguages"), languageString.toString());
     }
+
+    launchOptions.nonValidInjectedCodeAllowed = shouldAllowNonValidInjectedCode();
 }
 
 void WebProcessProxy::connectionWillOpen(IPC::Connection& connection)
@@ -610,6 +612,13 @@ bool WebProcessProxy::platformIsBeingDebugged() const
 }
 #endif
 
+#if !PLATFORM(MAC)
+bool WebProcessProxy::shouldAllowNonValidInjectedCode() const
+{
+    return false;
+}
+#endif
+
 void WebProcessProxy::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
 {
     if (dispatchMessage(connection, decoder))
index f9d849e..3701f7b 100644 (file)
@@ -247,6 +247,7 @@ private:
     void getStorageProcessConnection(PAL::SessionID initialSessionID, Ref<Messages::WebProcessProxy::GetStorageProcessConnection::DelayedReply>&&);
 
     bool platformIsBeingDebugged() const;
+    bool shouldAllowNonValidInjectedCode() const;
 
     static const HashSet<String>& platformPathsWithAssumedReadAccess();
 
index 212623b..d917ad0 100644 (file)
@@ -24,6 +24,7 @@
  */
  
 #import "config.h"
+#import "WebProcessPool.h"
 #import "WebProcessProxy.h"
 
 #if PLATFORM(MAC)
@@ -37,6 +38,24 @@ bool WebProcessProxy::fullKeyboardAccessEnabled()
     return [WKFullKeyboardAccessWatcher fullKeyboardAccessEnabled];
 }
 
+bool WebProcessProxy::shouldAllowNonValidInjectedCode() const
+{
+    static bool isSystemWebKit = [] {
+#if WK_API_ENABLED
+        NSBundle *webkit2Bundle = [NSBundle bundleForClass:NSClassFromString(@"WKWebView")];
+#else
+        NSBundle *webkit2Bundle = [NSBundle bundleForClass:NSClassFromString(@"WKView")];
+#endif
+        return [webkit2Bundle.bundlePath hasPrefix:@"/System/"];
+    }();
+
+    if (!isSystemWebKit)
+        return false;
+
+    const String& path = m_processPool->configuration().injectedBundlePath();
+    return !path.isEmpty() && !path.startsWith("/System/");
+}
+
 } // namespace WebKit
 
 #endif // PLATFORM(MAC)
index de54a0c..6b9c9ce 100644 (file)
@@ -16,6 +16,7 @@
                        );
                        dependencies = (
                                BCA8D46815BCE0D6009DC1F1 /* PBXTargetDependency */,
+                               372EBB492017E6CF00085064 /* PBXTargetDependency */,
                                51A60B2E180CCF1700F3BF50 /* PBXTargetDependency */,
                                BC77F95616D0459100F8F78A /* PBXTargetDependency */,
                                BC82844616B4FF6600A278FE /* PBXTargetDependency */,
                371E695B1AED7A6700495E48 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* WebKit.framework */; };
                372CAF0B1833FD910040AC27 /* WKNSError.h in Headers */ = {isa = PBXBuildFile; fileRef = 372CAF091833FD910040AC27 /* WKNSError.h */; };
                372CAF0C1833FD910040AC27 /* WKNSError.mm in Sources */ = {isa = PBXBuildFile; fileRef = 372CAF0A1833FD910040AC27 /* WKNSError.mm */; };
+               372EBB3C2017E64300085064 /* XPCServiceMain.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC82839616B47EC400A278FE /* XPCServiceMain.mm */; };
+               372EBB3E2017E64300085064 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC3DE46815A91763008D26FC /* Foundation.framework */; };
+               372EBB3F2017E64300085064 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* WebKit.framework */; };
+               372EBB412017E64300085064 /* WebContentProcess.xib in Resources */ = {isa = PBXBuildFile; fileRef = E1D26A4C1759634E0095BFD1 /* WebContentProcess.xib */; };
                373CEAD5185417AE008C363D /* WKNSData.mm in Sources */ = {isa = PBXBuildFile; fileRef = 373CEAD3185417AE008C363D /* WKNSData.mm */; };
                373CEAD6185417AE008C363D /* WKNSData.h in Headers */ = {isa = PBXBuildFile; fileRef = 373CEAD4185417AE008C363D /* WKNSData.h */; };
                373CEAD81859553F008C363D /* WKPagePolicyClientInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 373CEAD71859553F008C363D /* WKPagePolicyClientInternal.h */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
+               372EBB3A2017E64300085064 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
+                       remoteInfo = WebKit;
+               };
+               372EBB482017E6CF00085064 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 372EBB382017E64300085064;
+                       remoteInfo = WebContent.Development;
+               };
                375E0626191EA8CC004E3CAF /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 0867D690FE84028FC02AAC07 /* Project object */;
                371A19401824D29300F32A5E /* WKNSDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKNSDictionary.h; sourceTree = "<group>"; };
                372CAF091833FD910040AC27 /* WKNSError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKNSError.h; sourceTree = "<group>"; };
                372CAF0A1833FD910040AC27 /* WKNSError.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKNSError.mm; sourceTree = "<group>"; };
+               372EBB462017E64300085064 /* com.apple.WebKit.WebContent.Development.xpc */ = {isa = PBXFileReference; explicitFileType = "wrapper.xpc-service"; includeInIndex = 0; path = com.apple.WebKit.WebContent.Development.xpc; sourceTree = BUILT_PRODUCTS_DIR; };
+               372EBB4A2017E76000085064 /* WebContentService.Development.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = WebContentService.Development.xcconfig; sourceTree = "<group>"; };
                373CEAD3185417AE008C363D /* WKNSData.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKNSData.mm; sourceTree = "<group>"; };
                373CEAD4185417AE008C363D /* WKNSData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKNSData.h; sourceTree = "<group>"; };
                373CEAD71859553F008C363D /* WKPagePolicyClientInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKPagePolicyClientInternal.h; sourceTree = "<group>"; };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               372EBB3D2017E64300085064 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               372EBB3E2017E64300085064 /* Foundation.framework in Frameworks */,
+                               372EBB3F2017E64300085064 /* WebKit.framework in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                510031EE1379CACB00C8DFE4 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                                510031F61379CACB00C8DFE4 /* SecItemShim.dylib */,
                                8DC2EF5B0486A6940098B216 /* WebKit.framework */,
                                CDC3830617211799008A2FC3 /* WebProcessShim.dylib */,
+                               372EBB462017E64300085064 /* com.apple.WebKit.WebContent.Development.xpc */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                                7C0BB9A818DCDE890006C086 /* WebContent-iOS.entitlements */,
                                37B418EB1C9624F20031E63B /* WebContent-OSX.entitlements */,
                                BCACC40E16B0B8A800B6E092 /* WebContentService.xcconfig */,
+                               372EBB4A2017E76000085064 /* WebContentService.Development.xcconfig */,
                                BCB86F4B116AAACD00CE20B7 /* WebKit.xcconfig */,
                                A1EDD2DD1884B9E300BBFE98 /* WebProcessShim.xcconfig */,
                        );
                        productReference = 1AC25FB012A48EA700BD2671 /* PluginProcessShim.dylib */;
                        productType = "com.apple.product-type.library.dynamic";
                };
+               372EBB382017E64300085064 /* WebContent.Development */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 372EBB422017E64300085064 /* Build configuration list for PBXNativeTarget "WebContent.Development" */;
+                       buildPhases = (
+                               372EBB3B2017E64300085064 /* Sources */,
+                               372EBB3D2017E64300085064 /* Frameworks */,
+                               372EBB402017E64300085064 /* Resources */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               372EBB392017E64300085064 /* PBXTargetDependency */,
+                       );
+                       name = WebContent.Development;
+                       productName = WebKit2Service;
+                       productReference = 372EBB462017E64300085064 /* com.apple.WebKit.WebContent.Development.xpc */;
+                       productType = "com.apple.product-type.xpc-service";
+               };
                510031EA1379CACB00C8DFE4 /* SecItemShim */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = 510031F21379CACB00C8DFE4 /* Build configuration list for PBXNativeTarget "SecItemShim" */;
                                510031EA1379CACB00C8DFE4 /* SecItemShim */,
                                CDC382FB17211799008A2FC3 /* WebProcessShim */,
                                BC3DE46515A91763008D26FC /* WebContent */,
+                               372EBB382017E64300085064 /* WebContent.Development */,
                                BC8283B016B4BF7700A278FE /* Networking */,
                                BC8283F816B4FDDE00A278FE /* Plugin.32 */,
                                BC82841E16B4FDF600A278FE /* Plugin.64 */,
 /* End PBXProject section */
 
 /* Begin PBXResourcesBuildPhase section */
+               372EBB402017E64300085064 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               372EBB412017E64300085064 /* WebContentProcess.xib in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                51F7DC45180CC93600212CA3 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                                "$(BUILT_PRODUCTS_DIR)/com.apple.WebKit.Plugin.32.xpc",
                                "$(BUILT_PRODUCTS_DIR)/com.apple.WebKit.Plugin.64.xpc",
                                "$(BUILT_PRODUCTS_DIR)/$(WK_STORAGE_SERVICE_PRODUCT_NAME).xpc",
+                               "$(BUILT_PRODUCTS_DIR)/com.apple.WebKit.WebContent.Development.xpc",
                        );
                        name = "Copy XPC services for engineering builds";
                        outputPaths = (
                                "$(BUILT_PRODUCTS_DIR)/WebKit.framework/XPCServices/com.apple.WebKit.Plugin.32.xpc",
                                "$(BUILT_PRODUCTS_DIR)/WebKit.framework/XPCServices/com.apple.WebKit.Plugin.64.xpc",
                                "$(BUILT_PRODUCTS_DIR)/WebKit.framework/XPCServices/$(WK_STORAGE_SERVICE_PRODUCT_NAME).xpc",
+                               "$(BUILT_PRODUCTS_DIR)/WebKit.framework/XPCServices/com.apple.WebKit.WebContent.Development.xpc",
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               372EBB3B2017E64300085064 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               372EBB3C2017E64300085064 /* XPCServiceMain.mm in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                510031EC1379CACB00C8DFE4 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
 /* End PBXSourcesBuildPhase section */
 
 /* Begin PBXTargetDependency section */
+               372EBB392017E64300085064 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 8DC2EF4F0486A6940098B216 /* WebKit */;
+                       targetProxy = 372EBB3A2017E64300085064 /* PBXContainerItemProxy */;
+               };
+               372EBB492017E6CF00085064 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 372EBB382017E64300085064 /* WebContent.Development */;
+                       targetProxy = 372EBB482017E6CF00085064 /* PBXContainerItemProxy */;
+               };
                375E0627191EA8CC004E3CAF /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = 8DC2EF4F0486A6940098B216 /* WebKit */;
                        };
                        name = Release;
                };
+               372EBB432017E64300085064 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 372EBB4A2017E76000085064 /* WebContentService.Development.xcconfig */;
+                       buildSettings = {
+                       };
+                       name = Debug;
+               };
+               372EBB442017E64300085064 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 372EBB4A2017E76000085064 /* WebContentService.Development.xcconfig */;
+                       buildSettings = {
+                       };
+                       name = Release;
+               };
+               372EBB452017E64300085064 /* Production */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = 372EBB4A2017E76000085064 /* WebContentService.Development.xcconfig */;
+                       buildSettings = {
+                       };
+                       name = Production;
+               };
                510031F31379CACB00C8DFE4 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        baseConfigurationReference = A1EDD2DC1884B9B500BBFE98 /* SecItemShim.xcconfig */;
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Production;
                };
+               372EBB422017E64300085064 /* Build configuration list for PBXNativeTarget "WebContent.Development" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               372EBB432017E64300085064 /* Debug */,
+                               372EBB442017E64300085064 /* Release */,
+                               372EBB452017E64300085064 /* Production */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Production;
+               };
                510031F21379CACB00C8DFE4 /* Build configuration list for PBXNativeTarget "SecItemShim" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (