Browse Source

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}
kylemantesso 6 years ago
parent
commit
afadc62ada

+ 15
- 0
ios/RNCWKProcessPoolManager.h View File

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

+ 36
- 0
ios/RNCWKProcessPoolManager.m View File

@@ -0,0 +1,36 @@
1
+/**
2
+ * Copyright (c) 2015-present, Facebook, Inc.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+#import <Foundation/Foundation.h>
9
+#import "RNCWKProcessPoolManager.h"
10
+
11
+@interface RNCWKProcessPoolManager() {
12
+    WKProcessPool *_sharedProcessPool;
13
+}
14
+@end
15
+
16
+@implementation RNCWKProcessPoolManager
17
+
18
++ (id) sharedManager {
19
+    static RNCWKProcessPoolManager *_sharedManager = nil;
20
+    @synchronized(self) {
21
+        if(_sharedManager == nil) {
22
+            _sharedManager = [[super alloc] init];
23
+        }
24
+        return _sharedManager;
25
+    }
26
+}
27
+
28
+- (WKProcessPool *)sharedProcessPool {
29
+    if (!_sharedProcessPool) {
30
+        _sharedProcessPool = [[WKProcessPool alloc] init];
31
+    }
32
+    return _sharedProcessPool;
33
+}
34
+
35
+@end
36
+

+ 2
- 1
ios/RNCWKWebView.h View File

@@ -14,7 +14,7 @@
14 14
 @protocol RNCWKWebViewDelegate <NSObject>
15 15
 
16 16
 - (BOOL)webView:(RNCWKWebView *)webView
17
-shouldStartLoadForRequest:(NSMutableDictionary<NSString *, id> *)request
17
+   shouldStartLoadForRequest:(NSMutableDictionary<NSString *, id> *)request
18 18
    withCallback:(RCTDirectEventBlock)callback;
19 19
 
20 20
 @end
@@ -38,6 +38,7 @@ shouldStartLoadForRequest:(NSMutableDictionary<NSString *, id> *)request
38 38
 @property (nonatomic, assign) BOOL automaticallyAdjustContentInsets;
39 39
 @property (nonatomic, assign) BOOL hideKeyboardAccessoryView;
40 40
 @property (nonatomic, assign) BOOL allowsBackForwardNavigationGestures;
41
+@property (nonatomic, assign) BOOL useSharedProcessPool;
41 42
 @property (nonatomic, copy) NSString *userAgent;
42 43
 @property (nonatomic, assign) BOOL allowsLinkPreview;
43 44
 

+ 6
- 3
ios/RNCWKWebView.m View File

@@ -8,6 +8,7 @@
8 8
 #import "RNCWKWebView.h"
9 9
 #import <React/RCTConvert.h>
10 10
 #import <React/RCTAutoInsetsProtocol.h>
11
+#import "RNCWKProcessPoolManager.h"
11 12
 #import <UIKit/UIKit.h>
12 13
 
13 14
 #import "objc/runtime.h"
@@ -60,7 +61,6 @@ static NSString *const MessageHanderName = @"ReactNative";
60 61
   return _webkitAvailable;
61 62
 }
62 63
 
63
-
64 64
 - (instancetype)initWithFrame:(CGRect)frame
65 65
 {
66 66
   if ((self = [super initWithFrame:frame])) {
@@ -81,6 +81,9 @@ static NSString *const MessageHanderName = @"ReactNative";
81 81
     };
82 82
 
83 83
     WKWebViewConfiguration *wkWebViewConfig = [WKWebViewConfiguration new];
84
+    if(self.useSharedProcessPool) {
85
+        wkWebViewConfig.processPool = [[RNCWKProcessPoolManager sharedManager] sharedProcessPool];
86
+    }
84 87
     wkWebViewConfig.userContentController = [WKUserContentController new];
85 88
     [wkWebViewConfig.userContentController addScriptMessageHandler: self name: MessageHanderName];
86 89
     wkWebViewConfig.allowsInlineMediaPlayback = _allowsInlineMediaPlayback;
@@ -308,8 +311,8 @@ static NSString *const MessageHanderName = @"ReactNative";
308 311
 /**
309 312
 * alert
310 313
 */
