diff --git a/ios/RNCWebView.m b/ios/RNCWebView.m index deda93288..968eb3e93 100644 --- a/ios/RNCWebView.m +++ b/ios/RNCWebView.m @@ -15,6 +15,7 @@ static NSTimer *keyboardTimer; static NSString *const MessageHandlerName = @"ReactNativeWebView"; +static NSString *const HistoryShimName = @"ReactNativeHistoryShim"; static NSURLCredential* clientAuthenticationCredential; // runtime trick to remove WKWebView keyboard default toolbar @@ -130,6 +131,32 @@ - (void)didMoveToWindow } wkWebViewConfig.userContentController = [WKUserContentController new]; + // Shim the HTML5 history API: + [wkWebViewConfig.userContentController addScriptMessageHandler:self name:HistoryShimName]; + NSString *source = [NSString stringWithFormat: + @"(function(history) {\n" + " function notify(type) {\n" + " setTimeout(function() {\n" + " window.webkit.messageHandlers.%@.postMessage(type)\n" + " }, 0)\n" + " }\n" + " function shim(f) {\n" + " return function pushState() {\n" + " notify('other')\n" + " return f.apply(history, arguments)\n" + " }\n" + " }\n" + " history.pushState = shim(history.pushState)\n" + " history.replaceState = shim(history.replaceState)\n" + " window.addEventListener('popstate', function() {\n" + " notify('backforward')\n" + " })\n" + "})(window.history)\n", HistoryShimName + ]; + WKUserScript *script = [[WKUserScript alloc] initWithSource:source injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; + [wkWebViewConfig.userContentController addUserScript:script]; + + if (_messagingEnabled) { [wkWebViewConfig.userContentController addScriptMessageHandler:self name:MessageHandlerName]; @@ -372,10 +399,21 @@ - (void)setContentInsetAdjustmentBehavior:(UIScrollViewContentInsetAdjustmentBeh - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { - if (_onMessage != nil) { + if ([message.name isEqualToString:HistoryShimName]) { NSMutableDictionary *event = [self baseEvent]; - [event addEntriesFromDictionary: @{@"data": message.body}]; - _onMessage(event); + if (_onLoadingFinish) { + [event addEntriesFromDictionary: @{@"data": message.body}]; + NSMutableDictionary *event = [self baseEvent]; + _onMessage(event); + [event addEntriesFromDictionary: @{@"navigationType": message.body}]; + _onLoadingFinish(event); + } + } else if ([message.name isEqualToString:MessageHandlerName]) { + if (_onMessage) { + NSMutableDictionary *event = [self baseEvent]; + [event addEntriesFromDictionary: @{@"data": message.body}]; + _onMessage(event); + } } }