No Description

WebViewShared.tsx 2.6KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import escapeStringRegexp from 'escape-string-regexp';
  2. import React from 'react';
  3. import { Linking, View, ActivityIndicator, Text } from 'react-native';
  4. import {
  5. WebViewNavigationEvent,
  6. OnShouldStartLoadWithRequest,
  7. } from './WebViewTypes';
  8. import styles from './WebView.styles';
  9. const defaultOriginWhitelist = ['http://*', 'https://*'];
  10. const extractOrigin = (url: string): string => {
  11. const result = /^[A-Za-z][A-Za-z0-9+\-.]+:(\/\/)?[^/]*/.exec(url);
  12. return result === null ? '' : result[0];
  13. };
  14. const originWhitelistToRegex = (originWhitelist: string): string =>
  15. `^${escapeStringRegexp(originWhitelist).replace(/\\\*/g, '.*')}`;
  16. const passesWhitelist = (
  17. compiledWhitelist: readonly string[],
  18. url: string,
  19. ) => {
  20. const origin = extractOrigin(url);
  21. return compiledWhitelist.some(x => new RegExp(x).test(origin));
  22. };
  23. const compileWhitelist = (
  24. originWhitelist: readonly string[],
  25. ): readonly string[] =>
  26. ['about:blank', ...(originWhitelist || [])].map(originWhitelistToRegex);
  27. const createOnShouldStartLoadWithRequest = (
  28. loadRequest: (
  29. shouldStart: boolean,
  30. url: string,
  31. lockIdentifier: number,
  32. ) => void,
  33. originWhitelist: readonly string[],
  34. onShouldStartLoadWithRequest?: OnShouldStartLoadWithRequest,
  35. ) => {
  36. return ({ nativeEvent }: WebViewNavigationEvent) => {
  37. let shouldStart = true;
  38. const { url, lockIdentifier } = nativeEvent;
  39. if (!passesWhitelist(compileWhitelist(originWhitelist), url)) {
  40. Linking.canOpenURL(url).then((supported) => {
  41. if (supported) {
  42. return Linking.openURL(url);
  43. }
  44. console.warn(`Can't open url: ${url}`);
  45. return undefined;
  46. }).catch(e => {
  47. console.warn('Error opening URL: ', e);
  48. });
  49. shouldStart = false;
  50. } else if (onShouldStartLoadWithRequest) {
  51. shouldStart = onShouldStartLoadWithRequest(nativeEvent);
  52. }
  53. loadRequest(shouldStart, url, lockIdentifier);
  54. };
  55. };
  56. const defaultRenderLoading = () => (
  57. <View style={styles.loadingOrErrorView}>
  58. <ActivityIndicator />
  59. </View>
  60. );
  61. const defaultRenderError = (
  62. errorDomain: string | undefined,
  63. errorCode: number,
  64. errorDesc: string,
  65. ) => (
  66. <View style={styles.loadingOrErrorView}>
  67. <Text style={styles.errorTextTitle}>Error loading page</Text>
  68. <Text style={styles.errorText}>{`Domain: ${errorDomain}`}</Text>
  69. <Text style={styles.errorText}>{`Error Code: ${errorCode}`}</Text>
  70. <Text style={styles.errorText}>{`Description: ${errorDesc}`}</Text>
  71. </View>
  72. );
  73. export {
  74. defaultOriginWhitelist,
  75. createOnShouldStartLoadWithRequest,
  76. defaultRenderLoading,
  77. defaultRenderError,
  78. };