Skip to content

originWhitelist does not behave the same in iOS & Android #3467

@arieloO

Description

@arieloO

Bug description:

I noticed originWhitelist does not behave the same in iOS and Android.

In Android originWhitelist works as expected, preventing navigation to other domains within the webview.
But in iOS it also filters out all non-navigation related requests (medias, embedded content, tracking).

There is a workaround I found in issues and comments from the repo (see #541, #1505), using onShouldStartLoadWithRequest & navigationType === "click" to handle wether or not to load a request.
But this does not work for Android, as the navigationType(NativeSyntheticEvent), exposed in onShouldStartLoadWithRequest only exists in iOS. So that we cannot filter navigations on user clicks from all other requests (medias, embedded content, tracking).

To Reproduce:

const DOMAIN_WHITELIST = ['github.com'];
const ORIGIN_WHITELIST = ['https://github.com/'];

const WebviewWrapper = () => {
  const webViewRef = useRef<WebView>(null);

  /* ... */

  const handleLoadRequest = (event: ShouldStartLoadRequest) => {
    const { url, navigationType } = event;
    const urlHostName = new URL(url).hostname;

    if (!DOMAIN_WHITELIST.includes(urlHostName) && navigationType === 'click') {
      Linking.canOpenURL(url)
        .then((supported) => {
          if (supported) {
            Linking.openURL(url);
          } else {
            Alert.alert('Error', `Could not open the following URL: ${url}`);
          }
        })
        .catch(() => {
          Alert.alert('Error', `Could not open the following URL: ${url}`);
        });

      return false; // Prevent WebView from loading the URL
    }
    return true;
  };

  return (
    <WebView
      ref={webViewRef}
      style={styles.webview}
      startInLoadingState
      domStorageEnabled
      allowsBackForwardNavigationGestures
      onNavigationStateChange={onNavigationStateChange}
      onShouldStartLoadWithRequest={handleLoadRequest} // in Android this is blocking all requests as Android does not expose "navigationType"
      mixedContentMode='compatibility'
      originWhitelist={ORIGIN_WHITELIST} // in iOS this will not let cdn images and embedded content to be requested
      onContentProcessDidTerminate={() => webViewRef.current?.reload()}
    />
  );
};

This is my current workaround for it:

<WebView
  //...
  onShouldStartLoadWithRequest={
    Platform.OS === 'ios' ? handleLoadRequest : undefined
  }
  originWhitelist={Platform.OS === 'android' ? ORIGIN_WHITELIST : undefined}
  //...
/>

I do not get how and why it is not behaving the same way, the source code where originWhitelist and onShouldStartLoadWithRequest are being used looks pretty simple :

const createOnShouldStartLoadWithRequest = (

Seems like the method is not called on the same events depending on the platform. 🤔

Expected behavior:

I would expect originWhitelist to behave the same for each platform: only blocking navigation and not blocking requests for cdn images, embedded content etc... So we wouldn't need to handle iOS requests in onShouldStartLoadWithRequest, for basic usages.

Or maybe have separated whitelists to distinguish navigation from all other requests ? 🤔

If this is an expected/known behavior, that depends on platform specific constraints, it would be great to add some documentation for it.

Environment:

  • OS: iOS & Android
  • OS version: iOS 17 & SDK 32
  • react-native version: 0.73.6
  • react-native-webview version: 13.6.4

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions