feat(WKWebview): Add shared process pool so cookies and localStorage are shared across webviews in iOS (#138)

* fix(WKWebview): [iOS] Add shared process pool so cookies and localStorage are shared across webviews (#68)

* Add optional shared process pool

BREAKING CHANGE: useSharedProcessPool prop is set to true by default. If you want the old behavior, please use useSharedProcessPool={false}
This commit is contained in:
kylemantesso 2019-01-08 01:19:32 +11:00 committed by Thibault Malbranche
parent 335792ce4c
commit afadc62ada
8 changed files with 78 additions and 4 deletions

View File

@ -0,0 +1,15 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <WebKit/WebKit.h>
@interface RNCWKProcessPoolManager : NSObject
+ (instancetype) sharedManager;
- (WKProcessPool *)sharedProcessPool;
@end

View File

@ -0,0 +1,36 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Foundation/Foundation.h>
#import "RNCWKProcessPoolManager.h"
@interface RNCWKProcessPoolManager() {
WKProcessPool *_sharedProcessPool;
}
@end
@implementation RNCWKProcessPoolManager
+ (id) sharedManager {
static RNCWKProcessPoolManager *_sharedManager = nil;
@synchronized(self) {
if(_sharedManager == nil) {
_sharedManager = [[super alloc] init];
}
return _sharedManager;
}
}
- (WKProcessPool *)sharedProcessPool {
if (!_sharedProcessPool) {
_sharedProcessPool = [[WKProcessPool alloc] init];
}
return _sharedProcessPool;
}
@end

View File

@ -14,7 +14,7 @@
@protocol RNCWKWebViewDelegate <NSObject>
- (BOOL)webView:(RNCWKWebView *)webView
shouldStartLoadForRequest:(NSMutableDictionary<NSString *, id> *)request
shouldStartLoadForRequest:(NSMutableDictionary<NSString *, id> *)request
withCallback:(RCTDirectEventBlock)callback;
@end
@ -38,6 +38,7 @@ shouldStartLoadForRequest:(NSMutableDictionary<NSString *, id> *)request
@property (nonatomic, assign) BOOL automaticallyAdjustContentInsets;
@property (nonatomic, assign) BOOL hideKeyboardAccessoryView;
@property (nonatomic, assign) BOOL allowsBackForwardNavigationGestures;
@property (nonatomic, assign) BOOL useSharedProcessPool;
@property (nonatomic, copy) NSString *userAgent;
@property (nonatomic, assign) BOOL allowsLinkPreview;

View File

@ -8,6 +8,7 @@
#import "RNCWKWebView.h"
#import <React/RCTConvert.h>
#import <React/RCTAutoInsetsProtocol.h>
#import "RNCWKProcessPoolManager.h"
#import <UIKit/UIKit.h>
#import "objc/runtime.h"
@ -60,7 +61,6 @@ static NSString *const MessageHanderName = @"ReactNative";
return _webkitAvailable;
}
- (instancetype)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
@ -81,6 +81,9 @@ static NSString *const MessageHanderName = @"ReactNative";
};
WKWebViewConfiguration *wkWebViewConfig = [WKWebViewConfiguration new];
if(self.useSharedProcessPool) {
wkWebViewConfig.processPool = [[RNCWKProcessPoolManager sharedManager] sharedProcessPool];
}
wkWebViewConfig.userContentController = [WKUserContentController new];
[wkWebViewConfig.userContentController addScriptMessageHandler: self name: MessageHanderName];
wkWebViewConfig.allowsInlineMediaPlayback = _allowsInlineMediaPlayback;
@ -308,8 +311,8 @@ static NSString *const MessageHanderName = @"ReactNative";
/**
* alert
*/
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
completionHandler();

View File

