@@ -34,6 +34,8 @@ @interface RCTWKWebView () <WKNavigationDelegate, RCTAutoInsetsProtocol, WKScrip
3434@property  (nonatomic , copy ) RCTDirectEventBlock onMessage;
3535@property  (nonatomic , copy ) RCTDirectEventBlock onScroll;
3636@property  (nonatomic , copy ) RCTDirectEventBlock onNavigationResponse;
37+ @property  (nonatomic , copy ) RCTDirectEventBlock onCanGoBackChange;
38+ @property  (nonatomic , copy ) RCTDirectEventBlock onCanGoForwardChange;
3739@property  (assign ) BOOL  sendCookies;
3840@property  (assign ) BOOL  useWKCookieStore;
3941@property  (nonatomic , strong ) WKUserScript  *atStartScript;
@@ -64,18 +66,18 @@ - (instancetype)initWithProcessPool:(WKProcessPool *)processPool
6466    super.backgroundColor  = [UIColor clearColor ];
6567    _automaticallyAdjustContentInsets = YES ;
6668    _contentInset = UIEdgeInsetsZero;
67-      
69+ 
6870    WKWebViewConfiguration * config = [[WKWebViewConfiguration  alloc ] init ];
6971    config.processPool  = processPool;
7072    WKUserContentController * userController = [[WKUserContentController  alloc ]init];
7173    [userController addScriptMessageHandler: [[WeakScriptMessageDelegate alloc ] initWithDelegate: self ] name: @" reactNative" 
7274    config.userContentController  = userController;
73-      
75+ 
7476    _webView = [[WKWebView  alloc ] initWithFrame: self .bounds configuration: config];
7577    _webView.UIDelegate  = self;
7678    _webView.navigationDelegate  = self;
7779    _webView.scrollView .delegate  = self;
78-      
80+ 
7981#if  defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /*  __IPHONE_11_0 */ 
8082    //  `contentInsetAdjustmentBehavior` is only available since iOS 11.
8183    //  We set the default behavior to "never" so that iOS
@@ -87,6 +89,8 @@ - (instancetype)initWithProcessPool:(WKProcessPool *)processPool
8789#endif 
8890    [self  setupPostMessageScript ];
8991    [_webView addObserver: self  forKeyPath: @" estimatedProgress" options: NSKeyValueObservingOptionNew context: nil ];
92+     [_webView addObserver: self  forKeyPath: @" canGoBack" options: NSKeyValueObservingOptionNew context: nil ];
93+     [_webView addObserver: self  forKeyPath: @" canGoForward" options: NSKeyValueObservingOptionNew context: nil ];
9094    [self  addSubview: _webView];
9195  }
9296  return  self;
@@ -164,7 +168,7 @@ - (void)loadRequest:(NSURLRequest *)request
164168      request = mutableRequest;
165169    }
166170  }
167-    
171+ 
168172  [_webView loadRequest: request];
169173}
170174
@@ -180,29 +184,29 @@ -(void)setHideKeyboardAccessoryView:(BOOL)hideKeyboardAccessoryView
180184  if  (!hideKeyboardAccessoryView) {
181185    return ;
182186  }
183-    
187+ 
184188  UIView* subview;
185189  for  (UIView* view in _webView.scrollView .subviews ) {
186190    if ([[view.class description ] hasPrefix: @" WKContent" 
187191      subview = view;
188192  }
189-    
193+ 
190194  if (subview == nil ) return ;
191-    
195+ 
192196  NSString * name = [NSString  stringWithFormat: @" %@ _SwizzleHelperWK" 
193197  Class  newClass = NSClassFromString (name);
194-    
198+ 
195199  if (newClass == nil )
196200  {
197201    newClass = objc_allocateClassPair (subview.class , [name cStringUsingEncoding: NSASCIIStringEncoding], 0 );
198202    if (!newClass) return ;
199-      
203+ 
200204    Method  method = class_getInstanceMethod ([_SwizzleHelperWK class ], @selector (inputAccessoryView ));
201205    class_addMethod (newClass, @selector (inputAccessoryView ), method_getImplementation (method), method_getTypeEncoding (method));
202-      
206+ 
203207    objc_registerClassPair (newClass);
204208  }
205-    
209+ 
206210  object_setClass (subview, newClass);
207211}
208212
@@ -213,7 +217,7 @@ -(void)setKeyboardDisplayRequiresUserAction:(BOOL)keyboardDisplayRequiresUserAct
213217  if  (!keyboardDisplayRequiresUserAction) {
214218    Class  class = NSClassFromString (@" WKContentView" 
215219    NSOperatingSystemVersion  iOS_11_3_0 = (NSOperatingSystemVersion ){11 , 3 , 0 };
216-      
220+ 
217221    if  ([[NSProcessInfo  processInfo ] isOperatingSystemAtLeastVersion:  iOS_11_3_0]) {
218222      SEL  selector = sel_getUid (" _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:" 
219223      Method  method = class_getInstanceMethod (class, selector);
@@ -371,20 +375,20 @@ - (void)setSource:(NSDictionary *)source
371375    if  ([source[@" customUserAgent" length ] != 0  && [_webView respondsToSelector: @selector (setCustomUserAgent: )]) {
372376      [_webView setCustomUserAgent: source[@" customUserAgent" 
373377    }
374-      
378+ 
375379    //  Allow loading local files:
376380    //  <WKWebView source={{ file: RNFS.MainBundlePath + '/data/index.html', allowingReadAccessToURL: RNFS.MainBundlePath }} />
377381    //  Only works for iOS 9+. So iOS 8 will simply ignore those two values
378382    NSString  *file = [RCTConvert NSString: source[@" file" 
379383    NSString  *allowingReadAccessToURL = [RCTConvert NSString: source[@" allowingReadAccessToURL" 
380-      
384+ 
381385    if  (file && [_webView respondsToSelector: @selector (loadFileURL:allowingReadAccessToURL: )]) {
382386      NSURL  *fileURL = [RCTConvert NSURL: file];
383387      NSURL  *baseURL = [RCTConvert NSURL: allowingReadAccessToURL];
384388      [_webView loadFileURL: fileURL allowingReadAccessToURL: baseURL];
385389      return ;
386390    }
387-      
391+ 
388392    //  Check for a static html source first
389393    NSString  *html = [RCTConvert NSString: source[@" html" 
390394    if  (html) {
@@ -395,7 +399,7 @@ - (void)setSource:(NSDictionary *)source
395399      [_webView loadHTMLString: html baseURL: baseURL];
396400      return ;
397401    }
398-      
402+ 
399403    NSURLRequest  *request = [RCTConvert NSURLRequest: source];
400404    //  Because of the way React works, as pages redirect, we actually end up
401405    //  passing the redirect urls back here, so we ignore them if trying to load
@@ -448,7 +452,7 @@ - (UIColor *)backgroundColor
448452                                                                                                 @" canGoBack" canGoBack ),
449453                                                                                                 @" canGoForward" canGoForward ),
450454                                                                                                 }];
451-    
455+ 
452456  return  event;
453457}
454458
@@ -470,6 +474,20 @@ - (void)observeValueForKeyPath:(NSString *)keyPath
470474    }
471475    _onProgress (@{@" progress" objectForKey: NSKeyValueChangeNewKey ]});
472476  }
477+ 
478+   if  ([keyPath isEqualToString: @" canGoBack" 
479+     if  (!_onCanGoBackChange) {
480+       return ;
481+     }
482+     _onCanGoBackChange (@{@" canGoBack" objectForKey: NSKeyValueChangeNewKey ]});
483+   }
484+ 
485+   if  ([keyPath isEqualToString: @" canGoForward" 
486+     if  (!_onCanGoForwardChange) {
487+       return ;
488+     }
489+     _onCanGoForwardChange (@{@" canGoForward" objectForKey: NSKeyValueChangeNewKey ]});
490+   }
473491}
474492
475493- (void )dealloc 
@@ -525,9 +543,9 @@ - (void)webView:(__unused WKWebView *)webView decidePolicyForNavigationAction:(W
525543  NSURLRequest  *request = navigationAction.request ;
526544  NSURL * url = request.URL ;
527545  NSString * scheme = url.scheme ;
528-    
546+ 
529547  BOOL  isJSNavigation = [scheme isEqualToString: RCTJSNavigationScheme];
530-    
548+ 
531549  //  handle mailto and tel schemes
532550  if  ([scheme isEqualToString: @" mailto" isEqualToString: @" tel" 
533551    if  ([app canOpenURL: url]) {
@@ -536,7 +554,7 @@ - (void)webView:(__unused WKWebView *)webView decidePolicyForNavigationAction:(W
536554      return ;
537555    }
538556  }
539-    
557+ 
540558  //  skip this for the JS Navigation handler
541559  if  (!isJSNavigation && _onShouldStartLoadWithRequest) {
542560    NSMutableDictionary <NSString  *, id > *event = [self  baseEvent ];
@@ -550,7 +568,7 @@ - (void)webView:(__unused WKWebView *)webView decidePolicyForNavigationAction:(W
550568      return  decisionHandler (WKNavigationActionPolicyCancel );
551569    }
552570  }
553-    
571+ 
554572  if  (_onLoadingStart) {
555573    //  We have this check to filter out iframe requests and whatnot
556574    BOOL  isTopFrame = [url isEqual: request.mainDocumentURL];
@@ -563,7 +581,7 @@ - (void)webView:(__unused WKWebView *)webView decidePolicyForNavigationAction:(W
563581      _onLoadingStart (event);
564582    }
565583  }
566-    
584+ 
567585  if  (isJSNavigation) {
568586    decisionHandler (WKNavigationActionPolicyCancel );
569587  }
@@ -582,7 +600,7 @@ - (void)webView:(__unused WKWebView *)webView didFailProvisionalNavigation:(__un
582600      //  http://stackoverflow.com/questions/1024748/how-do-i-fix-nsurlerrordomain-error-999-in-iphone-3-0-os
583601      return ;
584602    }
585-      
603+ 
586604    NSMutableDictionary <NSString  *, id > *event = [self  baseEvent ];
587605    [event addEntriesFromDictionary: @{
588606                                      @" domain" domain ,
@@ -605,7 +623,7 @@ - (void)webView:(WKWebView *)webView didFinishNavigation:(__unused WKNavigation
605623
606624- (void )webView : (WKWebView  *)webView  runJavaScriptAlertPanelWithMessage : (NSString  *)message  initiatedByFrame : (WKFrameInfo  *)frame  completionHandler : (void  (^)(void ))completionHandler  {
607625  UIAlertController *alertController = [UIAlertController alertControllerWithTitle: message message: nil  preferredStyle: UIAlertControllerStyleAlert];
608-    
626+ 
609627  [alertController addAction: [UIAlertAction actionWithTitle: NSLocalizedString(@" Close" nil ) style: UIAlertActionStyleCancel handler: ^(UIAlertAction *action) {
610628    completionHandler ();
611629  }]];
@@ -614,7 +632,7 @@ - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSStrin
614632}
615633
616634- (void )webView : (WKWebView  *)webView  runJavaScriptConfirmPanelWithMessage : (NSString  *)message  initiatedByFrame : (WKFrameInfo  *)frame  completionHandler : (void  (^)(BOOL ))completionHandler  {
617-    
635+ 
618636  //  TODO We have to think message to confirm "YES"
619637  UIAlertController *alertController = [UIAlertController alertControllerWithTitle: message message: nil  preferredStyle: UIAlertControllerStyleAlert];
620638  [alertController addAction: [UIAlertAction actionWithTitle: NSLocalizedString(@" OK" nil ) style: UIAlertActionStyleDefault handler: ^(UIAlertAction *action) {
@@ -628,17 +646,17 @@ - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSStr
628646}
629647
630648- (void )webView : (WKWebView  *)webView  runJavaScriptTextInputPanelWithPrompt : (NSString  *)prompt  defaultText : (NSString  *)defaultText  initiatedByFrame : (WKFrameInfo  *)frame  completionHandler : (void  (^)(NSString  *))completionHandler  {
631-    
649+ 
632650  UIAlertController *alertController = [UIAlertController alertControllerWithTitle: prompt message: nil  preferredStyle: UIAlertControllerStyleAlert];
633651  [alertController addTextFieldWithConfigurationHandler: ^(UITextField *textField) {
634652    textField.text  = defaultText;
635653  }];
636-    
654+ 
637655  [alertController addAction: [UIAlertAction actionWithTitle: NSLocalizedString(@" OK" nil ) style: UIAlertActionStyleDefault handler: ^(UIAlertAction *action) {
638656    NSString  *input = ((UITextField *)alertController.textFields .firstObject ).text ;
639657    completionHandler (input);
640658  }]];
641-    
659+ 
642660  [alertController addAction: [UIAlertAction actionWithTitle: NSLocalizedString(@" Cancel" nil ) style: UIAlertActionStyleCancel handler: ^(UIAlertAction *action) {
643661    completionHandler (nil );
644662  }]];
0 commit comments