Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MIGRATED: Issue with window.postmessage on Android webview only when debug is not turned on. (#20714) #29

Closed
jamonholmgren opened this issue Sep 10, 2018 · 6 comments
Labels
migrated Migrated from https://github.com/facebook/react-native/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+

Comments

@jamonholmgren
Copy link
Member

Migrated from facebook/react-native#20714.

@mattdwardle says:


Environment
React Native Environment Info:
System:
OS: macOS High Sierra 10.13.6
CPU: x64 Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
Memory: 944.55 MB / 16.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 10.6.0 - /usr/local/bin/node
npm: 6.3.0 - /usr/local/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 11.4, macOS 10.13, tvOS 11.4, watchOS 4.3
Android SDK:
Build Tools: 19.1.0, 20.0.0, 21.1.2, 22.0.1, 23.0.1, 23.0.2, 23.0.3, 24.0.0, 24.0.1, 25.0.0, 25.0.1, 25.0.2, 26.0.0, 26.0.1, 26.0.2, 26.0.3
API Levels: 23, 24, 25, 26, 27
IDEs:
Android Studio: 3.1 AI-173.4819257
Xcode: 9.4.1/9F2000 - /usr/bin/xcodebuild
npmPackages:
react: 16.4.1 => 16.4.1
react-native: 0.56.0 => 0.56.0
npmGlobalPackages:
create-react-native-app: 1.0.0
react-native-cli: 2.0.1
react-native-git-upgrade: 0.2.7
react-native-rename: 2.2.2
react-native-video: 1.2.0

Description
So I am looking to send the scroll location from a webview to the native code. I am able to get it working on iOS however and on Android but only while debug is turned on. I created a raw boilerplate version of my app and I still experience the same issue. I have also tried just appending javascript to the HTML string and I have also tried injectedjavascript with no luck. See the code example below.

Reproducible Demo

import React, { Component } from 'react';
import { View, Text, Button, WebView, AsyncStorage } from 'react-native';

export default class Web extends Component {

constructor(props) {
    super(props);
    this.webview;
    this.onWebViewMessage = this.onWebViewMessage.bind(this);
    this.state = {
        scrollLocation: null,
    };
}

componentWillMount() {
    this.checkForBookmark();
}

getLocal = async (key) => {
    return AsyncStorage.getItem(key).then((res) => {
        var localData = JSON.parse(res);
        return localData;
    });
}

setLocal = async (key, data) => {
    data = JSON.stringify(data);
    AsyncStorage.setItem(key, data);
    return data;
}


removeLocal = async (key) => {
    AsyncStorage.removeItem(key);
    return key;
}

getLocalBookmark = async () => {
    var postId = 2;
    var localpost = await this.getLocal(`@article${postId}Data:key`);
    return localpost;
}

setLocalBookmark = async (scrollLocation) => {
    var postId = 2;
    var localpost = await this.removeLocal(`@article${postId}Data:key`);
    var localpost = await this.setLocal(`@article${postId}Data:key`, scrollLocation);
}

async checkForBookmark() {
    var content = this.props.navigation.state.params;
    var currentBookMark = await this.getLocalBookmark();
    if (currentBookMark) {
        this.setState({
            scrollLocation: currentBookMark
        });
    }
}

async onWebViewMessage(event) {
    let msg;
    msg = JSON.parse(event.nativeEvent.data);
    console.log(msg);
    this.setLocalBookmark(msg);
}

render() {
    var htmlcontent = this.props.navigation.state.params;

    var fullhtml;
    var webviewScript;
    if (!!this.state.scrollLocation) {
        var scrollPosi = this.state.scrollLocation;
        webviewScript = `
        function Scrolldown() {
            window.scrollBy(0, 765);
       }
       window.onscroll = function() {
            var scrollPos = window.scrollY || window.scrollTop || document.getElementsByTagName("html")[0].scrollTop;
            try {
                window.postMessage(scrollPos, '*');
            } catch (error) {
                alert(error)
            }
        };
       window.onload = Scrolldown;
        `
        fullhtml = htmlcontent;
    }
    else {
        webviewScript = `
        function Scrolldown() {
              window.onscroll = function() {
                var scrollPos = window.scrollY || window.scrollTop || document.getElementsByTagName("html")[0].scrollTop;
                try {
                    window.postMessage(scrollPos, '*');
                } catch (error) {
                    alert(error)
                }
            };
       }
       window.onload = Scrolldown;
       `
        fullhtml = htmlcontent;
    }
    return (
        <View style={{ flex: 10 }}>
            <WebView
                originWhitelist={['*']}
                source={{
                    html: fullhtml,
                    baseUrl: ''
                }}
                javaScriptEnabled={true}
                injectedJavaScript={webviewScript}
                onMessage={this.onWebViewMessage}
            />
        </View>
    );

}
}

@jamonholmgren jamonholmgren added the migrated Migrated from https://github.com/facebook/react-native/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+ label Sep 10, 2018
@finalquest
Copy link

finalquest commented Oct 17, 2018

Hi. @jamonholmgren
We have to inject this jscode on the webview to get the postMessage works on the web side.

  const originalPostMessage = window.postMessage;
  const patchedPostMessage = function (message, targetOrigin, transfer) {
    originalPostMessage(message, targetOrigin, transfer);
  };
  patchedPostMessage.toString = function () {
    return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');
  };
  window.postMessage = patchedPostMessage;

@jamonholmgren
Copy link
Member Author

@finalquest Interesting, thanks for sharing that code snippet!

@Titozzz
Copy link
Collaborator

Titozzz commented Oct 21, 2018

Will probably need to be closed once #66 is solved

@dev-0x1
Copy link

dev-0x1 commented Jan 17, 2019

Let say my injectedscript function

const injectedScript = function () {
	function waitForBridge() {
		if (window.postMessage.length !== 1) {
			setTimeout(waitForBridge, 200);
		} else {
			let height = Math.max(
				document.body.scrollHeight,
				document.documentElement.scrollHeight,
				document.body.offsetHeight,
				document.documentElement.offsetHeight,
				document.body.clientHeight,
				document.documentElement.clientHeight
			);
			window.postMessage(height, '*');
		}
	}
	setTimeout(() => { waitForBridge() }, 0); //add setTimeout to make post message work
};

add setTimeout for waitBridge() to make post message work

@Titozzz Titozzz closed this as completed Feb 1, 2019
@Titozzz

This comment has been minimized.

Titozzz added a commit that referenced this issue Feb 1, 2019
…entation (#303)

fixes #29
fixes #272
fixes #221
fixes #105
fixes #66

BREAKING CHANGE: Communication from webview to react-native has been completely rewritten. React-native-webview will not use or override window.postMessage anymore. Reasons behind these changes can be found throughout so many issues that it made sense to go that way.

Instead of using window.postMessage(data, *), please now use window.ReactNativeWebView.postMessage(data).

Side note: if you wish to keep compatibility with the old version when you upgrade, you can use the injectedJavascript prop to do that:

const injectedJavascript = `(function() {
  window.postMessage = function(data) {
    window.ReactNativeWebView.postMessage(data);
  };
})()`;

Huge thanks to @jordansexton and @KoenLav!
Titozzz pushed a commit that referenced this issue Feb 1, 2019
# [5.0.0](v4.1.0...v5.0.0) (2019-02-01)

### Features

* **Android/iOS postMessage:** refactoring the old postMessage implementation ([#303](#303)) ([f3bdab5](f3bdab5)), closes [#29](#29) [#272](#272) [#221](#221) [#105](#105) [#66](#66)

### BREAKING CHANGES

* **Android/iOS postMessage:** Communication from webview to react-native has been completely rewritten. React-native-webview will not use or override window.postMessage anymore. Reasons behind these changes can be found throughout so many issues that it made sense to go that way.

Instead of using window.postMessage(data, *), please now use window.ReactNativeWebView.postMessage(data).

Side note: if you wish to keep compatibility with the old version when you upgrade, you can use the injectedJavascript prop to do that:

const injectedJavascript = `(function() {
  window.postMessage = function(data) {
    window.ReactNativeWebView.postMessage(data);
  };
})()`;

Huge thanks to @jordansexton and @KoenLav!
@Titozzz
Copy link
Collaborator

Titozzz commented Feb 1, 2019

🎉 This issue has been resolved in version 5.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

phuongwd pushed a commit to phuongwd/react-native-webview that referenced this issue Apr 29, 2020
…entation (react-native-webview#303)

fixes react-native-webview#29
fixes react-native-webview#272
fixes react-native-webview#221
fixes react-native-webview#105
fixes react-native-webview#66

BREAKING CHANGE: Communication from webview to react-native has been completely rewritten. React-native-webview will not use or override window.postMessage anymore. Reasons behind these changes can be found throughout so many issues that it made sense to go that way.

Instead of using window.postMessage(data, *), please now use window.ReactNativeWebView.postMessage(data).

Side note: if you wish to keep compatibility with the old version when you upgrade, you can use the injectedJavascript prop to do that:

const injectedJavascript = `(function() {
  window.postMessage = function(data) {
    window.ReactNativeWebView.postMessage(data);
  };
})()`;

Huge thanks to @jordansexton and @KoenLav!
phuongwd pushed a commit to phuongwd/react-native-webview that referenced this issue Apr 29, 2020
# [5.0.0](react-native-webview/react-native-webview@v4.1.0...v5.0.0) (2019-02-01)

### Features

* **Android/iOS postMessage:** refactoring the old postMessage implementation ([react-native-webview#303](react-native-webview#303)) ([f3bdab5](react-native-webview@f3bdab5)), closes [react-native-webview#29](react-native-webview#29) [react-native-webview#272](react-native-webview#272) [react-native-webview#221](react-native-webview#221) [react-native-webview#105](react-native-webview#105) [react-native-webview#66](react-native-webview#66)

### BREAKING CHANGES

* **Android/iOS postMessage:** Communication from webview to react-native has been completely rewritten. React-native-webview will not use or override window.postMessage anymore. Reasons behind these changes can be found throughout so many issues that it made sense to go that way.

Instead of using window.postMessage(data, *), please now use window.ReactNativeWebView.postMessage(data).

Side note: if you wish to keep compatibility with the old version when you upgrade, you can use the injectedJavascript prop to do that:

const injectedJavascript = `(function() {
  window.postMessage = function(data) {
    window.ReactNativeWebView.postMessage(data);
  };
})()`;

Huge thanks to @jordansexton and @KoenLav!
jaynilson added a commit to jaynilson/reactNative_service_USA that referenced this issue Sep 11, 2024
# [5.0.0](react-native-webview/react-native-webview@v4.1.0...v5.0.0) (2019-02-01)

### Features

* **Android/iOS postMessage:** refactoring the old postMessage implementation ([#303](react-native-webview/react-native-webview#303)) ([f3bdab5](react-native-webview/react-native-webview@f3bdab5)), closes [#29](react-native-webview/react-native-webview#29) [#272](react-native-webview/react-native-webview#272) [#221](react-native-webview/react-native-webview#221) [#105](react-native-webview/react-native-webview#105) [#66](react-native-webview/react-native-webview#66)

### BREAKING CHANGES

* **Android/iOS postMessage:** Communication from webview to react-native has been completely rewritten. React-native-webview will not use or override window.postMessage anymore. Reasons behind these changes can be found throughout so many issues that it made sense to go that way.

Instead of using window.postMessage(data, *), please now use window.ReactNativeWebView.postMessage(data).

Side note: if you wish to keep compatibility with the old version when you upgrade, you can use the injectedJavascript prop to do that:

const injectedJavascript = `(function() {
  window.postMessage = function(data) {
    window.ReactNativeWebView.postMessage(data);
  };
})()`;

Huge thanks to @jordansexton and @KoenLav!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
migrated Migrated from https://github.com/facebook/react-native/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+
Projects
None yet
Development

No branches or pull requests

4 participants