@ -71,6 +71,10 @@ RCT_CUSTOM_VIEW_PROPERTY(bounces, BOOL, RNCWKWebView) {
view.bounces = json == nil ? true : [RCTConvert BOOL: json];
}
RCT_CUSTOM_VIEW_PROPERTY(useSharedProcessPool, BOOL, RNCWKWebView) {
view.useSharedProcessPool = json == nil ? true : [RCTConvert BOOL: json];
}
RCT_CUSTOM_VIEW_PROPERTY(scrollEnabled, BOOL, RNCWKWebView) {
view.scrollEnabled = json == nil ? true : [RCTConvert BOOL: json];
}

View File

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
3515965E21A3C86000623BFA /* RNCWKProcessPoolManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3515965D21A3C86000623BFA /* RNCWKProcessPoolManager.m */; };
E914DBF6214474710071092B /* RNCUIWebViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E914DBF3214474710071092B /* RNCUIWebViewManager.m */; };
E914DBF7214474710071092B /* RNCUIWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = E914DBF4214474710071092B /* RNCUIWebView.m */; };
E91B351D21446E6C00F9801F /* RNCWKWebViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E91B351B21446E6C00F9801F /* RNCWKWebViewManager.m */; };
@ -27,6 +28,8 @@
/* Begin PBXFileReference section */
134814201AA4EA6300B7C361 /* libRNCWebView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNCWebView.a; sourceTree = BUILT_PRODUCTS_DIR; };
3515965D21A3C86000623BFA /* RNCWKProcessPoolManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCWKProcessPoolManager.m; sourceTree = "<group>"; };
3515965F21A3C87E00623BFA /* RNCWKProcessPoolManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCWKProcessPoolManager.h; sourceTree = "<group>"; };
E914DBF2214474710071092B /* RNCUIWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCUIWebView.h; sourceTree = "<group>"; };
E914DBF3214474710071092B /* RNCUIWebViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCUIWebViewManager.m; sourceTree = "<group>"; };
E914DBF4214474710071092B /* RNCUIWebView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCUIWebView.m; sourceTree = "<group>"; };
@ -67,6 +70,8 @@
E91B351C21446E6C00F9801F /* RNCWKWebView.m */,
E91B351921446E6C00F9801F /* RNCWKWebViewManager.h */,
E91B351B21446E6C00F9801F /* RNCWKWebViewManager.m */,
3515965D21A3C86000623BFA /* RNCWKProcessPoolManager.m */,
3515965F21A3C87E00623BFA /* RNCWKProcessPoolManager.h */,
134814211AA4EA7D00B7C361 /* Products */,
);
sourceTree = "<group>";
@ -131,6 +136,7 @@
E914DBF7214474710071092B /* RNCUIWebView.m in Sources */,
E914DBF6214474710071092B /* RNCUIWebViewManager.m in Sources */,
E91B351E21446E6C00F9801F /* RNCWKWebView.m in Sources */,
3515965E21A3C86000623BFA /* RNCWKProcessPoolManager.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -134,6 +134,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
static defaultProps = {
useWebKit: true,
originWhitelist: defaultOriginWhitelist,
useSharedProcessPool: true,
};
static isFileUploadSupported = async () => {
@ -265,6 +266,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
this.props.mediaPlaybackRequiresUserAction
}
dataDetectorTypes={this.props.dataDetectorTypes}
useSharedProcessPool={this.props.useSharedProcessPool}
allowsLinkPreview={this.props.allowsLinkPreview}
{...nativeConfig.props}
/>

View File

@ -232,6 +232,13 @@ export type IOSWebViewProps = $ReadOnly<{|
* back-forward list navigations.
*/
allowsBackForwardNavigationGestures?: ?boolean,
/**
* A Boolean value indicating whether WebKit WebView should be created using a shared
* process pool, enabling WebViews to share cookies and localStorage between each other.
* Default is true but can be set to false for backwards compatibility.
* @platform ios
*/
useSharedProcessPool?: ?boolean,
/**
* The custom user agent string.
*/