311
-- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler 
312
-{ 
314
+- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
315
+{
313 316
     UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
314 317
     [alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
315 318
         completionHandler();

+ 4
- 0
ios/RNCWKWebViewManager.m View File

@@ -71,6 +71,10 @@ RCT_CUSTOM_VIEW_PROPERTY(bounces, BOOL, RNCWKWebView) {
71 71
   view.bounces = json == nil ? true : [RCTConvert BOOL: json];
72 72
 }
73 73
 
74
+RCT_CUSTOM_VIEW_PROPERTY(useSharedProcessPool, BOOL, RNCWKWebView) {
75
+  view.useSharedProcessPool = json == nil ? true : [RCTConvert BOOL: json];
76
+}
77
+
74 78
 RCT_CUSTOM_VIEW_PROPERTY(scrollEnabled, BOOL, RNCWKWebView) {
75 79
   view.scrollEnabled = json == nil ? true : [RCTConvert BOOL: json];
76 80
 }

+ 6
- 0
ios/RNCWebView.xcodeproj/project.pbxproj View File

@@ -7,6 +7,7 @@
7 7
 	objects = {
8 8
 
9 9
 /* Begin PBXBuildFile section */
10
+		3515965E21A3C86000623BFA /* RNCWKProcessPoolManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3515965D21A3C86000623BFA /* RNCWKProcessPoolManager.m */; };
10 11
 		E914DBF6214474710071092B /* RNCUIWebViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E914DBF3214474710071092B /* RNCUIWebViewManager.m */; };
11 12
 		E914DBF7214474710071092B /* RNCUIWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = E914DBF4214474710071092B /* RNCUIWebView.m */; };
12 13
 		E91B351D21446E6C00F9801F /* RNCWKWebViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E91B351B21446E6C00F9801F /* RNCWKWebViewManager.m */; };
@@ -27,6 +28,8 @@
27 28
 
28 29
 /* Begin PBXFileReference section */
29 30
 		134814201AA4EA6300B7C361 /* libRNCWebView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNCWebView.a; sourceTree = BUILT_PRODUCTS_DIR; };
31
+		3515965D21A3C86000623BFA /* RNCWKProcessPoolManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCWKProcessPoolManager.m; sourceTree = "<group>"; };
32
+		3515965F21A3C87E00623BFA /* RNCWKProcessPoolManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCWKProcessPoolManager.h; sourceTree = "<group>"; };
30 33
 		E914DBF2214474710071092B /* RNCUIWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCUIWebView.h; sourceTree = "<group>"; };
31 34
 		E914DBF3214474710071092B /* RNCUIWebViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCUIWebViewManager.m; sourceTree = "<group>"; };
32 35
 		E914DBF4214474710071092B /* RNCUIWebView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCUIWebView.m; sourceTree = "<group>"; };
@@ -67,6 +70,8 @@
67 70
 				E91B351C21446E6C00F9801F /* RNCWKWebView.m */,
68 71
 				E91B351921446E6C00F9801F /* RNCWKWebViewManager.h */,
69 72
 				E91B351B21446E6C00F9801F /* RNCWKWebViewManager.m */,
73
+				3515965D21A3C86000623BFA /* RNCWKProcessPoolManager.m */,
74
+				3515965F21A3C87E00623BFA /* RNCWKProcessPoolManager.h */,
70 75
 				134814211AA4EA7D00B7C361 /* Products */,
71 76
 			);
72 77
 			sourceTree = "<group>";
@@ -131,6 +136,7 @@
131 136
 				E914DBF7214474710071092B /* RNCUIWebView.m in Sources */,
132 137
 				E914DBF6214474710071092B /* RNCUIWebViewManager.m in Sources */,
133 138
 				E91B351E21446E6C00F9801F /* RNCWKWebView.m in Sources */,
139
+				3515965E21A3C86000623BFA /* RNCWKProcessPoolManager.m in Sources */,
134 140
 			);
135 141
 			runOnlyForDeploymentPostprocessing = 0;
136 142
 		};

+ 2
- 0
js/WebView.ios.js View File

@@ -134,6 +134,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
134 134
   static defaultProps = {
135 135
     useWebKit: true,
136 136
     originWhitelist: defaultOriginWhitelist,
137
+    useSharedProcessPool: true,
137 138
   };
138 139
 
139 140
   static isFileUploadSupported = async () => {
@@ -265,6 +266,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
265 266
           this.props.mediaPlaybackRequiresUserAction
266 267
         }
267 268
         dataDetectorTypes={this.props.dataDetectorTypes}
269
+        useSharedProcessPool={this.props.useSharedProcessPool}
268 270
         allowsLinkPreview={this.props.allowsLinkPreview}
269 271
         {...nativeConfig.props}
270 272
       />

+ 7
- 0
js/WebViewTypes.js View File

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