Skip to content

Commit

Permalink
Webview rewrite (#1096)
Browse files Browse the repository at this point in the history
* webview rewrite in progress

* some fixes

* update deps

* update unit tests

* clear cache

* android injection working

* add missing props

* remove UIWebview imports from react native

* fix CI caching issues on dev

* update branch sdk

* set yarn network concurrency = 1 for CI

* update react-native-branch

* fix postinstall

* postinstall fix

* update react-native-webview

* fix token rendering

* fix favorites

* fix alert crash

* bugfixes

* fixes

* fix import

* bump react-native-webview
  • Loading branch information
Bruno Barbieri authored Sep 27, 2019
1 parent 23275d4 commit da86a0d
Show file tree
Hide file tree
Showing 20 changed files with 178 additions and 188 deletions.
19 changes: 4 additions & 15 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
aliases:
- &restore-cache
keys:
- v1.0.7-{{ .Branch }}-{{ checksum "package.json" }}
- v1.0.7-{{ .Branch }}

- &save-cache
key: v1.0.7-{{ .Branch }}-{{ checksum "package.json" }}
paths:
- node_modules
- &restore-node-cache
keys:
- v1.0.7-node-{{ .Branch }}-{{ checksum "package.json" }}
- v1.0.7-node-{{ .Branch }}
- v1.1.0-node-{{ .Branch }}-{{ checksum "package.json" }}
- v1.1.0-node-{{ .Branch }}
- &save-node-cache
key: v1.0.7-node-{{ .Branch }}-{{ checksum "package.json" }}
key: v1.1.0-node-{{ .Branch }}-{{ checksum "package.json" }}
paths:
- node_modules

- &install-node-dependencies
|
rm -rf node_modules/websocket/.git && yarn install --network-timeout 300000 --frozen-lockfile
rm -rf node_modules/websocket/.git && yarn install --network-timeout 300000 --frozen-lockfile --network-concurrency 1

defaults: &defaults
working_directory: ~/MetaMask
Expand All @@ -32,13 +23,11 @@ jobs:
xcode: 10.3.0
steps:
- checkout
- restore_cache: *restore-cache
- run: *install-node-dependencies
- persist_to_workspace:
root: .
paths:
- node_modules
- save_cache: *save-cache
prep-node-deps:
<<: *defaults
docker:
Expand Down
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ android {
}

dependencies {
implementation project(':react-native-webview')
implementation project(':react-native-fabric')
implementation project(':@react-native-community_netinfo')
implementation project(':react-native-view-shot')
Expand All @@ -274,7 +275,6 @@ dependencies {
implementation project(':react-native-branch')
implementation "io.branch.sdk.android:library:3.0.4"

implementation project(':react-native-web3-webview')
implementation project(':react-native-camera')
implementation project(':react-native-share')
implementation project(':react-native-i18n')
Expand Down
4 changes: 2 additions & 2 deletions android/app/src/main/java/io/metamask/MainApplication.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.metamask;

import com.facebook.react.ReactApplication;
import com.reactnativecommunity.webview.RNCWebViewPackage;
import com.smixx.fabric.FabricPackage;
import com.reactnativecommunity.netinfo.NetInfoPackage;
import fr.greweb.reactnativeviewshot.RNViewShotPackage;
Expand All @@ -13,7 +14,6 @@
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
import io.branch.rnbranch.RNBranchPackage;
import io.branch.rnbranch.RNBranchModule;
import com.web3webview.Web3WebviewPackage;
import io.metamask.nativeModules.RCTAnalyticsPackage;
import com.oblador.vectoricons.VectorIconsPackage;
import cl.json.RNSharePackage;
Expand Down Expand Up @@ -48,6 +48,7 @@ public boolean getUseDeveloperSupport() {
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNCWebViewPackage(),
new FabricPackage(),
new NetInfoPackage(),
new RNViewShotPackage(),
Expand All @@ -69,7 +70,6 @@ protected List<ReactPackage> getPackages() {
new RNOSModule(),
new RNSharePackage(),
new VectorIconsPackage(),
new Web3WebviewPackage(),
new RCTAnalyticsPackage()
);
}
Expand Down
2 changes: 2 additions & 0 deletions android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
rootProject.name = 'MetaMask'
include ':react-native-webview'
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
include ':react-native-fabric'
project(':react-native-fabric').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fabric/android')
include ':@react-native-community_netinfo'
Expand Down
6 changes: 4 additions & 2 deletions app/components/UI/TokenImage/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ exports[`TokenImage should render correctly 1`] = `
style={
Array [
Object {
"borderRadius": 25,
"height": 50,
"overflow": "hidden",
"width": 50,
},
undefined,
Object {
"borderRadius": 25,
"overflow": "hidden",
},
]
}
>
Expand Down
6 changes: 4 additions & 2 deletions app/components/UI/TokenImage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import { toChecksumAddress } from 'ethereumjs-util';
const styles = StyleSheet.create({
itemLogoWrapper: {
width: 50,
height: 50,
height: 50
},
roundImage: {
overflow: 'hidden',
borderRadius: 25
}
Expand Down Expand Up @@ -53,7 +55,7 @@ export default class TokenElement extends Component {
// When image is defined, is coming from a token added by watchAsset, so it has to be handled alone
const watchedAsset = asset.image !== undefined;
return (
<View style={[styles.itemLogoWrapper, containerStyle]}>
<View style={[styles.itemLogoWrapper, containerStyle, asset.logo || asset.image ? {} : styles.roundImage]}>
{asset.logo || asset.image ? (
<AssetIcon watchedAsset={watchedAsset} logo={asset.image || asset.logo} customStyle={iconStyle} />
) : (
Expand Down
27 changes: 11 additions & 16 deletions app/components/Views/BrowserTab/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
InteractionManager
} from 'react-native';
import { withNavigation } from 'react-navigation';
import Web3Webview from 'react-native-web3-webview';
import { WebView } from 'react-native-webview';
import Icon from 'react-native-vector-icons/FontAwesome';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import MaterialCommunityIcon from 'react-native-vector-icons/MaterialCommunityIcons';
Expand All @@ -32,7 +32,7 @@ import { colors, baseStyles, fontStyles } from '../../../styles/common';
import Networks from '../../../util/networks';
import Logger from '../../../util/Logger';
import onUrlSubmit, { getHost, getUrlObj } from '../../../util/browser';
import { SPA_urlChangeListener, JS_WINDOW_INFORMATION, JS_DESELECT_TEXT } from '../../../util/browserSripts';
import { SPA_urlChangeListener, JS_WINDOW_INFORMATION, JS_DESELECT_TEXT } from '../../../util/browserScripts';
import resolveEnsToIpfsContentId from '../../../lib/ens-ipfs/resolver';
import Button from '../../UI/Button';
import { strings } from '../../../../locales/i18n';
Expand Down Expand Up @@ -414,10 +414,7 @@ export class BrowserTab extends PureComponent {
if (!currentPageTitle || currentPageTitle !== {}) {
// We need to get the title to add bookmark
const { current } = this.webview;
current &&
(Platform.OS === 'ios'
? current.evaluateJavaScript(JS_WINDOW_INFORMATION)
: current.injectJavaScript(JS_WINDOW_INFORMATION));
current && current.injectJavaScript(JS_WINDOW_INFORMATION);
}
setTimeout(() => {
callback();
Expand Down Expand Up @@ -1263,11 +1260,7 @@ export class BrowserTab extends PureComponent {
this.setState({ autocompleteInputValue: inputValue });
};

sendStateUpdate = () => {
this.backgroundBridge.sendStateUpdate();
};

onLoadProgress = progress => {
onLoadProgress = ({ nativeEvent: { progress } }) => {
this.setState({ progress });
};

Expand Down Expand Up @@ -1296,7 +1289,7 @@ export class BrowserTab extends PureComponent {
// Inject favorites on the homepage
if (this.isHomepage() && current) {
const js = this.state.homepageScripts;
Platform.OS === 'ios' ? current.evaluateJavaScript(js) : current.injectJavaScript(js);
current.injectJavaScript(js);
}
};

Expand Down Expand Up @@ -1438,7 +1431,7 @@ export class BrowserTab extends PureComponent {
if (this.isHomepage()) {
const { current } = this.webview;
const blur = `document.getElementsByClassName('autocomplete-input')[0].blur();`;
current && (Platform.OS === 'ios' ? current.evaluateJavaScript(blur) : current.injectJavaScript(blur));
current && current.injectJavaScript(blur);
}
};

Expand Down Expand Up @@ -1709,13 +1702,13 @@ export class BrowserTab extends PureComponent {
>
<View style={styles.webview}>
{activated && !forceReload && (
<Web3Webview
<WebView
// eslint-disable-next-line react/jsx-no-bind
renderError={() => (
<WebviewError error={this.state.lastError} onReload={this.forceReload} />
)}
injectedOnStartLoadingJavaScript={entryScriptWeb3}
onProgress={this.onLoadProgress}
injectedJavaScript={entryScriptWeb3}
onLoadProgress={this.onLoadProgress}
onLoadStart={this.onLoadStart}
onLoadEnd={this.onLoadEnd}
onError={this.onError}
Expand All @@ -1727,6 +1720,8 @@ export class BrowserTab extends PureComponent {
userAgent={USER_AGENT}
sendCookies
javascriptEnabled
allowsInlineMediaPlayback
useWebkit
/>
)}
</View>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,15 @@ exports[`SimpleWebview should render correctly 1`] = `
}
}
>
<Web3Webview
<WebView
cacheEnabled={true}
javaScriptEnabled={true}
messagingEnabled={true}
openNewWindowInWebView={true}
originWhitelist={
Array [
"http://*",
"https://*",
]
}
saveFormDataDisabled={false}
scalesPageToFit={true}
showDefaultLoader={false}
source={
Object {
"uri": Object {
Expand All @@ -29,7 +25,7 @@ exports[`SimpleWebview should render correctly 1`] = `
},
}
}
thirdPartyCookiesEnabled={true}
useSharedProcessPool={true}
/>
</View>
`;
4 changes: 2 additions & 2 deletions app/components/Views/SimpleWebview/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native';
import Web3Webview from 'react-native-web3-webview';
import { WebView } from 'react-native-webview';
import { getWebviewNavbar } from '../../UI/Navbar';
import Share from 'react-native-share'; // eslint-disable-line import/default
import Logger from '../../../util/Logger';
Expand Down Expand Up @@ -39,7 +39,7 @@ export default class SimpleWebview extends PureComponent {
if (uri) {
return (
<View style={baseStyles.flexGrow}>
<Web3Webview source={{ uri }} />
<WebView source={{ uri }} />
</View>
);
}
Expand Down
34 changes: 18 additions & 16 deletions app/core/BackgroundBridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,23 @@ export class BackgroundBridge {
_webview;
_accounts;

_onInpageRequest(payload) {
_postMessageToProvider(message) {
const current = this._webview.current;
current &&
current.injectJavaScript(`window.ethereum && window.ethereum._onMessage(${JSON.stringify(message)})`);
}

_onInpageRequest(payload) {
const { provider } = this._engine.context.NetworkController;
const override = this._rpcOverrides && this._rpcOverrides[payload.method];
const __mmID = payload.__mmID + '';
const done = (error, response) => {
current &&
current.postMessage(
JSON.stringify({
type: 'INPAGE_RESPONSE',
payload: { error, response, __mmID }
})
);
this._postMessageToProvider(
JSON.stringify({
type: 'INPAGE_RESPONSE',
payload: { error, response, __mmID }
})
);
};
if (override) {
override(payload)
Expand Down Expand Up @@ -70,19 +74,17 @@ export class BackgroundBridge {
* Sends updated state to the InpageBridge provider
*/
sendStateUpdate = () => {
const current = this._webview.current;
const { network, selectedAddress } = this._engine.datamodel.flatState;
const payload = { network };
if (this._accounts) {
payload.selectedAddress = selectedAddress;
}
current &&
current.postMessage(
JSON.stringify({
type: 'STATE_UPDATE',
payload
})
);
this._postMessageToProvider(
JSON.stringify({
type: 'STATE_UPDATE',
payload
})
);
};

/**
Expand Down
30 changes: 16 additions & 14 deletions app/core/BackgroundBridge.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const MOCK_ENGINE = {

const MOCK_WEBVIEW = {
current: {
postMessage() {
injectJavaScript() {
/* eslint-disable-line no-empty */
}
}
Expand All @@ -47,26 +47,28 @@ describe('BackgroundBridge', () => {
it('should relay response from provider', () =>
new Promise(resolve => {
const bridge = new BackgroundBridge(MOCK_ENGINE, MOCK_WEBVIEW);
const stub = spyOn(MOCK_WEBVIEW.current, 'postMessage');
const stub = spyOn(MOCK_WEBVIEW.current, 'injectJavaScript');
bridge.onMessage({ type: 'INPAGE_REQUEST', payload: { method: 'net_version' } });
setTimeout(() => {
expect(stub).toBeCalledWith(
JSON.stringify({ type: 'INPAGE_RESPONSE', payload: { response: true, __mmID: 'undefined' } })
);
const msg = JSON.stringify({
type: 'INPAGE_RESPONSE',
payload: { response: true, __mmID: 'undefined' }
});
expect(stub).toBeCalledWith(`window.ethereum && window.ethereum._onMessage(${JSON.stringify(msg)})`);
resolve();
}, 250);
}));

it('should emit state update', () => {
const stub = spyOn(MOCK_WEBVIEW.current, 'postMessage');
const stub = spyOn(MOCK_WEBVIEW.current, 'injectJavaScript');
new BackgroundBridge(MOCK_ENGINE, MOCK_WEBVIEW);
expect(stub).toBeCalledWith(
JSON.stringify({
type: 'STATE_UPDATE',
payload: {
network: 'bar'
}
})
);
const msg = JSON.stringify({
type: 'STATE_UPDATE',
payload: {
network: 'bar'
}
});

expect(stub).toBeCalledWith(`window.ethereum && window.ethereum._onMessage(${JSON.stringify(msg)})`);
});
});
Loading

0 comments on commit da86a0d

Please sign in to comment.