react-native-webview: Links with target="_blank" do not trigger onShouldStartLoadWithRequest

Bug description:

On Android, elements with target=“_blank” do not trigger onShouldStartLoadWithRequest. Absolute links will immediately open in the browser. Relative links don’t do anything at all (unless you provide a baseUrl, in which case they will be immediately opened in the browser).

To Reproduce: Following example code does not call onShouldStartLoadWithRequest for links with blank target.

import * as React from "react";
import { SafeAreaView } from "react-native";
import WebView from "react-native-webview";
import { ShouldStartLoadRequest } from "react-native-webview/lib/WebViewTypes";

export default function App() {
  const htmlContent = `
    <!DOCTYPE html>
    <html>
      <head>
        <style type="text/css">
          body {
            display: flex;
            flex-direction: column;
          }
        </style>
        <meta http-equiv="content-type" content="text/html; charset=utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
      </head>
      <body>
        <a href="https://github.com">Absolute link</a>
        <a href="https://github.com" target="_blank">Absolute link with blank target</a>
        <a href="/react-native-webview">Relative link</a>
        <a href="/react-native-webview" target="_blank">Relative link with blank target</a>
      </body>
    </html>
  `;

  const handleShoudStartLoadingWithRequest = (request: ShouldStartLoadRequest) => {
    console.log("shouldStartLoadWithRequest", request);

    return false;
  };

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <WebView
        originWhitelist={["*"]}
        onShouldStartLoadWithRequest={handleShoudStartLoadingWithRequest}
        source={{ html: htmlContent }}
        style={{ flex: 1, height: 100 }}
      />
    </SafeAreaView>
  );
}

I added the following piece of JS on the page, and then it does work:

<script>
  // Need to remove target=_blank on links or onShoudStartLoadingWithRequest doesnt get called on Android
  Array.from(document.querySelectorAll('a[target="_blank"]'))
  .forEach(link => link.removeAttribute('target'));
</script>

Expected behavior: I expect onShouldStartLoadWithRequest to be called for absolute/ relative links in all cases, irrespective of their target.

Environment:

  • OS: Android
  • OS version: 11
  • react-native version: 0.63.4
  • react-native-webview version: 11.2.1

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 10
  • Comments: 16

Most upvoted comments

I’ve found a better way to make it work, I removed all that previous workaround and set the setSupportMultipleWindows to false, this lead me into two other problems, first was that even if i return a false to the onShouldStartLoadWithRequest the webview was redirected to the next page, so i added a webViewRef?.stopLoading() and all is working fine now. But, the other problem i had was with a vulnerability that setting setSupportMultipleWindows to false exposes, so i just tested if the URL from navigation on included a base URL. I couldn’t make the originWhitelist work, it made a lot of links stop working in the webview even if it matches with the whitelist URIs.

it solved in my case onShouldStartLoadWithRequest={(request) => {

                    // prevent load request about : blank 
                    if(request.url == 'about:blank') return false;

}

The code below is my solution. It works for me.

          onShouldStartLoadWithRequest={(request) => {
            if(request.url.indexOf(consts.baseUrl) == -1 ){  
              Linking.openURL(request.url);
            }
          }}

it solved in my case onShouldStartLoadWithRequest={(request) => {

                    // prevent load request about : blank 
                    if(request.url == 'about:blank') return false;

}

How do you solved it if onShouldStartLoadWithRequest is not even being triggered? Or setting setSupportMultipleWindows to false and doing that mitigates the vulnerability?

Anyway, i have the same problem.

I’m having the same issue. I’m also using react-native 0.64. Setting setSupportMultipleWindows to false, makes no difference for me, but if I downgrade to 10.10.2 things start to work.

@RZsam, have you had any progress on this issue?

You can use “injectedJavaScript” to handle the “a” target’s “click” event.

For example:

<WebView
          source={{ uri: h5 }}
          onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
          injectedJavaScript={`
           (function(){
             document.body.addEventListener('click', function () {
                const target = event.target || event.srcElement;
                if (target.nodeName.toLocaleLowerCase() === 'a') {
                    if (event.preventDefault) {
                        event.preventDefault();
                    } else {
                        window.event.returnValue = true;
                    }
                    const url = target.getAttribute("href")
                    window.location.href = url
                }
            });
           })()
            `}
        />

It will change the “_blank” to “self”, and trigger the “onShouldStartLoadWithRequest” method