From 6ca438a7f4bd7e6b317f0461aebbd5a7186151ed Mon Sep 17 00:00:00 2001 From: Christoph Nakazawa Date: Thu, 4 Apr 2019 15:39:17 -0700 Subject: [PATCH] Move iOS WebView files to FB internal Summary: This moves the iOS WebView files to be fb internal which completes the removal of WebView from React Native open source as part of the Lean Core effort. Reviewed By: TheSavior Differential Revision: D14630076 fbshipit-source-id: 7bc11d6c1470bb748c823c86cbb8b5ee94b508ff --- React/React-Core.podspec | 2 - React/React.xcodeproj/project.pbxproj | 40 --- React/Views/RCTWKWebView.h | 47 --- React/Views/RCTWKWebView.m | 435 -------------------------- React/Views/RCTWKWebViewManager.h | 11 - React/Views/RCTWKWebViewManager.m | 170 ---------- React/Views/RCTWebView.h | 46 --- React/Views/RCTWebView.m | 351 --------------------- React/Views/RCTWebViewManager.h | 12 - React/Views/RCTWebViewManager.m | 158 ---------- 10 files changed, 1272 deletions(-) delete mode 100644 React/Views/RCTWKWebView.h delete mode 100644 React/Views/RCTWKWebView.m delete mode 100644 React/Views/RCTWKWebViewManager.h delete mode 100644 React/Views/RCTWKWebViewManager.m delete mode 100644 React/Views/RCTWebView.h delete mode 100644 React/Views/RCTWebView.m delete mode 100644 React/Views/RCTWebViewManager.h delete mode 100644 React/Views/RCTWebViewManager.m diff --git a/React/React-Core.podspec b/React/React-Core.podspec index 0643e53af48e22..07b250db4c6b72 100644 --- a/React/React-Core.podspec +++ b/React/React-Core.podspec @@ -41,8 +41,6 @@ Pod::Spec.new do |s| "Views/RCTRefreshControl*", "Views/RCTSlider*", "Views/RCTSwitch*", - "Views/RCTWebView*", - "Views/RCTWKWebView*" s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags s.header_dir = "React" s.framework = "JavaScriptCore" diff --git a/React/React.xcodeproj/project.pbxproj b/React/React.xcodeproj/project.pbxproj index 6c71576abda507..18f194eaf790aa 100644 --- a/React/React.xcodeproj/project.pbxproj +++ b/React/React.xcodeproj/project.pbxproj @@ -106,8 +106,6 @@ 13B080261A694A8400A75B9A /* RCTWrapperViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B080241A694A8400A75B9A /* RCTWrapperViewController.m */; }; 13BB3D021BECD54500932C10 /* RCTImageSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BB3D011BECD54500932C10 /* RCTImageSource.m */; }; 13BCE8091C99CB9D00DD7AAD /* RCTRootShadowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BCE8081C99CB9D00DD7AAD /* RCTRootShadowView.m */; }; - 13C156051AB1A2840079392D /* RCTWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13C156021AB1A2840079392D /* RCTWebView.m */; }; - 13C156061AB1A2840079392D /* RCTWebViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13C156041AB1A2840079392D /* RCTWebViewManager.m */; }; 13CC8A821B17642100940AE7 /* RCTBorderDrawing.m in Sources */ = {isa = PBXBuildFile; fileRef = 13CC8A811B17642100940AE7 /* RCTBorderDrawing.m */; }; 13D033631C1837FE0021DC29 /* RCTClipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = 13D033621C1837FE0021DC29 /* RCTClipboard.m */; }; 13D9FEEB1CDCCECF00158BD7 /* RCTEventEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = 13D9FEEA1CDCCECF00158BD7 /* RCTEventEmitter.m */; }; @@ -546,8 +544,6 @@ 3D80D9921DF6FA890028D040 /* RCTTextDecorationLineType.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = E3BBC8EB1ADE6F47001BBD81 /* RCTTextDecorationLineType.h */; }; 3D80D9931DF6FA890028D040 /* RCTView.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13E0674F1A70F44B002CDEE1 /* RCTView.h */; }; 3D80D9951DF6FA890028D040 /* RCTViewManager.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13E0674D1A70F44B002CDEE1 /* RCTViewManager.h */; }; - 3D80D9961DF6FA890028D040 /* RCTWebView.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13C156011AB1A2840079392D /* RCTWebView.h */; }; - 3D80D9971DF6FA890028D040 /* RCTWebViewManager.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13C156031AB1A2840079392D /* RCTWebViewManager.h */; }; 3D80D9981DF6FA890028D040 /* RCTWrapperViewController.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13B080231A694A8400A75B9A /* RCTWrapperViewController.h */; }; 3D80D99A1DF6FA890028D040 /* UIView+React.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13E067531A70F44B002CDEE1 /* UIView+React.h */; }; 3D80DA191DF820620028D040 /* RCTImageLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D1FA0831DE4F3A000E03CC6 /* RCTImageLoader.h */; }; @@ -644,8 +640,6 @@ 3D80DA8C1DF820620028D040 /* RCTTextDecorationLineType.h in Headers */ = {isa = PBXBuildFile; fileRef = E3BBC8EB1ADE6F47001BBD81 /* RCTTextDecorationLineType.h */; }; 3D80DA8D1DF820620028D040 /* RCTView.h in Headers */ = {isa = PBXBuildFile; fileRef = 13E0674F1A70F44B002CDEE1 /* RCTView.h */; }; 3D80DA8F1DF820620028D040 /* RCTViewManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 13E0674D1A70F44B002CDEE1 /* RCTViewManager.h */; }; - 3D80DA901DF820620028D040 /* RCTWebView.h in Headers */ = {isa = PBXBuildFile; fileRef = 13C156011AB1A2840079392D /* RCTWebView.h */; }; - 3D80DA911DF820620028D040 /* RCTWebViewManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 13C156031AB1A2840079392D /* RCTWebViewManager.h */; }; 3D80DA921DF820620028D040 /* RCTWrapperViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 13B080231A694A8400A75B9A /* RCTWrapperViewController.h */; }; 3D80DA931DF820620028D040 /* UIView+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 83F15A171B7CC46900F10295 /* UIView+Private.h */; }; 3D80DA941DF820620028D040 /* UIView+React.h in Headers */ = {isa = PBXBuildFile; fileRef = 13E067531A70F44B002CDEE1 /* UIView+React.h */; }; @@ -757,8 +751,6 @@ 3DA982301E5B0F7F004F2374 /* RCTTVView.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 130443D61E401AD800D93A67 /* RCTTVView.h */; }; 3DA982311E5B0F7F004F2374 /* RCTView.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13E0674F1A70F44B002CDEE1 /* RCTView.h */; }; 3DA982331E5B0F7F004F2374 /* RCTViewManager.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13E0674D1A70F44B002CDEE1 /* RCTViewManager.h */; }; - 3DA982341E5B0F7F004F2374 /* RCTWebView.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13C156011AB1A2840079392D /* RCTWebView.h */; }; - 3DA982351E5B0F7F004F2374 /* RCTWebViewManager.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13C156031AB1A2840079392D /* RCTWebViewManager.h */; }; 3DA982361E5B0F7F004F2374 /* RCTWrapperViewController.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13B080231A694A8400A75B9A /* RCTWrapperViewController.h */; }; 3DA982381E5B0F7F004F2374 /* UIView+React.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 13E067531A70F44B002CDEE1 /* UIView+React.h */; }; 3DA982391E5B0F8A004F2374 /* UIView+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 83F15A171B7CC46900F10295 /* UIView+Private.h */; }; @@ -804,10 +796,6 @@ 4F56C93822167A4800DB9F3F /* jsilib.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F56C93722167A4800DB9F3F /* jsilib.h */; }; 4F56C93922167A4D00DB9F3F /* jsilib.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4F56C93722167A4800DB9F3F /* jsilib.h */; }; 4F56C93A2216A3B700DB9F3F /* jsilib.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4F56C93722167A4800DB9F3F /* jsilib.h */; }; - 50E98FEA21460B0D00CD9289 /* RCTWKWebViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 50E98FE621460B0D00CD9289 /* RCTWKWebViewManager.m */; }; - 50E98FEB21460B0D00CD9289 /* RCTWKWebView.h in Headers */ = {isa = PBXBuildFile; fileRef = 50E98FE721460B0D00CD9289 /* RCTWKWebView.h */; }; - 50E98FEC21460B0D00CD9289 /* RCTWKWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = 50E98FE821460B0D00CD9289 /* RCTWKWebView.m */; }; - 50E98FED21460B0D00CD9289 /* RCTWKWebViewManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 50E98FE921460B0D00CD9289 /* RCTWKWebViewManager.h */; }; 5335D5411FE81A4700883D58 /* RCTShadowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5335D5401FE81A4700883D58 /* RCTShadowView.m */; }; 53438962203905BB008E0CB3 /* YGLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5343895E203905B6008E0CB3 /* YGLayout.cpp */; }; 53438963203905BC008E0CB3 /* YGLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5343895E203905B6008E0CB3 /* YGLayout.cpp */; }; @@ -1436,8 +1424,6 @@ 3DA982301E5B0F7F004F2374 /* RCTTVView.h in Copy Headers */, 3DA982311E5B0F7F004F2374 /* RCTView.h in Copy Headers */, 3DA982331E5B0F7F004F2374 /* RCTViewManager.h in Copy Headers */, - 3DA982341E5B0F7F004F2374 /* RCTWebView.h in Copy Headers */, - 3DA982351E5B0F7F004F2374 /* RCTWebViewManager.h in Copy Headers */, 3DA982361E5B0F7F004F2374 /* RCTWrapperViewController.h in Copy Headers */, 3DA982381E5B0F7F004F2374 /* UIView+React.h in Copy Headers */, 3DA981BF1E5B0F29004F2374 /* RCTAssert.h in Copy Headers */, @@ -1669,8 +1655,6 @@ 3D80D9921DF6FA890028D040 /* RCTTextDecorationLineType.h in Copy Headers */, 3D80D9931DF6FA890028D040 /* RCTView.h in Copy Headers */, 3D80D9951DF6FA890028D040 /* RCTViewManager.h in Copy Headers */, - 3D80D9961DF6FA890028D040 /* RCTWebView.h in Copy Headers */, - 3D80D9971DF6FA890028D040 /* RCTWebViewManager.h in Copy Headers */, 3D80D9981DF6FA890028D040 /* RCTWrapperViewController.h in Copy Headers */, 3D80D99A1DF6FA890028D040 /* UIView+React.h in Copy Headers */, ); @@ -1936,10 +1920,6 @@ 13BB3D011BECD54500932C10 /* RCTImageSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageSource.m; sourceTree = ""; }; 13BCE8071C99CB9D00DD7AAD /* RCTRootShadowView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRootShadowView.h; sourceTree = ""; }; 13BCE8081C99CB9D00DD7AAD /* RCTRootShadowView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRootShadowView.m; sourceTree = ""; }; - 13C156011AB1A2840079392D /* RCTWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTWebView.h; sourceTree = ""; }; - 13C156021AB1A2840079392D /* RCTWebView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTWebView.m; sourceTree = ""; }; - 13C156031AB1A2840079392D /* RCTWebViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTWebViewManager.h; sourceTree = ""; }; - 13C156041AB1A2840079392D /* RCTWebViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTWebViewManager.m; sourceTree = ""; }; 13C325261AA63B6A0048765F /* RCTAutoInsetsProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAutoInsetsProtocol.h; sourceTree = ""; }; 13C325281AA63B6A0048765F /* RCTComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTComponent.h; sourceTree = ""; }; 13CC8A801B17642100940AE7 /* RCTBorderDrawing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTBorderDrawing.h; sourceTree = ""; }; @@ -2067,10 +2047,6 @@ 3EDCA8A31D3591E700450C31 /* RCTErrorInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTErrorInfo.h; sourceTree = ""; }; 3EDCA8A41D3591E700450C31 /* RCTErrorInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTErrorInfo.m; sourceTree = ""; }; 4F56C93722167A4800DB9F3F /* jsilib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jsilib.h; sourceTree = ""; }; - 50E98FE621460B0D00CD9289 /* RCTWKWebViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTWKWebViewManager.m; sourceTree = ""; }; - 50E98FE721460B0D00CD9289 /* RCTWKWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTWKWebView.h; sourceTree = ""; }; - 50E98FE821460B0D00CD9289 /* RCTWKWebView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTWKWebView.m; sourceTree = ""; }; - 50E98FE921460B0D00CD9289 /* RCTWKWebViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTWKWebViewManager.h; sourceTree = ""; }; 5335D5401FE81A4700883D58 /* RCTShadowView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTShadowView.m; sourceTree = ""; }; 5343895E203905B6008E0CB3 /* YGLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YGLayout.cpp; sourceTree = ""; }; 5343895F203905B6008E0CB3 /* YGLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YGLayout.h; sourceTree = ""; }; @@ -2552,10 +2528,6 @@ 13B07FF31A6947C200A75B9A /* Views */ = { isa = PBXGroup; children = ( - 50E98FE721460B0D00CD9289 /* RCTWKWebView.h */, - 50E98FE821460B0D00CD9289 /* RCTWKWebView.m */, - 50E98FE921460B0D00CD9289 /* RCTWKWebViewManager.h */, - 50E98FE621460B0D00CD9289 /* RCTWKWebViewManager.m */, B95154301D1B34B200FE7B80 /* RCTActivityIndicatorView.h */, B95154311D1B34B200FE7B80 /* RCTActivityIndicatorView.m */, 13B080181A69489C00A75B9A /* RCTActivityIndicatorViewManager.h */, @@ -2630,10 +2602,6 @@ 13E067501A70F44B002CDEE1 /* RCTView.m */, 13E0674D1A70F44B002CDEE1 /* RCTViewManager.h */, 13E0674E1A70F44B002CDEE1 /* RCTViewManager.m */, - 13C156011AB1A2840079392D /* RCTWebView.h */, - 13C156021AB1A2840079392D /* RCTWebView.m */, - 13C156031AB1A2840079392D /* RCTWebViewManager.h */, - 13C156041AB1A2840079392D /* RCTWebViewManager.m */, 13B080231A694A8400A75B9A /* RCTWrapperViewController.h */, 13B080241A694A8400A75B9A /* RCTWrapperViewController.m */, 59D031E41F8353D3008361F0 /* SafeAreaView */, @@ -3421,7 +3389,6 @@ 3D80DA2A1DF820620028D040 /* RCTErrorCustomizer.h in Headers */, 3D80DA2B1DF820620028D040 /* RCTErrorInfo.h in Headers */, 1384E2081E806D4E00545659 /* RCTNativeModule.h in Headers */, - 50E98FED21460B0D00CD9289 /* RCTWKWebViewManager.h in Headers */, 3D7BFD2D1EA8E3FA008DFB7A /* RCTReconnectingWebSocket.h in Headers */, 3D80DA2C1DF820620028D040 /* RCTEventDispatcher.h in Headers */, 3D80DA2D1DF820620028D040 /* RCTFrameUpdate.h in Headers */, @@ -3431,7 +3398,6 @@ 599FAA3A1FB274980058CCF6 /* RCTSurfaceDelegate.h in Headers */, 3D80DA301DF820620028D040 /* RCTJavaScriptExecutor.h in Headers */, 3DCE53281FEAB23100613583 /* RCTDatePicker.h in Headers */, - 50E98FEB21460B0D00CD9289 /* RCTWKWebView.h in Headers */, 3D80DA311DF820620028D040 /* RCTJavaScriptLoader.h in Headers */, 130E3D881E6A082100ACE484 /* RCTDevSettings.h in Headers */, 3D80DA321DF820620028D040 /* RCTJSStackFrame.h in Headers */, @@ -3551,8 +3517,6 @@ 3D80DA8F1DF820620028D040 /* RCTViewManager.h in Headers */, 13134CA01E296B2A00B9F3CB /* RCTCxxUtils.h in Headers */, 599FAA4A1FB274980058CCF6 /* RCTSurfaceView.h in Headers */, - 3D80DA901DF820620028D040 /* RCTWebView.h in Headers */, - 3D80DA911DF820620028D040 /* RCTWebViewManager.h in Headers */, 3D80DA921DF820620028D040 /* RCTWrapperViewController.h in Headers */, 3D80DA931DF820620028D040 /* UIView+Private.h in Headers */, 3D80DA941DF820620028D040 /* UIView+React.h in Headers */, @@ -4471,7 +4435,6 @@ C60128AD1F3D1258009DF9FF /* RCTCxxConvert.m in Sources */, 3DCE53291FEAB23100613583 /* RCTDatePicker.m in Sources */, 0EEEA8DF2239002200A8C82D /* RCTSurfacePresenterStub.m in Sources */, - 50E98FEA21460B0D00CD9289 /* RCTWKWebViewManager.m in Sources */, 83CBBA511A601E3B00E9B192 /* RCTAssert.m in Sources */, 59EB6DBD1EBD6FC90072A5E7 /* RCTUIManagerObserverCoordinator.mm in Sources */, 59E604A21FE9CCE300BD90C5 /* RCTScrollContentViewManager.m in Sources */, @@ -4546,13 +4509,10 @@ 130443C61E401A8C00D93A67 /* RCTConvert+Transform.m in Sources */, 191E3EC11C29DC3800C180A6 /* RCTRefreshControl.m in Sources */, 3DCE532B1FEAB23100613583 /* RCTDatePickerManager.m in Sources */, - 13C156051AB1A2840079392D /* RCTWebView.m in Sources */, 83CBBA601A601EAA00E9B192 /* RCTBridge.m in Sources */, - 50E98FEC21460B0D00CD9289 /* RCTWKWebView.m in Sources */, 590D7BFF1EBD458B00D8A370 /* RCTShadowView+Layout.m in Sources */, 5335D5411FE81A4700883D58 /* RCTShadowView.m in Sources */, 66CD94B31F1045E700CB3C7C /* RCTMaskedView.m in Sources */, - 13C156061AB1A2840079392D /* RCTWebViewManager.m in Sources */, 58114A161AAE854800E7D092 /* RCTPicker.m in Sources */, 83A1FE8C1B62640A00BE0E65 /* RCTModalHostView.m in Sources */, 5925356A20084D0600DD584B /* RCTSurfaceSizeMeasureMode.mm in Sources */, diff --git a/React/Views/RCTWKWebView.h b/React/Views/RCTWKWebView.h deleted file mode 100644 index 04b6e4e4cc50c1..00000000000000 --- a/React/Views/RCTWKWebView.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import -#import -#import - -@class RCTWKWebView; - -@protocol RCTWKWebViewDelegate - -- (BOOL)webView:(RCTWKWebView *)webView -shouldStartLoadForRequest:(NSMutableDictionary *)request - withCallback:(RCTDirectEventBlock)callback; - -@end - -@interface RCTWKWebView : RCTView - -@property (nonatomic, weak) id delegate; -@property (nonatomic, copy) NSDictionary *source; -@property (nonatomic, assign) BOOL messagingEnabled; -@property (nonatomic, copy) NSString *injectedJavaScript; -@property (nonatomic, assign) BOOL scrollEnabled; -@property (nonatomic, assign) CGFloat decelerationRate; -@property (nonatomic, assign) BOOL allowsInlineMediaPlayback; -@property (nonatomic, assign) BOOL bounces; -@property (nonatomic, assign) BOOL mediaPlaybackRequiresUserAction; -#if WEBKIT_IOS_10_APIS_AVAILABLE -@property (nonatomic, assign) WKDataDetectorTypes dataDetectorTypes; -#endif -@property (nonatomic, assign) UIEdgeInsets contentInset; -@property (nonatomic, assign) BOOL automaticallyAdjustContentInsets; - -+ (void)setClientAuthenticationCredential:(nullable NSURLCredential*)credential; -- (void)postMessage:(NSString *)message; -- (void)injectJavaScript:(NSString *)script; -- (void)goForward; -- (void)goBack; -- (void)reload; -- (void)stopLoading; - -@end diff --git a/React/Views/RCTWKWebView.m b/React/Views/RCTWKWebView.m deleted file mode 100644 index 2171d42fb14d5b..00000000000000 --- a/React/Views/RCTWKWebView.m +++ /dev/null @@ -1,435 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "RCTWKWebView.h" -#import -#import "RCTAutoInsetsProtocol.h" - -static NSString *const MessageHanderName = @"ReactNative"; -static NSURLCredential* clientAuthenticationCredential; - - -@interface RCTWKWebView () -@property (nonatomic, copy) RCTDirectEventBlock onLoadingStart; -@property (nonatomic, copy) RCTDirectEventBlock onLoadingFinish; -@property (nonatomic, copy) RCTDirectEventBlock onLoadingError; -@property (nonatomic, copy) RCTDirectEventBlock onShouldStartLoadWithRequest; -@property (nonatomic, copy) RCTDirectEventBlock onMessage; -@property (nonatomic, copy) WKWebView *webView; -@end - -@implementation RCTWKWebView -{ - UIColor * _savedBackgroundColor; -} - -- (void)dealloc -{ - -} - -/** - * See https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/DisplayWebContent/Tasks/WebKitAvail.html. - */ -+ (BOOL)dynamicallyLoadWebKitIfAvailable -{ - static BOOL _webkitAvailable=NO; - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - NSBundle *webKitBundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/WebKit.framework"]; - if (webKitBundle) { - _webkitAvailable = [webKitBundle load]; - } - }); - - return _webkitAvailable; -} - - -- (instancetype)initWithFrame:(CGRect)frame -{ - if ((self = [super initWithFrame:frame])) { - super.backgroundColor = [UIColor clearColor]; - _bounces = YES; - _scrollEnabled = YES; - _automaticallyAdjustContentInsets = YES; - _contentInset = UIEdgeInsetsZero; - } - return self; -} - -- (void)didMoveToWindow -{ - if (self.window != nil) { - if (![[self class] dynamicallyLoadWebKitIfAvailable]) { - return; - }; - - WKWebViewConfiguration *wkWebViewConfig = [WKWebViewConfiguration new]; - wkWebViewConfig.userContentController = [WKUserContentController new]; - [wkWebViewConfig.userContentController addScriptMessageHandler: self name: MessageHanderName]; - wkWebViewConfig.allowsInlineMediaPlayback = _allowsInlineMediaPlayback; -#if WEBKIT_IOS_10_APIS_AVAILABLE - wkWebViewConfig.mediaTypesRequiringUserActionForPlayback = _mediaPlaybackRequiresUserAction - ? WKAudiovisualMediaTypeAll - : WKAudiovisualMediaTypeNone; - wkWebViewConfig.dataDetectorTypes = _dataDetectorTypes; -#else - wkWebViewConfig.mediaPlaybackRequiresUserAction = _mediaPlaybackRequiresUserAction; -#endif - - _webView = [[WKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig]; - _webView.scrollView.delegate = self; - _webView.UIDelegate = self; - _webView.navigationDelegate = self; - _webView.scrollView.scrollEnabled = _scrollEnabled; - _webView.scrollView.bounces = _bounces; - -#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */ - if ([_webView.scrollView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) { - _webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; - } -#endif - - [self addSubview:_webView]; - - [self visitSource]; - } -} - -- (void)setBackgroundColor:(UIColor *)backgroundColor -{ - _savedBackgroundColor = backgroundColor; - if (_webView == nil) { - return; - } - - CGFloat alpha = CGColorGetAlpha(backgroundColor.CGColor); - self.opaque = _webView.opaque = (alpha == 1.0); - _webView.scrollView.backgroundColor = backgroundColor; - _webView.backgroundColor = backgroundColor; -} - -/** - * This method is called whenever JavaScript running within the web view calls: - * - window.webkit.messageHandlers.[MessageHanderName].postMessage - */ -- (void)userContentController:(__unused WKUserContentController *)userContentController - didReceiveScriptMessage:(WKScriptMessage *)message -{ - if (_onMessage != nil) { - NSMutableDictionary *event = [self baseEvent]; - [event addEntriesFromDictionary: @{@"data": message.body}]; - _onMessage(event); - } -} - -- (void)setSource:(NSDictionary *)source -{ - if (![_source isEqualToDictionary:source]) { - _source = [source copy]; - - if (_webView != nil) { - [self visitSource]; - } - } -} - -- (void)setContentInset:(UIEdgeInsets)contentInset -{ - _contentInset = contentInset; - [RCTView autoAdjustInsetsForView:self - withScrollView:_webView.scrollView - updateOffset:NO]; -} - -- (void)refreshContentInset -{ - [RCTView autoAdjustInsetsForView:self - withScrollView:_webView.scrollView - updateOffset:YES]; -} - -- (void)visitSource -{ - // Check for a static html source first - NSString *html = [RCTConvert NSString:_source[@"html"]]; - if (html) { - NSURL *baseURL = [RCTConvert NSURL:_source[@"baseUrl"]]; - if (!baseURL) { - baseURL = [NSURL URLWithString:@"about:blank"]; - } - [_webView loadHTMLString:html baseURL:baseURL]; - return; - } - - NSURLRequest *request = [RCTConvert NSURLRequest:_source]; - // Because of the way React works, as pages redirect, we actually end up - // passing the redirect urls back here, so we ignore them if trying to load - // the same url. We'll expose a call to 'reload' to allow a user to load - // the existing page. - if ([request.URL isEqual:_webView.URL]) { - return; - } - if (!request.URL) { - // Clear the webview - [_webView loadHTMLString:@"" baseURL:nil]; - return; - } - [_webView loadRequest:request]; -} - - -- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView -{ - scrollView.decelerationRate = _decelerationRate; -} - -- (void)setScrollEnabled:(BOOL)scrollEnabled -{ - _scrollEnabled = scrollEnabled; - _webView.scrollView.scrollEnabled = scrollEnabled; -} - -- (void)postMessage:(NSString *)message -{ - NSDictionary *eventInitDict = @{@"data": message}; - NSString *source = [NSString - stringWithFormat:@"document.dispatchEvent(new MessageEvent('message', %@));", - RCTJSONStringify(eventInitDict, NULL) - ]; - [self evaluateJS: source thenCall: nil]; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - // Ensure webview takes the position and dimensions of RCTWKWebView - _webView.frame = self.bounds; -} - -- (NSMutableDictionary *)baseEvent -{ - NSDictionary *event = @{ - @"url": _webView.URL.absoluteString ?: @"", - @"title": _webView.title, - @"loading" : @(_webView.loading), - @"canGoBack": @(_webView.canGoBack), - @"canGoForward" : @(_webView.canGoForward) - }; - return [[NSMutableDictionary alloc] initWithDictionary: event]; -} - -#pragma mark - WKNavigationDelegate methods - -/** - * Decides whether to allow or cancel a navigation. - * @see https://fburl.com/42r9fxob - */ -- (void) webView:(__unused WKWebView *)webView - decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction - decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler -{ - static NSDictionary *navigationTypes; - static dispatch_once_t onceToken; - - dispatch_once(&onceToken, ^{ - navigationTypes = @{ - @(WKNavigationTypeLinkActivated): @"click", - @(WKNavigationTypeFormSubmitted): @"formsubmit", - @(WKNavigationTypeBackForward): @"backforward", - @(WKNavigationTypeReload): @"reload", - @(WKNavigationTypeFormResubmitted): @"formresubmit", - @(WKNavigationTypeOther): @"other", - }; - }); - - WKNavigationType navigationType = navigationAction.navigationType; - NSURLRequest *request = navigationAction.request; - - if (_onShouldStartLoadWithRequest) { - NSMutableDictionary *event = [self baseEvent]; - [event addEntriesFromDictionary: @{ - @"url": (request.URL).absoluteString, - @"navigationType": navigationTypes[@(navigationType)] - }]; - if (![self.delegate webView:self - shouldStartLoadForRequest:event - withCallback:_onShouldStartLoadWithRequest]) { - decisionHandler(WKNavigationActionPolicyCancel); - return; - } - } - - if (_onLoadingStart) { - // We have this check to filter out iframe requests and whatnot - BOOL isTopFrame = [request.URL isEqual:request.mainDocumentURL]; - if (isTopFrame) { - NSMutableDictionary *event = [self baseEvent]; - [event addEntriesFromDictionary: @{ - @"url": (request.URL).absoluteString, - @"navigationType": navigationTypes[@(navigationType)] - }]; - _onLoadingStart(event); - } - } - - // Allow all navigation by default - decisionHandler(WKNavigationActionPolicyAllow); -} - -/** - * Called when an error occurs while the web view is loading content. - * @see https://fburl.com/km6vqenw - */ -- (void) webView:(__unused WKWebView *)webView - didFailProvisionalNavigation:(__unused WKNavigation *)navigation - withError:(NSError *)error -{ - if (_onLoadingError) { - if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled) { - // NSURLErrorCancelled is reported when a page has a redirect OR if you load - // a new URL in the WebView before the previous one came back. We can just - // ignore these since they aren't real errors. - // http://stackoverflow.com/questions/1024748/how-do-i-fix-nsurlerrordomain-error-999-in-iphone-3-0-os - return; - } - - NSMutableDictionary *event = [self baseEvent]; - [event addEntriesFromDictionary:@{ - @"didFailProvisionalNavigation": @YES, - @"domain": error.domain, - @"code": @(error.code), - @"description": error.localizedDescription, - }]; - _onLoadingError(event); - } - - [self setBackgroundColor: _savedBackgroundColor]; -} - -+ (void)setClientAuthenticationCredential:(nullable NSURLCredential*)credential { - clientAuthenticationCredential = credential; -} - -- (void) webView:(__unused WKWebView *)webView - didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge - completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable))completionHandler -{ - if (!clientAuthenticationCredential) { - completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); - return; - } - if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate) { - completionHandler(NSURLSessionAuthChallengeUseCredential, clientAuthenticationCredential); - } else { - completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); -} -} - -- (void)evaluateJS:(NSString *)js - thenCall: (void (^)(NSString*)) callback -{ - [self.webView evaluateJavaScript: js completionHandler: ^(id result, NSError *error) { - if (error == nil && callback != nil) { - callback([NSString stringWithFormat:@"%@", result]); - } - }]; -} - - -/** - * Called when the navigation is complete. - * @see https://fburl.com/rtys6jlb - */ -- (void) webView:(__unused WKWebView *)webView - didFinishNavigation:(__unused WKNavigation *)navigation -{ - if (_messagingEnabled) { - #if RCT_DEV - - // Implementation inspired by Lodash.isNative. - NSString *isPostMessageNative = @"String(String(window.postMessage) === String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage'))"; - [self evaluateJS: isPostMessageNative thenCall: ^(NSString *result) { - if (! [result isEqualToString:@"true"]) { - RCTLogError(@"Setting onMessage on a WebView overrides existing values of window.postMessage, but a previous value was defined"); - } - }]; - #endif - - NSString *source = [NSString stringWithFormat: - @"(function() {" - "window.originalPostMessage = window.postMessage;" - - "window.postMessage = function(data) {" - "window.webkit.messageHandlers.%@.postMessage(String(data));" - "};" - "})();", - MessageHanderName - ]; - [self evaluateJS: source thenCall: nil]; - } - - if (_injectedJavaScript) { - [self evaluateJS: _injectedJavaScript thenCall: ^(NSString *jsEvaluationValue) { - NSMutableDictionary *event = [self baseEvent]; - event[@"jsEvaluationValue"] = jsEvaluationValue; - if (self.onLoadingFinish) { - self.onLoadingFinish(event); - } - }]; - } else if (_onLoadingFinish) { - _onLoadingFinish([self baseEvent]); - } - - [self setBackgroundColor: _savedBackgroundColor]; -} - -- (void)injectJavaScript:(NSString *)script -{ - [self evaluateJS: script thenCall: nil]; -} - -- (void)goForward -{ - [_webView goForward]; -} - -- (void)goBack -{ - [_webView goBack]; -} - -- (void)reload -{ - /** - * When the initial load fails due to network connectivity issues, - * [_webView reload] doesn't reload the webpage. Therefore, we must - * manually call [_webView loadRequest:request]. - */ - NSURLRequest *request = [RCTConvert NSURLRequest:self.source]; - if (request.URL && !_webView.URL.absoluteString.length) { - [_webView loadRequest:request]; - } - else { - [_webView reload]; - } -} - -- (void)stopLoading -{ - [_webView stopLoading]; -} - -- (void)setBounces:(BOOL)bounces -{ - _bounces = bounces; - _webView.scrollView.bounces = bounces; -} -@end diff --git a/React/Views/RCTWKWebViewManager.h b/React/Views/RCTWKWebViewManager.h deleted file mode 100644 index cf44faf240cbd0..00000000000000 --- a/React/Views/RCTWKWebViewManager.h +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -@interface RCTWKWebViewManager : RCTViewManager -@end diff --git a/React/Views/RCTWKWebViewManager.m b/React/Views/RCTWKWebViewManager.m deleted file mode 100644 index 39a6cfd8def77d..00000000000000 --- a/React/Views/RCTWKWebViewManager.m +++ /dev/null @@ -1,170 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "RCTWKWebViewManager.h" - -#import "RCTUIManager.h" -#import "RCTWKWebView.h" -#import - -@interface RCTWKWebViewManager () -@end - -@implementation RCTWKWebViewManager -{ - NSConditionLock *_shouldStartLoadLock; - BOOL _shouldStartLoad; -} - -RCT_EXPORT_MODULE() - -- (UIView *)view -{ - RCTWKWebView *webView = [RCTWKWebView new]; - webView.delegate = self; - return webView; -} - -RCT_EXPORT_VIEW_PROPERTY(source, NSDictionary) -RCT_EXPORT_VIEW_PROPERTY(onLoadingStart, RCTDirectEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onLoadingFinish, RCTDirectEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onLoadingError, RCTDirectEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onShouldStartLoadWithRequest, RCTDirectEventBlock) -RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString) -RCT_EXPORT_VIEW_PROPERTY(allowsInlineMediaPlayback, BOOL) -RCT_EXPORT_VIEW_PROPERTY(mediaPlaybackRequiresUserAction, BOOL) -#if WEBKIT_IOS_10_APIS_AVAILABLE -RCT_EXPORT_VIEW_PROPERTY(dataDetectorTypes, WKDataDetectorTypes) -#endif -RCT_EXPORT_VIEW_PROPERTY(contentInset, UIEdgeInsets) -RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustContentInsets, BOOL) - -/** - * Expose methods to enable messaging the webview. - */ -RCT_EXPORT_VIEW_PROPERTY(messagingEnabled, BOOL) -RCT_EXPORT_VIEW_PROPERTY(onMessage, RCTDirectEventBlock) - -RCT_EXPORT_METHOD(postMessage:(nonnull NSNumber *)reactTag message:(NSString *)message) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - RCTWKWebView *view = viewRegistry[reactTag]; - if (![view isKindOfClass:[RCTWKWebView class]]) { - RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); - } else { - [view postMessage:message]; - } - }]; -} - -RCT_CUSTOM_VIEW_PROPERTY(bounces, BOOL, __unused RCTWKWebView) { - view.bounces = json == nil ? true : [RCTConvert BOOL: json]; -} - -RCT_CUSTOM_VIEW_PROPERTY(scrollEnabled, BOOL, __unused RCTWKWebView) { - view.scrollEnabled = json == nil ? true : [RCTConvert BOOL: json]; -} - -RCT_CUSTOM_VIEW_PROPERTY(decelerationRate, CGFloat, __unused RCTWKWebView) { - view.decelerationRate = json == nil ? UIScrollViewDecelerationRateNormal : [RCTConvert CGFloat: json]; -} - -RCT_EXPORT_METHOD(injectJavaScript:(nonnull NSNumber *)reactTag script:(NSString *)script) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - RCTWKWebView *view = viewRegistry[reactTag]; - if (![view isKindOfClass:[RCTWKWebView class]]) { - RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); - } else { - [view injectJavaScript:script]; - } - }]; -} - -RCT_EXPORT_METHOD(goBack:(nonnull NSNumber *)reactTag) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - RCTWKWebView *view = viewRegistry[reactTag]; - if (![view isKindOfClass:[RCTWKWebView class]]) { - RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); - } else { - [view goBack]; - } - }]; -} - -RCT_EXPORT_METHOD(goForward:(nonnull NSNumber *)reactTag) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - RCTWKWebView *view = viewRegistry[reactTag]; - if (![view isKindOfClass:[RCTWKWebView class]]) { - RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); - } else { - [view goForward]; - } - }]; -} - -RCT_EXPORT_METHOD(reload:(nonnull NSNumber *)reactTag) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - RCTWKWebView *view = viewRegistry[reactTag]; - if (![view isKindOfClass:[RCTWKWebView class]]) { - RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); - } else { - [view reload]; - } - }]; -} - -RCT_EXPORT_METHOD(stopLoading:(nonnull NSNumber *)reactTag) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - RCTWKWebView *view = viewRegistry[reactTag]; - if (![view isKindOfClass:[RCTWKWebView class]]) { - RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); - } else { - [view stopLoading]; - } - }]; -} - -#pragma mark - Exported synchronous methods - -- (BOOL) webView:(__unused RCTWKWebView *)webView -shouldStartLoadForRequest:(NSMutableDictionary *)request - withCallback:(RCTDirectEventBlock)callback -{ - _shouldStartLoadLock = [[NSConditionLock alloc] initWithCondition:arc4random()]; - _shouldStartLoad = YES; - request[@"lockIdentifier"] = @(_shouldStartLoadLock.condition); - callback(request); - - // Block the main thread for a maximum of 250ms until the JS thread returns - if ([_shouldStartLoadLock lockWhenCondition:0 beforeDate:[NSDate dateWithTimeIntervalSinceNow:.25]]) { - BOOL returnValue = _shouldStartLoad; - [_shouldStartLoadLock unlock]; - _shouldStartLoadLock = nil; - return returnValue; - } else { - RCTLogWarn(@"Did not receive response to shouldStartLoad in time, defaulting to YES"); - return YES; - } -} - -RCT_EXPORT_METHOD(startLoadWithResult:(BOOL)result lockIdentifier:(NSInteger)lockIdentifier) -{ - if ([_shouldStartLoadLock tryLockWhenCondition:lockIdentifier]) { - _shouldStartLoad = result; - [_shouldStartLoadLock unlockWithCondition:0]; - } else { - RCTLogWarn(@"startLoadWithResult invoked with invalid lockIdentifier: " - "got %lld, expected %lld", (long long)lockIdentifier, (long long)_shouldStartLoadLock.condition); - } -} - -@end diff --git a/React/Views/RCTWebView.h b/React/Views/RCTWebView.h deleted file mode 100644 index 4fa9d62d8a831d..00000000000000 --- a/React/Views/RCTWebView.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -@class RCTWebView; - -/** - * Special scheme used to pass messages to the injectedJavaScript - * code without triggering a page load. Usage: - * - * window.location.href = RCTJSNavigationScheme + '://hello' - */ -extern NSString *const RCTJSNavigationScheme; - -@protocol RCTWebViewDelegate - -- (BOOL)webView:(RCTWebView *)webView -shouldStartLoadForRequest:(NSMutableDictionary *)request - withCallback:(RCTDirectEventBlock)callback; - -@end - -@interface RCTWebView : RCTView - -@property (nonatomic, weak) id delegate; - -@property (nonatomic, copy) NSDictionary *source; -@property (nonatomic, assign) UIEdgeInsets contentInset; -@property (nonatomic, assign) BOOL automaticallyAdjustContentInsets; -@property (nonatomic, assign) BOOL messagingEnabled; -@property (nonatomic, copy) NSString *injectedJavaScript; -@property (nonatomic, assign) BOOL scalesPageToFit; - -- (void)goForward; -- (void)goBack; -- (void)reload; -- (void)stopLoading; -- (void)postMessage:(NSString *)message; -- (void)injectJavaScript:(NSString *)script; - -@end diff --git a/React/Views/RCTWebView.m b/React/Views/RCTWebView.m deleted file mode 100644 index 8f61e38041439e..00000000000000 --- a/React/Views/RCTWebView.m +++ /dev/null @@ -1,351 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "RCTWebView.h" - -#import - -#import "RCTAutoInsetsProtocol.h" -#import "RCTConvert.h" -#import "RCTEventDispatcher.h" -#import "RCTLog.h" -#import "RCTUtils.h" -#import "RCTView.h" -#import "UIView+React.h" - -NSString *const RCTJSNavigationScheme = @"react-js-navigation"; - -static NSString *const kPostMessageHost = @"postMessage"; - -@interface RCTWebView () - -@property (nonatomic, copy) RCTDirectEventBlock onLoadingStart; -@property (nonatomic, copy) RCTDirectEventBlock onLoadingFinish; -@property (nonatomic, copy) RCTDirectEventBlock onLoadingError; -@property (nonatomic, copy) RCTDirectEventBlock onShouldStartLoadWithRequest; -@property (nonatomic, copy) RCTDirectEventBlock onMessage; - -@end - -@implementation RCTWebView -{ - UIWebView *_webView; - NSString *_injectedJavaScript; -} - -- (void)dealloc -{ - _webView.delegate = nil; -} - -- (instancetype)initWithFrame:(CGRect)frame -{ - if ((self = [super initWithFrame:frame])) { - super.backgroundColor = [UIColor clearColor]; - _automaticallyAdjustContentInsets = YES; - _contentInset = UIEdgeInsetsZero; - _webView = [[UIWebView alloc] initWithFrame:self.bounds]; - _webView.delegate = self; -#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */ - if ([_webView.scrollView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) { - _webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; - } -#endif - [self addSubview:_webView]; - } - return self; -} - -RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder) - -- (void)goForward -{ - [_webView goForward]; -} - -- (void)goBack -{ - [_webView goBack]; -} - -- (void)reload -{ - NSURLRequest *request = [RCTConvert NSURLRequest:self.source]; - if (request.URL && !_webView.request.URL.absoluteString.length) { - [_webView loadRequest:request]; - } - else { - [_webView reload]; - } -} - -- (void)stopLoading -{ - [_webView stopLoading]; -} - -- (void)postMessage:(NSString *)message -{ - NSDictionary *eventInitDict = @{ - @"data": message, - }; - NSString *source = [NSString - stringWithFormat:@"document.dispatchEvent(new MessageEvent('message', %@));", - RCTJSONStringify(eventInitDict, NULL) - ]; - [_webView stringByEvaluatingJavaScriptFromString:source]; -} - -- (void)injectJavaScript:(NSString *)script -{ - [_webView stringByEvaluatingJavaScriptFromString:script]; -} - -- (void)setSource:(NSDictionary *)source -{ - if (![_source isEqualToDictionary:source]) { - _source = [source copy]; - - // Check for a static html source first - NSString *html = [RCTConvert NSString:source[@"html"]]; - if (html) { - NSURL *baseURL = [RCTConvert NSURL:source[@"baseUrl"]]; - if (!baseURL) { - baseURL = [NSURL URLWithString:@"about:blank"]; - } - [_webView loadHTMLString:html baseURL:baseURL]; - return; - } - - NSURLRequest *request = [RCTConvert NSURLRequest:source]; - // Because of the way React works, as pages redirect, we actually end up - // passing the redirect urls back here, so we ignore them if trying to load - // the same url. We'll expose a call to 'reload' to allow a user to load - // the existing page. - if ([request.URL isEqual:_webView.request.URL]) { - return; - } - if (!request.URL) { - // Clear the webview - [_webView loadHTMLString:@"" baseURL:nil]; - return; - } - [_webView loadRequest:request]; - } -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - _webView.frame = self.bounds; -} - -- (void)setContentInset:(UIEdgeInsets)contentInset -{ - _contentInset = contentInset; - [RCTView autoAdjustInsetsForView:self - withScrollView:_webView.scrollView - updateOffset:NO]; -} - -- (void)setScalesPageToFit:(BOOL)scalesPageToFit -{ - if (_webView.scalesPageToFit != scalesPageToFit) { - _webView.scalesPageToFit = scalesPageToFit; - [_webView reload]; - } -} - -- (BOOL)scalesPageToFit -{ - return _webView.scalesPageToFit; -} - -- (void)setBackgroundColor:(UIColor *)backgroundColor -{ - CGFloat alpha = CGColorGetAlpha(backgroundColor.CGColor); - self.opaque = _webView.opaque = (alpha == 1.0); - _webView.backgroundColor = backgroundColor; -} - -- (UIColor *)backgroundColor -{ - return _webView.backgroundColor; -} - -- (NSMutableDictionary *)baseEvent -{ - NSMutableDictionary *event = [[NSMutableDictionary alloc] initWithDictionary:@{ - @"url": _webView.request.URL.absoluteString ?: @"", - @"loading" : @(_webView.loading), - @"title": [_webView stringByEvaluatingJavaScriptFromString:@"document.title"], - @"canGoBack": @(_webView.canGoBack), - @"canGoForward" : @(_webView.canGoForward), - }]; - - return event; -} - -- (void)refreshContentInset -{ - [RCTView autoAdjustInsetsForView:self - withScrollView:_webView.scrollView - updateOffset:YES]; -} - -#pragma mark - UIWebViewDelegate methods - -- (BOOL)webView:(__unused UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request - navigationType:(UIWebViewNavigationType)navigationType -{ - BOOL isJSNavigation = [request.URL.scheme isEqualToString:RCTJSNavigationScheme]; - - static NSDictionary *navigationTypes; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - navigationTypes = @{ - @(UIWebViewNavigationTypeLinkClicked): @"click", - @(UIWebViewNavigationTypeFormSubmitted): @"formsubmit", - @(UIWebViewNavigationTypeBackForward): @"backforward", - @(UIWebViewNavigationTypeReload): @"reload", - @(UIWebViewNavigationTypeFormResubmitted): @"formresubmit", - @(UIWebViewNavigationTypeOther): @"other", - }; - }); - - // skip this for the JS Navigation handler - if (!isJSNavigation && _onShouldStartLoadWithRequest) { - NSMutableDictionary *event = [self baseEvent]; - [event addEntriesFromDictionary: @{ - @"url": (request.URL).absoluteString, - @"navigationType": navigationTypes[@(navigationType)] - }]; - if (![self.delegate webView:self - shouldStartLoadForRequest:event - withCallback:_onShouldStartLoadWithRequest]) { - return NO; - } - } - - if (_onLoadingStart) { - // We have this check to filter out iframe requests and whatnot - BOOL isTopFrame = [request.URL isEqual:request.mainDocumentURL]; - if (isTopFrame) { - NSMutableDictionary *event = [self baseEvent]; - [event addEntriesFromDictionary: @{ - @"url": (request.URL).absoluteString, - @"navigationType": navigationTypes[@(navigationType)] - }]; - _onLoadingStart(event); - } - } - - if (isJSNavigation && [request.URL.host isEqualToString:kPostMessageHost]) { - NSString *data = request.URL.query; - data = [data stringByReplacingOccurrencesOfString:@"+" withString:@" "]; - data = [data stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]; - - NSMutableDictionary *event = [self baseEvent]; - [event addEntriesFromDictionary: @{ - @"data": data, - }]; - - NSString *source = @"document.dispatchEvent(new MessageEvent('message:received'));"; - - [_webView stringByEvaluatingJavaScriptFromString:source]; - - _onMessage(event); - } - - // JS Navigation handler - return !isJSNavigation; -} - -- (void)webView:(__unused UIWebView *)webView didFailLoadWithError:(NSError *)error -{ - if (_onLoadingError) { - if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled) { - // NSURLErrorCancelled is reported when a page has a redirect OR if you load - // a new URL in the WebView before the previous one came back. We can just - // ignore these since they aren't real errors. - // http://stackoverflow.com/questions/1024748/how-do-i-fix-nsurlerrordomain-error-999-in-iphone-3-0-os - return; - } - - if ([error.domain isEqualToString:@"WebKitErrorDomain"] && error.code == 102) { - // Error code 102 "Frame load interrupted" is raised by the UIWebView if - // its delegate returns FALSE from webView:shouldStartLoadWithRequest:navigationType - // when the URL is from an http redirect. This is a common pattern when - // implementing OAuth with a WebView. - return; - } - - NSMutableDictionary *event = [self baseEvent]; - [event addEntriesFromDictionary:@{ - @"domain": error.domain, - @"code": @(error.code), - @"description": error.localizedDescription, - }]; - _onLoadingError(event); - } -} - -- (void)webViewDidFinishLoad:(UIWebView *)webView -{ - if (_messagingEnabled) { - #if RCT_DEV - // See isNative in lodash - NSString *testPostMessageNative = @"String(window.postMessage) === String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage')"; - BOOL postMessageIsNative = [ - [webView stringByEvaluatingJavaScriptFromString:testPostMessageNative] - isEqualToString:@"true" - ]; - if (!postMessageIsNative) { - RCTLogError(@"Setting onMessage on a WebView overrides existing values of window.postMessage, but a previous value was defined"); - } - #endif - NSString *source = [NSString stringWithFormat: - @"(function() {" - "window.originalPostMessage = window.postMessage;" - - "var messageQueue = [];" - "var messagePending = false;" - - "function processQueue() {" - "if (!messageQueue.length || messagePending) return;" - "messagePending = true;" - "window.location = '%@://%@?' + encodeURIComponent(messageQueue.shift());" - "}" - - "window.postMessage = function(data) {" - "messageQueue.push(String(data));" - "processQueue();" - "};" - - "document.addEventListener('message:received', function(e) {" - "messagePending = false;" - "processQueue();" - "});" - "})();", RCTJSNavigationScheme, kPostMessageHost - ]; - [webView stringByEvaluatingJavaScriptFromString:source]; - } - if (_injectedJavaScript != nil) { - NSString *jsEvaluationValue = [webView stringByEvaluatingJavaScriptFromString:_injectedJavaScript]; - - NSMutableDictionary *event = [self baseEvent]; - event[@"jsEvaluationValue"] = jsEvaluationValue; - - _onLoadingFinish(event); - } - // we only need the final 'finishLoad' call so only fire the event when we're actually done loading. - else if (_onLoadingFinish && !webView.loading && ![webView.request.URL.absoluteString isEqualToString:@"about:blank"]) { - _onLoadingFinish([self baseEvent]); - } -} - -@end diff --git a/React/Views/RCTWebViewManager.h b/React/Views/RCTWebViewManager.h deleted file mode 100644 index d06ea1b806e470..00000000000000 --- a/React/Views/RCTWebViewManager.h +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -@interface RCTWebViewManager : RCTViewManager - -@end diff --git a/React/Views/RCTWebViewManager.m b/React/Views/RCTWebViewManager.m deleted file mode 100644 index fc39f7cb1382a2..00000000000000 --- a/React/Views/RCTWebViewManager.m +++ /dev/null @@ -1,158 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "RCTWebViewManager.h" - -#import "RCTBridge.h" -#import "RCTUIManager.h" -#import "RCTWebView.h" -#import "UIView+React.h" - -@interface RCTWebViewManager () - -@end - -@implementation RCTWebViewManager -{ - NSConditionLock *_shouldStartLoadLock; - BOOL _shouldStartLoad; -} - -RCT_EXPORT_MODULE() - -- (UIView *)view -{ - RCTWebView *webView = [RCTWebView new]; - webView.delegate = self; - return webView; -} - -RCT_EXPORT_VIEW_PROPERTY(source, NSDictionary) -RCT_REMAP_VIEW_PROPERTY(bounces, _webView.scrollView.bounces, BOOL) -RCT_REMAP_VIEW_PROPERTY(scrollEnabled, _webView.scrollView.scrollEnabled, BOOL) -RCT_REMAP_VIEW_PROPERTY(decelerationRate, _webView.scrollView.decelerationRate, CGFloat) -RCT_EXPORT_VIEW_PROPERTY(scalesPageToFit, BOOL) -RCT_EXPORT_VIEW_PROPERTY(messagingEnabled, BOOL) -RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString) -RCT_EXPORT_VIEW_PROPERTY(contentInset, UIEdgeInsets) -RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustContentInsets, BOOL) -RCT_EXPORT_VIEW_PROPERTY(onLoadingStart, RCTDirectEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onLoadingFinish, RCTDirectEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onLoadingError, RCTDirectEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onMessage, RCTDirectEventBlock) -RCT_EXPORT_VIEW_PROPERTY(onShouldStartLoadWithRequest, RCTDirectEventBlock) -RCT_REMAP_VIEW_PROPERTY(allowsInlineMediaPlayback, _webView.allowsInlineMediaPlayback, BOOL) -RCT_REMAP_VIEW_PROPERTY(mediaPlaybackRequiresUserAction, _webView.mediaPlaybackRequiresUserAction, BOOL) -RCT_REMAP_VIEW_PROPERTY(dataDetectorTypes, _webView.dataDetectorTypes, UIDataDetectorTypes) - -RCT_EXPORT_METHOD(goBack:(nonnull NSNumber *)reactTag) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - RCTWebView *view = viewRegistry[reactTag]; - if (![view isKindOfClass:[RCTWebView class]]) { - RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); - } else { - [view goBack]; - } - }]; -} - -RCT_EXPORT_METHOD(goForward:(nonnull NSNumber *)reactTag) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - RCTWebView *view = viewRegistry[reactTag]; - if (![view isKindOfClass:[RCTWebView class]]) { - RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); - } else { - [view goForward]; - } - }]; -} - -RCT_EXPORT_METHOD(reload:(nonnull NSNumber *)reactTag) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - RCTWebView *view = viewRegistry[reactTag]; - if (![view isKindOfClass:[RCTWebView class]]) { - RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); - } else { - [view reload]; - } - }]; -} - -RCT_EXPORT_METHOD(stopLoading:(nonnull NSNumber *)reactTag) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - RCTWebView *view = viewRegistry[reactTag]; - if (![view isKindOfClass:[RCTWebView class]]) { - RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); - } else { - [view stopLoading]; - } - }]; -} - -RCT_EXPORT_METHOD(postMessage:(nonnull NSNumber *)reactTag message:(NSString *)message) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - RCTWebView *view = viewRegistry[reactTag]; - if (![view isKindOfClass:[RCTWebView class]]) { - RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); - } else { - [view postMessage:message]; - } - }]; -} - -RCT_EXPORT_METHOD(injectJavaScript:(nonnull NSNumber *)reactTag script:(NSString *)script) -{ - [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - RCTWebView *view = viewRegistry[reactTag]; - if (![view isKindOfClass:[RCTWebView class]]) { - RCTLogError(@"Invalid view returned from registry, expecting RCTWebView, got: %@", view); - } else { - [view injectJavaScript:script]; - } - }]; -} - -#pragma mark - Exported synchronous methods - -- (BOOL)webView:(__unused RCTWebView *)webView -shouldStartLoadForRequest:(NSMutableDictionary *)request - withCallback:(RCTDirectEventBlock)callback -{ - _shouldStartLoadLock = [[NSConditionLock alloc] initWithCondition:arc4random()]; - _shouldStartLoad = YES; - request[@"lockIdentifier"] = @(_shouldStartLoadLock.condition); - callback(request); - - // Block the main thread for a maximum of 250ms until the JS thread returns - if ([_shouldStartLoadLock lockWhenCondition:0 beforeDate:[NSDate dateWithTimeIntervalSinceNow:.25]]) { - BOOL returnValue = _shouldStartLoad; - [_shouldStartLoadLock unlock]; - _shouldStartLoadLock = nil; - return returnValue; - } else { - RCTLogWarn(@"Did not receive response to shouldStartLoad in time, defaulting to YES"); - return YES; - } -} - -RCT_EXPORT_METHOD(startLoadWithResult:(BOOL)result lockIdentifier:(NSInteger)lockIdentifier) -{ - if ([_shouldStartLoadLock tryLockWhenCondition:lockIdentifier]) { - _shouldStartLoad = result; - [_shouldStartLoadLock unlockWithCondition:0]; - } else { - RCTLogWarn(@"startLoadWithResult invoked with invalid lockIdentifier: " - "got %lld, expected %lld", (long long)lockIdentifier, (long long)_shouldStartLoadLock.condition); - } -} - -@end