Skip to content

Commit 787c4a5

Browse files
borisyankovgnprice
authored andcommitted
webview: Encode input messages in base64.
Fixes #2505, #2538, #2558. When using `postMessage` to communicate with the WebView, depending on the content of the message we send, an exception might be thrown. A minimal but reliable way to reproduce the issue is to send the string `'%22'`. Other character combinations might also cause issues. To work around the issue, we encode our data in the nice boring characters of base64 so that it doesn't get reinterpreted. --- More details on how React Native sends messages to the WebView: The logic is different on iOS vs. Android. This explains why the issue this is fixing is Android-specific. On iOS, a custom navigation scheme is used to pass the data into the webview; search the RN source for `RCTJSNavigationScheme`, and see the implementation of `webViewDidFinishLoad` in `RTCWebView.m`. The Android messaging happens in `receiveCommand` in `ReactWebViewManager.java`, by navigating to a URL of the form `javascript:(.....)`, which is a standard way of injecting JavaScript into web pages. The issue comes from the fact that since Android 4.4, `loadUrl` does a URL decode on the string passed to it: https://issuetracker.google.com/issues/36995865 See #2854 for links to upstream RN bug reports and PRs. [greg: lightly revised commit message; found better reference for the `loadUrl` issue]
1 parent e93ff11 commit 787c4a5

File tree

3 files changed

+6
-3
lines changed

3 files changed

+6
-3
lines changed

src/webview/MessageListWeb.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import getHtml from './html/html';
1010
import renderMessagesAsHtml from './html/renderMessagesAsHtml';
1111
import { getInputMessages } from './webViewHandleUpdates';
1212
import * as webViewEventHandlers from './webViewEventHandlers';
13+
import { base64Utf8Encode } from '../utils/encoding';
1314

1415
export default class MessageListWeb extends Component<Props> {
1516
context: Context;
@@ -29,7 +30,7 @@ export default class MessageListWeb extends Component<Props> {
2930

3031
sendMessages = (messages: WebviewInputMessage[]): void => {
3132
if (this.webview && messages.length > 0) {
32-
this.webview.postMessage(JSON.stringify(messages), '*');
33+
this.webview.postMessage(base64Utf8Encode(JSON.stringify(messages)), '*');
3334
}
3435
};
3536

src/webview/js/generatedEs3.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ var messageHandlers = {
241241
document.addEventListener('message', function (e) {
242242
scrollEventsDisabled = true;
243243
244-
var messages = JSON.parse(e.data);
244+
var decodedData = decodeURIComponent(escape(window.atob(e.data)));
245+
var messages = JSON.parse(decodedData);
245246
messages.forEach(function (msg) {
246247
messageHandlers[msg.type](msg);
247248
});

src/webview/js/js.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,8 @@ const messageHandlers = {
261261
document.addEventListener('message', e => {
262262
scrollEventsDisabled = true;
263263
// $FlowFixMe
264-
const messages: WebviewInputMessage[] = JSON.parse(e.data);
264+
const decodedData = decodeURIComponent(escape(window.atob(e.data)));
265+
const messages: WebviewInputMessage[] = JSON.parse(decodedData);
265266
messages.forEach((msg: WebviewInputMessage) => {
266267
// $FlowFixMe
267268
messageHandlers[msg.type](msg);

0 commit comments

Comments
 (0)