Skip to content

Commit 4b949b9

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 16e74c4 commit 4b949b9

File tree

3 files changed

+6
-3
lines changed

3 files changed

+6
-3
lines changed

Diff for: src/webview/MessageListWeb.js

+2-1
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

Diff for: src/webview/js/generatedEs3.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,8 @@ var messageHandlers = {
228228
document.addEventListener('message', function (e) {
229229
scrollEventsDisabled = true;
230230
231-
var messages = JSON.parse(e.data);
231+
var decodedData = decodeURIComponent(escape(window.atob(e.data)));
232+
var messages = JSON.parse(decodedData);
232233
messages.forEach(function (msg) {
233234
messageHandlers[msg.type](msg);
234235
});

Diff for: src/webview/js/js.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,8 @@ const messageHandlers = {
252252
document.addEventListener('message', e => {
253253
scrollEventsDisabled = true;
254254
// $FlowFixMe
255-
const messages: WebviewInputMessage[] = JSON.parse(e.data);
255+
const decodedData = decodeURIComponent(escape(window.atob(e.data)));
256+
const messages: WebviewInputMessage[] = JSON.parse(decodedData);
256257
messages.forEach((msg: WebviewInputMessage) => {
257258
// $FlowFixMe
258259
messageHandlers[msg.type](msg);

0 commit comments

Comments
 (0)