Don't allow camera and mic permissions by default. Notify user about permission request

This commit is contained in:
Volodymyr Kozieiev
2020-08-03 11:18:45 +03:00
parent 3bef57fcf8
commit f7a3d58b2f
23 changed files with 264 additions and 78 deletions
@@ -93,6 +93,7 @@ import com.reactnativecommunity.webview.events.TopLoadingProgressEvent;
import com.reactnativecommunity.webview.events.TopLoadingStartEvent;
import com.reactnativecommunity.webview.events.TopMessageEvent;
import com.reactnativecommunity.webview.events.TopShouldStartLoadWithRequestEvent;
import com.reactnativecommunity.webview.events.TopPermissionRequestEvent;
import org.json.JSONException;
import org.json.JSONObject;
@@ -143,6 +144,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
public static final int COMMAND_INJECT_JAVASCRIPT = 6;
public static final int COMMAND_LOAD_URL = 7;
public static final int COMMAND_FOCUS = 8;
public static final int COMMAND_ANSWER_PERMISSION_REQUEST = 9;
// android commands
public static final int COMMAND_CLEAR_FORM_DATA = 1000;
@@ -720,6 +722,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
export.put(TopShouldStartLoadWithRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShouldStartLoadWithRequest"));
export.put(ScrollEventType.getJSEventName(ScrollEventType.SCROLL), MapBuilder.of("registrationName", "onScroll"));
export.put(TopHttpErrorEvent.EVENT_NAME, MapBuilder.of("registrationName", "onHttpError"));
export.put(TopPermissionRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onPermissionRequest"));
return export;
}
@@ -733,6 +736,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
.put("stopLoading", COMMAND_STOP_LOADING)
.put("postMessage", COMMAND_POST_MESSAGE)
.put("injectJavaScript", COMMAND_INJECT_JAVASCRIPT)
.put("answerPermissionRequest", COMMAND_ANSWER_PERMISSION_REQUEST)
.put("loadUrl", COMMAND_LOAD_URL)
.put("requestFocus", COMMAND_FOCUS)
.put("clearFormData", COMMAND_CLEAR_FORM_DATA)
@@ -779,6 +783,23 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
case COMMAND_INJECT_JAVASCRIPT:
RNCWebView reactWebView = (RNCWebView) root;
reactWebView.evaluateJavascriptWithFallback(args.getString(0));
break;
case COMMAND_ANSWER_PERMISSION_REQUEST:
if (args == null || args.size() < 1) {
throw new RuntimeException("Arguments for answerPermissionRequest are null!");
}
boolean answer = args.getBoolean(0);
ArrayList<String> resources = new ArrayList<String>();
for(int i=1; i<args.size(); ++i) {
resources.add(args.getString(i));
}
RNCWebChromeClient client = (RNCWebChromeClient) root.getWebChromeClient();
if(null != client) {
client.answerPermissionRequest(answer, resources.toArray(new String[resources.size()]));
}
break;
case COMMAND_LOAD_URL:
if (args == null) {
@@ -1300,6 +1321,12 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
protected View mVideoView;
protected WebChromeClient.CustomViewCallback mCustomViewCallback;
/**
* This field stores the PermissionRequest from the web application until it is allowed
* or denied by user.
*/
private PermissionRequest mPermissionRequest;
protected RNCWebView.ProgressChangedFilter progressChangedFilter = null;
public RNCWebChromeClient(ReactContext reactContext, WebView webView) {
@@ -1319,40 +1346,47 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
return true;
}
public void answerPermissionRequest(boolean allowed, String[] resources) {
if(null == mPermissionRequest )
return;
if (allowed) {
mPermissionRequest.grant(resources);
} else {
mPermissionRequest.deny();
}
mPermissionRequest = null;
}
// This method is called when the permission request is canceled by the web content.
@Override
public void onPermissionRequestCanceled(PermissionRequest request) {
// We dismiss the prompt UI here as the request is no longer valid.
mPermissionRequest = null;
}
// Fix WebRTC permission request error.
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onPermissionRequest(final PermissionRequest request) {
mPermissionRequest = request;
String[] requestedResources = request.getResources();
ArrayList<String> permissions = new ArrayList<>();
ArrayList<String> grantedPermissions = new ArrayList<String>();
WebView wv = (WebView) mWebView;
WritableMap event = Arguments.createMap();
WritableNativeArray params = new WritableNativeArray();
for (int i = 0; i < requestedResources.length; i++) {
if (requestedResources[i].equals(PermissionRequest.RESOURCE_AUDIO_CAPTURE)) {
permissions.add(Manifest.permission.RECORD_AUDIO);
} else if (requestedResources[i].equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
permissions.add(Manifest.permission.CAMERA);
}
// TODO: RESOURCE_MIDI_SYSEX, RESOURCE_PROTECTED_MEDIA_ID.
params.pushString(requestedResources[i]);
}
event.putArray("resources", params);
for (int i = 0; i < permissions.size(); i++) {
if (ContextCompat.checkSelfPermission(mReactContext, permissions.get(i)) != PackageManager.PERMISSION_GRANTED) {
continue;
}
if (permissions.get(i).equals(Manifest.permission.RECORD_AUDIO)) {
grantedPermissions.add(PermissionRequest.RESOURCE_AUDIO_CAPTURE);
} else if (permissions.get(i).equals(Manifest.permission.CAMERA)) {
grantedPermissions.add(PermissionRequest.RESOURCE_VIDEO_CAPTURE);
}
}
if (grantedPermissions.isEmpty()) {
request.deny();
} else {
String[] grantedPermissionsArray = new String[grantedPermissions.size()];
grantedPermissionsArray = grantedPermissions.toArray(grantedPermissionsArray);
request.grant(grantedPermissionsArray);
}
dispatchEvent(
wv,
new TopPermissionRequestEvent(
wv.getId(),
event));
}
@Override
@@ -0,0 +1,24 @@
package com.reactnativecommunity.webview.events
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.events.Event
import com.facebook.react.uimanager.events.RCTEventEmitter
/**
* Event emitted when there is an error in loading.
*/
class TopPermissionRequestEvent(viewId: Int, private val mEventData: WritableMap) : Event<TopPermissionRequestEvent>(viewId) {
companion object {
const val EVENT_NAME = "topPermissionRequest"
}
override fun getEventName(): String = EVENT_NAME
override fun canCoalesce(): Boolean = false
override fun getCoalescingKey(): Short = 0
override fun dispatch(rctEventEmitter: RCTEventEmitter) {
rctEventEmitter.receiveEvent(viewTag, EVENT_NAME, mEventData)
}
}
+14
View File
@@ -10,6 +10,7 @@ import {
Platform,
} from 'react-native';
import Permission from './examples/Permission';
import Alerts from './examples/Alerts';
import Scrolling from './examples/Scrolling';
import Background from './examples/Background';
@@ -19,6 +20,14 @@ import Injection from './examples/Injection';
import LocalPageLoad from './examples/LocalPageLoad';
const TESTS = {
Permission: {
title: 'Permission',
testId: 'permission',
description: 'Permission tests',
render() {
return <Permission />;
},
},
Alerts: {
title: 'Alerts',
testId: 'alerts',
@@ -113,6 +122,11 @@ export default class App extends Component<Props, State> {
</TouchableOpacity>
<View style={styles.testPickerContainer}>
<Button
testID="testType_permission"
title="Permission"
onPress={() => this._changeTest('Permission')}
/>
<Button
testID="testType_alerts"
title="Alerts"
+27
View File
@@ -0,0 +1,27 @@
import React, {Component} from 'react';
import {Text, View} from 'react-native';
import WebView from 'react-native-webview';
type Props = {};
type State = {};
export default class Permission extends Component<Props, State> {
state = {};
render() {
return (
<View style={{ height: 120 }}>
<WebView
ref={(ref) => (this.webview = ref)}
onPermissionRequest={(event) => {
console.log("!!! JS: onPermissionRequest, event: ", event.nativeEvent);
this.webview.answerPermissionRequest(false, event.nativeEvent.resources );
}}
source={{uri: 'https://fatal0.netlify.app/android/webviewvideo.html'}}
automaticallyAdjustContentInsets={false}
/>
</View>
);
}
}
+11 -8
View File
@@ -1,5 +1,5 @@
import React from 'react';
import { AndroidWebViewProps, NativeWebViewAndroid, State } from './WebViewTypes';
import { WebViewErrorEvent, WebViewHttpErrorEvent, WebViewMessageEvent, WebViewNavigationEvent, WebViewProgressEvent, WebViewPermissionEvent, AndroidWebViewProps, NativeWebViewAndroid, State } from './WebViewTypes';
/**
* Renders a native WebView.
*/
@@ -34,6 +34,7 @@ declare class WebView extends React.Component<AndroidWebViewProps, State> {
clearHistory: number;
clearCache: number;
clearFormData: number;
answerPermissionRequest: number;
};
goForward: () => void;
goBack: () => void;
@@ -51,21 +52,23 @@ declare class WebView extends React.Component<AndroidWebViewProps, State> {
* functionality, look into postMessage/onMessage.
*/
injectJavaScript: (data: string) => void;
answerPermissionRequest: (allow: boolean, resources: string[]) => void;
/**
* We return an event with a bunch of fields including:
* url, title, loading, canGoBack, canGoForward
*/
updateNavigationState: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNavigation>) => void;
updateNavigationState: (event: WebViewNavigationEvent) => void;
/**
* Returns the native `WebView` node.
*/
getWebViewHandle: () => number;
onLoadingStart: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNavigation>) => void;
onLoadingError: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewError>) => void;
onHttpError: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewHttpError>) => void;
onLoadingFinish: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNavigation>) => void;
onMessage: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewMessage>) => void;
onLoadingProgress: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNativeProgressEvent>) => void;
onLoadingStart: (event: WebViewNavigationEvent) => void;
onLoadingError: (event: WebViewErrorEvent) => void;
onHttpError: (event: WebViewHttpErrorEvent) => void;
onLoadingFinish: (event: WebViewNavigationEvent) => void;
onMessage: (event: WebViewMessageEvent) => void;
onPermissionRequest: (event: WebViewPermissionEvent) => void;
onLoadingProgress: (event: WebViewProgressEvent) => void;
onShouldStartLoadWithRequestCallback: (shouldStart: boolean, url: string) => void;
render(): JSX.Element;
}
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"WebView.android.d.ts","sourceRoot":"","sources":["../src/WebView.android.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAsB1B,OAAO,EAML,mBAAmB,EACnB,oBAAoB,EACpB,KAAK,EAEN,MAAM,gBAAgB,CAAC;AAgBxB;;GAEG;AACH,cAAM,OAAQ,SAAQ,KAAK,CAAC,SAAS,CAAC,mBAAmB,EAAE,KAAK,CAAC;IAC/D,MAAM,CAAC,YAAY;;;;;;;;;;;MAWjB;IAEF,MAAM,CAAC,qBAAqB,qBAG1B;IAEF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,KAAK,EAAE,KAAK,CAGV;IAGF,UAAU,wCAA2C;IAErD,mBAAmB,SAA0C;IAE7D,iBAAiB,aAEf;IAEF,WAAW;;;;;;;;;;;;MAA+D;IAE1E,SAAS,aAMP;IAEF,MAAM,aAMJ;IAEF,MAAM,aASJ;IAEF,WAAW,aAMT;IAEF,YAAY,aAMV;IAEF,WAAW,yBAMT;IAEF,aAAa,aAMZ;IAED,UAAU,sCAMR;IAEF,YAAY,aAMV;IAEF;;;;;OAKG;IACH,gBAAgB,yBAMd;IAEF;;;OAGG;IACH,qBAAqB,2GAInB;IAEF;;OAEG;IACH,gBAAgB,eAId;IAEF,cAAc,2GAQZ;IAEF,cAAc,sGAeZ;IAEF,WAAW,0GAKV;IAED,eAAe,2GAeb;IAEF,SAAS,wGAKP;IAEF,iBAAiB,oHAcf;IAEF,oCAAoC,8CAWlC;IAEF,MAAM;CAmFP;AAED,eAAe,OAAO,CAAC"}
{"version":3,"file":"WebView.android.d.ts","sourceRoot":"","sources":["../src/WebView.android.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAsB1B,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,KAAK,EAEN,MAAM,gBAAgB,CAAC;AAgBxB;;GAEG;AACH,cAAM,OAAQ,SAAQ,KAAK,CAAC,SAAS,CAAC,mBAAmB,EAAE,KAAK,CAAC;IAC/D,MAAM,CAAC,YAAY;;;;;;;;;;;MAWjB;IAEF,MAAM,CAAC,qBAAqB,qBAG1B;IAEF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,KAAK,EAAE,KAAK,CAGV;IAGF,UAAU,wCAA2C;IAErD,mBAAmB,SAA0C;IAE7D,iBAAiB,aAEf;IAEF,WAAW;;;;;;;;;;;;;MAA+D;IAE1E,SAAS,aAMP;IAEF,MAAM,aAMJ;IAEF,MAAM,aASJ;IAEF,WAAW,aAMT;IAEF,YAAY,aAMV;IAEF,WAAW,yBAMT;IAEF,aAAa,aAMZ;IAED,UAAU,sCAMR;IAEF,YAAY,aAMV;IAEF;;;;;OAKG;IACH,gBAAgB,yBAMd;IAEF,uBAAuB,gDAMtB;IAED;;;OAGG;IACH,qBAAqB,0CAInB;IAEF;;OAEG;IACH,gBAAgB,eAId;IAEF,cAAc,0CAQZ;IAEF,cAAc,qCAeZ;IAEF,WAAW,yCAKV;IAED,eAAe,0CAeb;IAEF,SAAS,uCAKP;IAEF,mBAAmB,0CAKlB;IAED,iBAAiB,wCAcf;IAEF,oCAAoC,8CAWlC;IAEF,MAAM;CAoFP;AAED,eAAe,OAAO,CAAC"}
+17 -1
View File
@@ -58,6 +58,13 @@ var __rest = (this && this.__rest) || function (s, e) {
}
return t;
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
import React from 'react';
import { Image, requireNativeComponent, UIManager as NotTypedUIManager, View, NativeModules, findNodeHandle, } from 'react-native';
import BatchedBridge from 'react-native/Libraries/BatchedBridge/BatchedBridge';
@@ -128,6 +135,9 @@ var WebView = /** @class */ (function (_super) {
_this.injectJavaScript = function (data) {
UIManager.dispatchViewManagerCommand(_this.getWebViewHandle(), _this.getCommands().injectJavaScript, [data]);
};
_this.answerPermissionRequest = function (allow, resources) {
UIManager.dispatchViewManagerCommand(_this.getWebViewHandle(), _this.getCommands().answerPermissionRequest, __spreadArrays([allow], (resources || [])));
};
/**
* We return an event with a bunch of fields including:
* url, title, loading, canGoBack, canGoForward
@@ -197,6 +207,12 @@ var WebView = /** @class */ (function (_super) {
onMessage(event);
}
};
_this.onPermissionRequest = function (event) {
var onPermissionRequest = _this.props.onPermissionRequest;
if (onPermissionRequest) {
onPermissionRequest(event);
}
};
_this.onLoadingProgress = function (event) {
var onLoadProgress = _this.props.onLoadProgress;
var progress = event.nativeEvent.progress;
@@ -247,7 +263,7 @@ var WebView = /** @class */ (function (_super) {
var onShouldStartLoadWithRequest = createOnShouldStartLoadWithRequest(this.onShouldStartLoadWithRequestCallback,
// casting cause it's in the default props
originWhitelist, onShouldStartLoadWithRequestProp);
var webView = (<NativeWebView key="webViewKey" {...otherProps} messagingEnabled={typeof onMessage === 'function'} messagingModuleName={this.messagingModuleName} onLoadingError={this.onLoadingError} onLoadingFinish={this.onLoadingFinish} onLoadingProgress={this.onLoadingProgress} onLoadingStart={this.onLoadingStart} onHttpError={this.onHttpError} onMessage={this.onMessage} onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} ref={this.webViewRef}
var webView = (<NativeWebView key="webViewKey" {...otherProps} messagingEnabled={typeof onMessage === 'function'} messagingModuleName={this.messagingModuleName} onLoadingError={this.onLoadingError} onLoadingFinish={this.onLoadingFinish} onLoadingProgress={this.onLoadingProgress} onPermissionRequest={this.onPermissionRequest} onLoadingStart={this.onLoadingStart} onHttpError={this.onHttpError} onMessage={this.onMessage} onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} ref={this.webViewRef}
// TODO: find a better way to type this.
source={resolveAssetSource(source)} style={webViewStyles} {...nativeConfig.props}/>);
return (<View style={webViewContainerStyle}>
+4 -1
View File
@@ -1,4 +1,7 @@
import { WebView } from 'react-native';
import React from 'react';
import { IOSWebViewProps, AndroidWebViewProps } from './WebViewTypes';
export declare type WebViewProps = IOSWebViewProps & AndroidWebViewProps;
declare const WebView: React.FunctionComponent<WebViewProps>;
export { WebView };
export default WebView;
//# sourceMappingURL=WebView.d.ts.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"WebView.d.ts","sourceRoot":"","sources":["../src/WebView.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,OAAO,EAAE,CAAC;AACnB,eAAe,OAAO,CAAC"}
{"version":3,"file":"WebView.d.ts","sourceRoot":"","sources":["../src/WebView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAEtE,oBAAY,YAAY,GAAG,eAAe,GAAG,mBAAmB,CAAC;AAMjE,QAAA,MAAM,OAAO,EAAE,KAAK,CAAC,iBAAiB,CAAC,YAAY,CAMlD,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC;AACnB,eAAe,OAAO,CAAC"}
+9 -9
View File
@@ -1,5 +1,5 @@
import React from 'react';
import { IOSWebViewProps, NativeWebViewIOS, State } from './WebViewTypes';
import { WebViewErrorEvent, WebViewHttpErrorEvent, WebViewMessageEvent, WebViewNavigationEvent, WebViewProgressEvent, WebViewTerminatedEvent, IOSWebViewProps, NativeWebViewIOS, State } from './WebViewTypes';
declare class WebView extends React.Component<IOSWebViewProps, State> {
static defaultProps: {
javaScriptEnabled: boolean;
@@ -62,19 +62,19 @@ declare class WebView extends React.Component<IOSWebViewProps, State> {
* We return an event with a bunch of fields including:
* url, title, loading, canGoBack, canGoForward
*/
updateNavigationState: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNavigation>) => void;
updateNavigationState: (event: WebViewNavigationEvent) => void;
/**
* Returns the native `WebView` node.
*/
getWebViewHandle: () => number;
onLoadingStart: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNavigation>) => void;
onLoadingError: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewError>) => void;
onHttpError: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewHttpError>) => void;
onLoadingFinish: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNavigation>) => void;
onMessage: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewMessage>) => void;
onLoadingProgress: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNativeProgressEvent>) => void;
onLoadingStart: (event: WebViewNavigationEvent) => void;
onLoadingError: (event: WebViewErrorEvent) => void;
onHttpError: (event: WebViewHttpErrorEvent) => void;
onLoadingFinish: (event: WebViewNavigationEvent) => void;
onMessage: (event: WebViewMessageEvent) => void;
onLoadingProgress: (event: WebViewProgressEvent) => void;
onShouldStartLoadWithRequestCallback: (shouldStart: boolean, _url: string, lockIdentifier: number) => void;
onContentProcessDidTerminate: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNativeEvent>) => void;
onContentProcessDidTerminate: (event: WebViewTerminatedEvent) => void;
componentDidUpdate(prevProps: IOSWebViewProps): void;
showRedboxOnPropChanges(prevProps: IOSWebViewProps, propName: keyof IOSWebViewProps): void;
render(): JSX.Element;
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"WebView.ios.d.ts","sourceRoot":"","sources":["../src/WebView.ios.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAkB1B,OAAO,EAOL,eAAe,EAEf,gBAAgB,EAEhB,KAAK,EAEN,MAAM,gBAAgB,CAAC;AAyBxB,cAAM,OAAQ,SAAQ,KAAK,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,CAAC;IAC3D,MAAM,CAAC,YAAY;;;;;MAKjB;IAEF,MAAM,CAAC,qBAAqB,yBAG1B;IAEF,KAAK,EAAE,KAAK,CAGV;IAEF,UAAU,oCAAuC;IAGjD,WAAW;;;;;;;;;MAA+D;IAE1E;;OAEG;IACH,SAAS,aAMP;IAEF;;OAEG;IACH,MAAM,aAMJ;IAEF;;OAEG;IACH,MAAM,aAOJ;IAEF;;OAEG;IACH,WAAW,aAMT;IAEF;;OAEG;IACH,YAAY,aAMV;IAEF;;;;;;;;;OASG;IACH,WAAW,yBAMT;IAEF;;;;;OAKG;IACH,gBAAgB,yBAMd;IAEF;;;OAGG;IACH,qBAAqB,2GAInB;IAEF;;OAEG;IACH,gBAAgB,eAId;IAEF,cAAc,2GAMZ;IAEF,cAAc,sGAeZ;IAEF,WAAW,0GAKV;IAED,eAAe,2GAYb;IAEF,SAAS,wGAKP;IAEF,iBAAiB,oHAKf;IAEF,oCAAoC,uEAUlC;IAEF,4BAA4B,4GAK1B;IAEF,kBAAkB,CAAC,SAAS,EAAE,eAAe;IAO7C,uBAAuB,CACrB,SAAS,EAAE,eAAe,EAC1B,QAAQ,EAAE,MAAM,eAAe;IASjC,MAAM;CAqFP;AAED,eAAe,OAAO,CAAC"}
{"version":3,"file":"WebView.ios.d.ts","sourceRoot":"","sources":["../src/WebView.ios.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAkB1B,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EAEf,gBAAgB,EAEhB,KAAK,EAEN,MAAM,gBAAgB,CAAC;AAyBxB,cAAM,OAAQ,SAAQ,KAAK,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,CAAC;IAC3D,MAAM,CAAC,YAAY;;;;;MAKjB;IAEF,MAAM,CAAC,qBAAqB,yBAG1B;IAEF,KAAK,EAAE,KAAK,CAGV;IAEF,UAAU,oCAAuC;IAGjD,WAAW;;;;;;;;;MAA+D;IAE1E;;OAEG;IACH,SAAS,aAMP;IAEF;;OAEG;IACH,MAAM,aAMJ;IAEF;;OAEG;IACH,MAAM,aAOJ;IAEF;;OAEG;IACH,WAAW,aAMT;IAEF;;OAEG;IACH,YAAY,aAMV;IAEF;;;;;;;;;OASG;IACH,WAAW,yBAMT;IAEF;;;;;OAKG;IACH,gBAAgB,yBAMd;IAEF;;;OAGG;IACH,qBAAqB,0CAInB;IAEF;;OAEG;IACH,gBAAgB,eAId;IAEF,cAAc,0CAMZ;IAEF,cAAc,qCAeZ;IAEF,WAAW,yCAKV;IAED,eAAe,0CAYb;IAEF,SAAS,uCAKP;IAEF,iBAAiB,wCAKf;IAEF,oCAAoC,uEAUlC;IAEF,4BAA4B,0CAK1B;IAEF,kBAAkB,CAAC,SAAS,EAAE,eAAe;IAO7C,uBAAuB,CACrB,SAAS,EAAE,eAAe,EAC1B,QAAQ,EAAE,MAAM,eAAe;IASjC,MAAM;CAqFP;AAED,eAAe,OAAO,CAAC"}
+11 -2
View File
@@ -1,4 +1,13 @@
// This files provides compatibility without tree platform.
import { WebView } from 'react-native';
import React from 'react';
import { View } from 'react-native';
// This "dummy" WebView is to render something for unsupported platforms,
// like for example Expo SDK "web" platform. It matches the previous react-native
// implementation which is produced by Expo SDK 37.0.0.1 implementation, with
// similar interface than the native ones have.
var WebView = function () { return (<View style={{
alignSelf: 'flex-start',
borderColor: 'rgb(255, 0, 0)',
borderWidth: 1
}}/>); };
export { WebView };
export default WebView;
+9 -9
View File
@@ -1,5 +1,5 @@
import React from 'react';
import { MacOSWebViewProps, NativeWebViewMacOS, State } from './WebViewTypes';
import { WebViewErrorEvent, WebViewHttpErrorEvent, WebViewMessageEvent, WebViewNavigationEvent, WebViewProgressEvent, WebViewTerminatedEvent, MacOSWebViewProps, NativeWebViewMacOS, State } from './WebViewTypes';
declare class WebView extends React.Component<MacOSWebViewProps, State> {
static defaultProps: {
javaScriptEnabled: boolean;
@@ -62,19 +62,19 @@ declare class WebView extends React.Component<MacOSWebViewProps, State> {
* We return an event with a bunch of fields including:
* url, title, loading, canGoBack, canGoForward
*/
updateNavigationState: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNavigation>) => void;
updateNavigationState: (event: WebViewNavigationEvent) => void;
/**
* Returns the native `WebView` node.
*/
getWebViewHandle: () => number;
onLoadingStart: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNavigation>) => void;
onLoadingError: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewError>) => void;
onHttpError: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewHttpError>) => void;
onLoadingFinish: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNavigation>) => void;
onMessage: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewMessage>) => void;
onLoadingProgress: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNativeProgressEvent>) => void;
onLoadingStart: (event: WebViewNavigationEvent) => void;
onLoadingError: (event: WebViewErrorEvent) => void;
onHttpError: (event: WebViewHttpErrorEvent) => void;
onLoadingFinish: (event: WebViewNavigationEvent) => void;
onMessage: (event: WebViewMessageEvent) => void;
onLoadingProgress: (event: WebViewProgressEvent) => void;
onShouldStartLoadWithRequestCallback: (shouldStart: boolean, _url: string, lockIdentifier: number) => void;
onContentProcessDidTerminate: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNativeEvent>) => void;
onContentProcessDidTerminate: (event: WebViewTerminatedEvent) => void;
componentDidUpdate(prevProps: MacOSWebViewProps): void;
showRedboxOnPropChanges(prevProps: MacOSWebViewProps, propName: keyof MacOSWebViewProps): void;
render(): JSX.Element;
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"WebView.macos.d.ts","sourceRoot":"","sources":["../src/WebView.macos.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAkB1B,OAAO,EAOL,iBAAiB,EACjB,kBAAkB,EAElB,KAAK,EAEN,MAAM,gBAAgB,CAAC;AAcxB,cAAM,OAAQ,SAAQ,KAAK,CAAC,SAAS,CAAC,iBAAiB,EAAE,KAAK,CAAC;IAC7D,MAAM,CAAC,YAAY;;;;;MAKjB;IAEF,MAAM,CAAC,qBAAqB,yBAG1B;IAEF,KAAK,EAAE,KAAK,CAGV;IAEF,UAAU,sCAAyC;IAGnD,WAAW;;;;;;;;;MAA+D;IAE1E;;OAEG;IACH,SAAS,aAMP;IAEF;;OAEG;IACH,MAAM,aAMJ;IAEF;;OAEG;IACH,MAAM,aAOJ;IAEF;;OAEG;IACH,WAAW,aAMT;IAEF;;OAEG;IACH,YAAY,aAMV;IAEF;;;;;;;;;OASG;IACH,WAAW,yBAMT;IAEF;;;;;OAKG;IACH,gBAAgB,yBAMd;IAEF;;;OAGG;IACH,qBAAqB,2GAInB;IAEF;;OAEG;IACH,gBAAgB,eAId;IAEF,cAAc,2GAMZ;IAEF,cAAc,sGAeZ;IAEF,WAAW,0GAKV;IAED,eAAe,2GAYb;IAEF,SAAS,wGAKP;IAEF,iBAAiB,oHAKf;IAEF,oCAAoC,uEAUlC;IAEF,4BAA4B,4GAK1B;IAEF,kBAAkB,CAAC,SAAS,EAAE,iBAAiB;IAM/C,uBAAuB,CACrB,SAAS,EAAE,iBAAiB,EAC5B,QAAQ,EAAE,MAAM,iBAAiB;IASnC,MAAM;CA0EP;AAED,eAAe,OAAO,CAAC"}
{"version":3,"file":"WebView.macos.d.ts","sourceRoot":"","sources":["../src/WebView.macos.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAkB1B,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EAElB,KAAK,EAEN,MAAM,gBAAgB,CAAC;AAcxB,cAAM,OAAQ,SAAQ,KAAK,CAAC,SAAS,CAAC,iBAAiB,EAAE,KAAK,CAAC;IAC7D,MAAM,CAAC,YAAY;;;;;MAKjB;IAEF,MAAM,CAAC,qBAAqB,yBAG1B;IAEF,KAAK,EAAE,KAAK,CAGV;IAEF,UAAU,sCAAyC;IAGnD,WAAW;;;;;;;;;MAA+D;IAE1E;;OAEG;IACH,SAAS,aAMP;IAEF;;OAEG;IACH,MAAM,aAMJ;IAEF;;OAEG;IACH,MAAM,aAOJ;IAEF;;OAEG;IACH,WAAW,aAMT;IAEF;;OAEG;IACH,YAAY,aAMV;IAEF;;;;;;;;;OASG;IACH,WAAW,yBAMT;IAEF;;;;;OAKG;IACH,gBAAgB,yBAMd;IAEF;;;OAGG;IACH,qBAAqB,0CAInB;IAEF;;OAEG;IACH,gBAAgB,eAId;IAEF,cAAc,0CAMZ;IAEF,cAAc,qCAeZ;IAEF,WAAW,yCAKV;IAED,eAAe,0CAYb;IAEF,SAAS,uCAKP;IAEF,iBAAiB,wCAKf;IAEF,oCAAoC,uEAUlC;IAEF,4BAA4B,0CAK1B;IAEF,kBAAkB,CAAC,SAAS,EAAE,iBAAiB;IAM/C,uBAAuB,CACrB,SAAS,EAAE,iBAAiB,EAC5B,QAAQ,EAAE,MAAM,iBAAiB;IASnC,MAAM;CA0EP;AAED,eAAe,OAAO,CAAC"}
+9 -8
View File
@@ -10,7 +10,7 @@
* Licensed under the MIT License.
*/
import React from 'react';
import { NativeWebViewWindows, WebViewSharedProps, State } from './WebViewTypes';
import { NativeWebViewWindows, WebViewSharedProps, WebViewProgressEvent, WebViewNavigationEvent, WebViewErrorEvent, WebViewHttpErrorEvent, WebViewMessageEvent, State } from './WebViewTypes';
export default class WebView extends React.Component<WebViewSharedProps, State> {
static defaultProps: {
javaScriptEnabled: boolean;
@@ -21,18 +21,19 @@ export default class WebView extends React.Component<WebViewSharedProps, State>
goBack: () => void;
reload: () => void;
injectJavaScript: (data: string) => void;
postMessage: (data: string) => void;
/**
* We return an event with a bunch of fields including:
* url, title, loading, canGoBack, canGoForward
*/
updateNavigationState: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNavigation>) => void;
updateNavigationState: (event: WebViewNavigationEvent) => void;
getWebViewHandle: () => number | null;
onLoadingStart: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNavigation>) => void;
onLoadingProgress: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNativeProgressEvent>) => void;
onLoadingError: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewError>) => void;
onLoadingFinish: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNavigation>) => void;
onMessage: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewMessage>) => void;
onHttpError: (event: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewHttpError>) => void;
onLoadingStart: (event: WebViewNavigationEvent) => void;
onLoadingProgress: (event: WebViewProgressEvent) => void;
onLoadingError: (event: WebViewErrorEvent) => void;
onLoadingFinish: (event: WebViewNavigationEvent) => void;
onMessage: (event: WebViewMessageEvent) => void;
onHttpError: (event: WebViewHttpErrorEvent) => void;
render(): JSX.Element;
}
//# sourceMappingURL=WebView.windows.d.ts.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"WebView.windows.d.ts","sourceRoot":"","sources":["../src/WebView.windows.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAa1B,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAOlB,KAAK,EACN,MAAM,gBAAgB,CAAC;AA0BxB,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,KAAK,CAAC,SAAS,CAAC,kBAAkB,EAAE,KAAK,CAAC;IAE7E,MAAM,CAAC,YAAY;;MAEjB;IAEF,KAAK,EAAE,KAAK,CAGX;IAED,UAAU,wCAA2C;IAErD,SAAS,aAMR;IAED,MAAM,aAML;IAED,MAAM,aAML;IAED,gBAAgB,yBAMf;IAED;;;OAGG;IACH,qBAAqB,2GAIpB;IAED,gBAAgB,sBAGf;IAED,cAAc,2GAMb;IAED,iBAAiB,oHAKf;IAEF,cAAc,sGAcb;IAED,eAAe,2GAYd;IAED,SAAS,wGAKR;IAED,WAAW,0GAKV;IAED,MAAM;CA6EP"}
{"version":3,"file":"WebView.windows.d.ts","sourceRoot":"","sources":["../src/WebView.windows.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAa1B,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EAEnB,KAAK,EACN,MAAM,gBAAgB,CAAC;AA0BxB,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,KAAK,CAAC,SAAS,CAAC,kBAAkB,EAAE,KAAK,CAAC;IAE7E,MAAM,CAAC,YAAY;;MAEjB;IAEF,KAAK,EAAE,KAAK,CAGX;IAED,UAAU,wCAA2C;IAErD,SAAS,aAMR;IAED,MAAM,aAML;IAED,MAAM,aAML;IAED,gBAAgB,yBAMf;IAED,WAAW,yBAMT;IAEF;;;OAGG;IACH,qBAAqB,0CAIpB;IAED,gBAAgB,sBAGf;IAED,cAAc,0CAMb;IAED,iBAAiB,wCAKf;IAEF,cAAc,qCAcb;IAED,eAAe,0CAYd;IAED,SAAS,uCAKR;IAED,WAAW,yCAKV;IAED,MAAM;CA6EP"}
+6 -3
View File
@@ -77,6 +77,9 @@ var WebView = /** @class */ (function (_super) {
_this.injectJavaScript = function (data) {
UIManager.dispatchViewManagerCommand(_this.getWebViewHandle(), UIManager.getViewManagerConfig('RCTWebView').Commands.injectJavaScript, [data]);
};
_this.postMessage = function (data) {
UIManager.dispatchViewManagerCommand(_this.getWebViewHandle(), UIManager.getViewManagerConfig('RCTWebView').Commands.postMessage, [String(data)]);
};
/**
* We return an event with a bunch of fields including:
* url, title, loading, canGoBack, canGoForward
@@ -171,9 +174,9 @@ var WebView = /** @class */ (function (_super) {
var NativeWebView = nativeConfig.component
|| RCTWebView;
var webView = (<NativeWebView ref={this.webViewRef} key="webViewKey" {...otherProps} messagingEnabled={typeof onMessage === 'function'} onLoadingError={this.onLoadingError} onLoadingFinish={this.onLoadingFinish} onLoadingProgress={this.onLoadingProgress} onLoadingStart={this.onLoadingStart} onHttpError={this.onHttpError} onMessage={this.onMessage} onScroll={this.props.onScroll} onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} source={resolveAssetSource(this.props.source)} style={webViewStyles} {...nativeConfig.props}/>);
return (<View style={styles.container}>
{webView}
{otherView}
return (<View style={styles.container}>
{webView}
{otherView}
</View>);
};
WebView.defaultProps = {
+2 -2
View File
@@ -1,6 +1,6 @@
import { OnShouldStartLoadWithRequest } from './WebViewTypes';
import { WebViewNavigationEvent, OnShouldStartLoadWithRequest } from './WebViewTypes';
declare const defaultOriginWhitelist: string[];
declare const createOnShouldStartLoadWithRequest: (loadRequest: (shouldStart: boolean, url: string, lockIdentifier: number) => void, originWhitelist: readonly string[], onShouldStartLoadWithRequest?: OnShouldStartLoadWithRequest | undefined) => ({ nativeEvent }: import("react-native").NativeSyntheticEvent<import("./WebViewTypes").WebViewNavigation>) => void;
declare const createOnShouldStartLoadWithRequest: (loadRequest: (shouldStart: boolean, url: string, lockIdentifier: number) => void, originWhitelist: readonly string[], onShouldStartLoadWithRequest?: OnShouldStartLoadWithRequest | undefined) => ({ nativeEvent }: WebViewNavigationEvent) => void;
declare const defaultRenderLoading: () => JSX.Element;
declare const defaultRenderError: (errorDomain: string | undefined, errorCode: number, errorDesc: string) => JSX.Element;
export { defaultOriginWhitelist, createOnShouldStartLoadWithRequest, defaultRenderLoading, defaultRenderError, };
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"WebViewShared.d.ts","sourceRoot":"","sources":["../src/WebViewShared.tsx"],"names":[],"mappings":"AAGA,OAAO,EAEL,4BAA4B,EAC7B,MAAM,gBAAgB,CAAC;AAGxB,QAAA,MAAM,sBAAsB,UAA4B,CAAC;AAuBzD,QAAA,MAAM,kCAAkC,uTA8BvC,CAAC;AAEF,QAAA,MAAM,oBAAoB,mBAIzB,CAAC;AACF,QAAA,MAAM,kBAAkB,wFAWvB,CAAC;AAEF,OAAO,EACL,sBAAsB,EACtB,kCAAkC,EAClC,oBAAoB,EACpB,kBAAkB,GACnB,CAAC"}
{"version":3,"file":"WebViewShared.d.ts","sourceRoot":"","sources":["../src/WebViewShared.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC7B,MAAM,gBAAgB,CAAC;AAGxB,QAAA,MAAM,sBAAsB,UAA4B,CAAC;AAuBzD,QAAA,MAAM,kCAAkC,sPA8BvC,CAAC;AAEF,QAAA,MAAM,oBAAoB,mBAIzB,CAAC;AACF,QAAA,MAAM,kBAAkB,wFAWvB,CAAC;AAEF,OAAO,EACL,sBAAsB,EACtB,kCAAkC,EAClC,oBAAoB,EACpB,kBAAkB,GACnB,CAAC"}
+25 -1
View File
@@ -1,7 +1,7 @@
import { ReactElement, Component } from 'react';
import { NativeSyntheticEvent, ViewProps, StyleProp, ViewStyle, NativeMethodsMixin, Constructor, UIManagerStatic, NativeScrollEvent } from 'react-native';
declare type WebViewCommands = 'goForward' | 'goBack' | 'reload' | 'stopLoading' | 'postMessage' | 'injectJavaScript' | 'loadUrl' | 'requestFocus';
declare type AndroidWebViewCommands = 'clearHistory' | 'clearCache' | 'clearFormData';
declare type AndroidWebViewCommands = 'clearHistory' | 'clearCache' | 'clearFormData' | 'answerPermissionRequest';
interface RNCWebViewUIManager<Commands extends string> extends UIManagerStatic {
getViewManagerConfig: (name: string) => {
Commands: {
@@ -63,6 +63,9 @@ export interface WebViewNativeEvent {
export interface WebViewNativeProgressEvent extends WebViewNativeEvent {
progress: number;
}
export interface WebViewNativePermissionEvent extends WebViewNativeEvent {
resources: string[];
}
export interface WebViewNavigation extends WebViewNativeEvent {
navigationType: 'click' | 'formsubmit' | 'backforward' | 'reload' | 'formresubmit' | 'other';
mainDocumentURL?: string;
@@ -88,6 +91,7 @@ export interface WebViewHttpError extends WebViewNativeEvent {
}
export declare type WebViewEvent = NativeSyntheticEvent<WebViewNativeEvent>;
export declare type WebViewProgressEvent = NativeSyntheticEvent<WebViewNativeProgressEvent>;
export declare type WebViewPermissionEvent = NativeSyntheticEvent<WebViewNativePermissionEvent>;
export declare type WebViewNavigationEvent = NativeSyntheticEvent<WebViewNavigation>;
export declare type FileDownloadEvent = NativeSyntheticEvent<FileDownload>;
export declare type WebViewMessageEvent = NativeSyntheticEvent<WebViewMessage>;
@@ -156,6 +160,9 @@ export interface CommonNativeWebViewProps extends ViewProps {
incognito?: boolean;
injectedJavaScript?: string;
injectedJavaScriptBeforeContentLoaded?: string;
injectedJavaScriptForMainFrameOnly?: boolean;
injectedJavaScriptBeforeContentLoadedForMainFrameOnly?: boolean;
javaScriptCanOpenWindowsAutomatically?: boolean;
mediaPlaybackRequiresUserAction?: boolean;
messagingEnabled: boolean;
onScroll?: (event: NativeScrollEvent) => void;
@@ -187,6 +194,7 @@ export interface AndroidNativeWebViewProps extends CommonNativeWebViewProps {
javaScriptEnabled?: boolean;
mixedContentMode?: 'never' | 'always' | 'compatibility';
onContentSizeChange?: (event: WebViewEvent) => void;
onPermissionRequest?: (event: WebViewPermissionEvent) => void;
overScrollMode?: OverScrollModeType;
saveFormDataDisabled?: boolean;
textZoom?: number;
@@ -552,6 +560,7 @@ export interface MacOSWebViewProps extends WebViewSharedProps {
export interface AndroidWebViewProps extends WebViewSharedProps {
onNavigationStateChange?: (event: WebViewNavigation) => void;
onContentSizeChange?: (event: WebViewEvent) => void;
onPermissionRequest?: (event: WebViewPermissionEvent) => void;
/**
* https://developer.android.com/reference/android/webkit/WebSettings.html#setCacheMode(int)
* Set the cacheMode. Possible values are:
@@ -674,6 +683,11 @@ export interface WebViewSharedProps extends ViewProps {
* @platform android
*/
javaScriptEnabled?: boolean;
/**
* A Boolean value indicating whether JavaScript can open windows without user interaction.
* The default value is `false`.
*/
javaScriptCanOpenWindowsAutomatically?: boolean;
/**
* Stylesheet object to set the style of the container view.
*/
@@ -742,6 +756,16 @@ export interface WebViewSharedProps extends ViewProps {
* once the webview is initialized but before the view loads any content.
*/
injectedJavaScriptBeforeContentLoaded?: string;
/**
* If `true` (default; mandatory for Android), loads the `injectedJavaScript` only into the main frame.
* If `false` (only supported on iOS and macOS), loads it into all frames (e.g. iframes).
*/
injectedJavaScriptForMainFrameOnly?: boolean;
/**
* If `true` (default; mandatory for Android), loads the `injectedJavaScriptBeforeContentLoaded` only into the main frame.
* If `false` (only supported on iOS and macOS), loads it into all frames (e.g. iframes).
*/
injectedJavaScriptBeforeContentLoadedForMainFrameOnly?: boolean;
/**
* Boolean value that determines whether a horizontal scroll indicator is
* shown in the `WebView`. The default value is `true`.
File diff suppressed because one or more lines are too long
+17
View File
@@ -26,6 +26,7 @@ import {
WebViewMessageEvent,
WebViewNavigationEvent,
WebViewProgressEvent,
WebViewPermissionEvent,
AndroidWebViewProps,
NativeWebViewAndroid,
State,
@@ -175,6 +176,14 @@ class WebView extends React.Component<AndroidWebViewProps, State> {
);
};
answerPermissionRequest = (allow: boolean, resources: string[]) => {
UIManager.dispatchViewManagerCommand(
this.getWebViewHandle(),
this.getCommands().answerPermissionRequest,
[allow, ...(resources || [])],
);
}
/**
* We return an event with a bunch of fields including:
* url, title, loading, canGoBack, canGoForward
@@ -252,6 +261,13 @@ class WebView extends React.Component<AndroidWebViewProps, State> {
}
};
onPermissionRequest = (event: WebViewPermissionEvent) => {
const { onPermissionRequest } = this.props;
if (onPermissionRequest) {
onPermissionRequest(event);
}
}
onLoadingProgress = (event: WebViewProgressEvent) => {
const { onLoadProgress } = this.props;
const { nativeEvent: { progress } } = event;
@@ -345,6 +361,7 @@ class WebView extends React.Component<AndroidWebViewProps, State> {
onLoadingError={this.onLoadingError}
onLoadingFinish={this.onLoadingFinish}
onLoadingProgress={this.onLoadingProgress}
onPermissionRequest={this.onPermissionRequest}
onLoadingStart={this.onLoadingStart}
onHttpError={this.onHttpError}
onMessage={this.onMessage}
+12 -1
View File
@@ -14,7 +14,7 @@ import {
type WebViewCommands = 'goForward' | 'goBack' | 'reload' | 'stopLoading' | 'postMessage' | 'injectJavaScript' | 'loadUrl' | 'requestFocus';
type AndroidWebViewCommands = 'clearHistory' | 'clearCache' | 'clearFormData';
type AndroidWebViewCommands = 'clearHistory' | 'clearCache' | 'clearFormData' | 'answerPermissionRequest';
@@ -102,6 +102,11 @@ export interface WebViewNativeProgressEvent extends WebViewNativeEvent {
progress: number;
}
export interface WebViewNativePermissionEvent extends WebViewNativeEvent {
resources: string[];
}
export interface WebViewNavigation extends WebViewNativeEvent {
navigationType:
| 'click'
@@ -143,6 +148,10 @@ export type WebViewProgressEvent = NativeSyntheticEvent<
WebViewNativeProgressEvent
>;
export type WebViewPermissionEvent = NativeSyntheticEvent<
WebViewNativePermissionEvent
>;
export type WebViewNavigationEvent = NativeSyntheticEvent<WebViewNavigation>;
export type FileDownloadEvent = NativeSyntheticEvent<FileDownload>;
@@ -277,6 +286,7 @@ export interface AndroidNativeWebViewProps extends CommonNativeWebViewProps {
javaScriptEnabled?: boolean;
mixedContentMode?: 'never' | 'always' | 'compatibility';
onContentSizeChange?: (event: WebViewEvent) => void;
onPermissionRequest?: (event: WebViewPermissionEvent) => void;
overScrollMode?: OverScrollModeType;
saveFormDataDisabled?: boolean;
textZoom?: number;
@@ -682,6 +692,7 @@ export interface MacOSWebViewProps extends WebViewSharedProps {
export interface AndroidWebViewProps extends WebViewSharedProps {
onNavigationStateChange?: (event: WebViewNavigation) => void;
onContentSizeChange?: (event: WebViewEvent) => void;
onPermissionRequest?: (event: WebViewPermissionEvent) => void;
/**
* https://developer.android.com/reference/android/webkit/WebSettings.html#setCacheMode(int)