diff --git a/android/src/main/java/com/reactnativecommunity/webview/RNCWebView.java b/android/src/main/java/com/reactnativecommunity/webview/RNCWebView.java index 7a2cc3c66..c80cf753f 100644 --- a/android/src/main/java/com/reactnativecommunity/webview/RNCWebView.java +++ b/android/src/main/java/com/reactnativecommunity/webview/RNCWebView.java @@ -263,7 +263,7 @@ protected void createRNCWebViewBridge(RNCWebView webView) { this.bridgeListener = new WebViewCompat.WebMessageListener() { @Override public void onPostMessage(@NonNull WebView view, @NonNull WebMessageCompat message, @NonNull Uri sourceOrigin, boolean isMainFrame, @NonNull JavaScriptReplyProxy replyProxy) { - RNCWebView.this.onMessage(message.getData(), sourceOrigin.toString(), isMainFrame); + RNCWebView.this.onMessage(message.getData(), sourceOrigin.toString(), isMainFrame, view.getUrl()); } }; WebViewCompat.addWebMessageListener( @@ -345,10 +345,14 @@ public void setInjectedJavaScriptObject(String obj) { } public void onMessage(String message, String sourceUrl) { - onMessage(message, sourceUrl, null); + onMessage(message, sourceUrl, null, null); } public void onMessage(String message, String sourceUrl, @Nullable Boolean isMainFrame) { + onMessage(message, sourceUrl, isMainFrame, null); + } + + public void onMessage(String message, String sourceUrl, @Nullable Boolean isMainFrame, @Nullable String topFrameUrl) { ThemedReactContext reactContext = getThemedReactContext(); RNCWebView mWebView = this; @@ -365,6 +369,9 @@ public void run() { if (isMainFrame != null) { data.putBoolean("isMainFrame", isMainFrame); } + if (topFrameUrl != null) { + data.putString("topFrameUrl", topFrameUrl); + } if (mMessagingJSModule != null) { dispatchDirectMessage(data); @@ -379,6 +386,9 @@ public void run() { if (isMainFrame != null) { eventData.putBoolean("isMainFrame", isMainFrame); } + if (topFrameUrl != null) { + eventData.putString("topFrameUrl", topFrameUrl); + } if (mMessagingJSModule != null) { dispatchDirectMessage(eventData); @@ -476,7 +486,7 @@ protected class RNCWebViewBridge { public void postMessage(String message) { if (mWebView.getMessagingEnabled()) { // Post to main thread because `mWebView.getUrl()` requires to be executed on main. - mWebView.post(() -> mWebView.onMessage(message, mWebView.getUrl())); + mWebView.post(() -> mWebView.onMessage(message, mWebView.getUrl(), null, mWebView.getUrl())); } else { FLog.w(TAG, "ReactNativeWebView.postMessage method was called but messaging is disabled. Pass an onMessage handler to the WebView."); } @@ -495,4 +505,4 @@ public boolean isWaitingForCommandLoadUrl() { return waitingForCommandLoadUrl; } } -} \ No newline at end of file +} diff --git a/apple/RNCWebView.mm b/apple/RNCWebView.mm index 32b96540f..c3930dafb 100644 --- a/apple/RNCWebView.mm +++ b/apple/RNCWebView.mm @@ -127,6 +127,8 @@ - (instancetype)initWithFrame:(CGRect)frame _view.onMessage = [self](NSDictionary* dictionary) { if (_eventEmitter) { auto webViewEventEmitter = std::static_pointer_cast(_eventEmitter); + id topFrameUrlValue = [dictionary valueForKey:@"topFrameUrl"]; + NSString *topFrameUrl = [topFrameUrlValue isKindOfClass:[NSString class]] ? topFrameUrlValue : @""; facebook::react::RNCWebViewEventEmitter::OnMessage data = { .url = std::string([[dictionary valueForKey:@"url"] UTF8String]), .lockIdentifier = [[dictionary valueForKey:@"lockIdentifier"] doubleValue], @@ -135,7 +137,8 @@ - (instancetype)initWithFrame:(CGRect)frame .canGoForward = static_cast([[dictionary valueForKey:@"canGoForward"] boolValue]), .loading = static_cast([[dictionary valueForKey:@"loading"] boolValue]), .data = std::string([[dictionary valueForKey:@"data"] UTF8String]), - .isMainFrame = static_cast([[dictionary valueForKey:@"isMainFrame"] boolValue]) + .isMainFrame = static_cast([[dictionary valueForKey:@"isMainFrame"] boolValue]), + .topFrameUrl = std::string([topFrameUrl UTF8String], [topFrameUrl lengthOfBytesUsingEncoding:NSUTF8StringEncoding]) }; webViewEventEmitter->onMessage(data); } diff --git a/apple/RNCWebViewImpl.m b/apple/RNCWebViewImpl.m index d497849cb..ea6024246 100644 --- a/apple/RNCWebViewImpl.m +++ b/apple/RNCWebViewImpl.m @@ -788,6 +788,7 @@ - (void)userContentController:(WKUserContentController *)userContentController NSMutableDictionary *event = [self baseEvent]; [event addEntriesFromDictionary: @{@"data": message.body}]; [event addEntriesFromDictionary: @{@"url": message.frameInfo.request.URL.absoluteString}]; + [event addEntriesFromDictionary: @{@"topFrameUrl": _webView.URL.absoluteString ?: @""}]; [event addEntriesFromDictionary: @{@"isMainFrame": @(isMainFrame)}]; _onMessage(event); } diff --git a/src/RNCWebViewNativeComponent.ts b/src/RNCWebViewNativeComponent.ts index ff9ee501f..9d50dc614 100644 --- a/src/RNCWebViewNativeComponent.ts +++ b/src/RNCWebViewNativeComponent.ts @@ -30,6 +30,7 @@ export type WebViewMessageEvent = Readonly<{ lockIdentifier: Double; data: string; isMainFrame?: boolean; + topFrameUrl?: string; }>; export type WebViewOpenWindowEvent = Readonly<{ targetUrl: string; diff --git a/src/WebViewTypes.ts b/src/WebViewTypes.ts index 1e2dadd0d..9eb2ab725 100644 --- a/src/WebViewTypes.ts +++ b/src/WebViewTypes.ts @@ -111,6 +111,7 @@ export type DecelerationRateConstant = 'normal' | 'fast'; export interface WebViewMessage extends WebViewNativeEvent { data: string; isMainFrame?: boolean; + topFrameUrl?: string; } export interface WebViewError extends WebViewNativeEvent {