Prevent WebView iframe loads from updating source (#3107)

* Prevent WebView iframe loads from updating source

* Use request type directly from the library that provides this param

---------

Co-authored-by: Johannes Klein <johannes.t.klein@gmail.com>
This commit is contained in:
Kirk van Gorkom
2025-10-09 05:26:10 -07:00
committed by GitHub
parent b0ba638ecc
commit 2e08467692
2 changed files with 57 additions and 7 deletions

View File

@@ -12,6 +12,7 @@ import React, { useEffect, useState } from "react";
import { Linking } from "react-native";
import { EventRegister } from "react-native-event-listeners";
import WebView from "react-native-webview";
import type { ShouldStartLoadRequest } from "react-native-webview/lib/WebViewTypes";
import { log } from "sharedHelpers/logger";
import { composeEmail } from "sharedHelpers/mail";
import { useFontScale } from "sharedHooks";
@@ -71,13 +72,8 @@ type WebViewSource = {
}
}
type WebViewRequest = {
url: string;
navigationType: "click" | "other"
}
export function onShouldStartLoadWithRequest(
request: WebViewRequest,
request: ShouldStartLoadRequest,
source: WebViewSource,
params: FullPageWebViewParams,
setSource?: ( source: WebViewSource ) => void
@@ -144,6 +140,22 @@ export function onShouldStartLoadWithRequest(
return true;
}
const isTopLevelNavigation = ( ) => {
if ( typeof request.isTopFrame === "boolean" ) {
return request.isTopFrame;
}
if ( request.mainDocumentURL ) {
return request.mainDocumentURL === request.url;
}
return true;
};
if ( !isTopLevelNavigation( ) ) {
return true;
}
// Note: this will cause infinite re-renders if the page has iframes
setSource( { ...source, uri: request.url } );
return true;
@@ -223,7 +235,7 @@ const FullPageWebView = ( ) => {
className="h-full w-full flex-1"
source={source}
onShouldStartLoadWithRequest={
( request: WebViewRequest ) => onShouldStartLoadWithRequest(
request => onShouldStartLoadWithRequest(
request,
source,
params,

View File

@@ -68,5 +68,43 @@ describe( "FullPageWebView", ( ) => {
expect( Linking.openURL ).not.toHaveBeenCalled( );
} );
} );
describe( "setSource", ( ) => {
it( "should update the source when navigating the top frame", ( ) => {
const url = "https://www.inaturalist.org";
const destination = "https://www.inaturalist.org/observations";
const request = {
url: destination,
mainDocumentURL: destination,
isTopFrame: true
};
const source = { uri: url };
const routeParams = { initialUrl: url };
const setSource = jest.fn();
expect(
onShouldStartLoadWithRequest( request, source, routeParams, setSource )
).toBeTruthy();
expect( setSource ).toHaveBeenCalledWith( { ...source, uri: destination } );
} );
it( "should not update the source for iframe requests", ( ) => {
const url = "https://www.inaturalist.org";
const iframeUrl = "https://www.inaturalist.org/embed";
const request = {
url: iframeUrl,
mainDocumentURL: url,
isTopFrame: false
};
const source = { uri: url };
const routeParams = { initialUrl: url };
const setSource = jest.fn();
expect(
onShouldStartLoadWithRequest( request, source, routeParams, setSource )
).toBeTruthy();
expect( setSource ).not.toHaveBeenCalled();
} );
} );
} );
} );