From 28ded362f7bd013c4ad919162cf0f8a969e09062 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Fri, 31 Aug 2018 22:51:32 -0400 Subject: [PATCH 01/12] android working with request interception --- .../CustomWebview/CustomWebviewManager.java | 230 +++++++++++++++--- .../CustomWebview/CustomWebviewPackage.java | 2 +- .../InputStreamWithInjectedJS.java | 85 +++++++ android/build.gradle | 9 +- app/components/Browser/index.js | 10 +- app/components/CustomWebview/index.android.js | 5 + app/components/Main/index.js | 2 +- scripts/postinstall.sh | 2 + 8 files changed, 299 insertions(+), 46 deletions(-) create mode 100644 android/app/src/main/java/com/metamask/CustomWebview/InputStreamWithInjectedJS.java diff --git a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java b/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java index 4f25c63d0cd..b497da52cdf 100644 --- a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java +++ b/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java @@ -7,25 +7,14 @@ package com.metamask.CustomWebview; import android.annotation.TargetApi; -import android.content.Context; -import com.facebook.react.uimanager.UIManagerModule; -import java.util.LinkedList; -import java.util.List; -import java.util.regex.Pattern; -import javax.annotation.Nullable; - -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - import android.content.ActivityNotFoundException; +import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Picture; import android.net.Uri; import android.os.Build; +import android.support.annotation.RequiresApi; import android.text.TextUtils; import android.util.Log; import android.view.ViewGroup.LayoutParams; @@ -33,13 +22,19 @@ import android.webkit.CookieManager; import android.webkit.GeolocationPermissions; import android.webkit.JavascriptInterface; +import android.webkit.ServiceWorkerClient; +import android.webkit.ServiceWorkerController; import android.webkit.WebChromeClient; +import android.webkit.WebResourceRequest; +import android.webkit.WebResourceResponse; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; + import com.facebook.common.logging.FLog; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.LifecycleEventListener; +import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; @@ -51,19 +46,45 @@ import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.events.ContentSizeChangeEvent; import com.facebook.react.uimanager.events.Event; import com.facebook.react.uimanager.events.EventDispatcher; +import com.facebook.react.views.webview.ReactWebViewManager; +import com.facebook.react.views.webview.WebViewConfig; import com.facebook.react.views.webview.events.TopLoadingErrorEvent; import com.facebook.react.views.webview.events.TopLoadingFinishEvent; import com.facebook.react.views.webview.events.TopLoadingStartEvent; import com.facebook.react.views.webview.events.TopMessageEvent; -import com.facebook.react.views.webview.WebViewConfig; import org.json.JSONException; import org.json.JSONObject; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Pattern; + +import javax.annotation.Nullable; + +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.OkHttpClient.Builder; + + +import static okhttp3.internal.Util.UTF_8; + /** * Manages instances of {@link WebView} * @@ -86,13 +107,18 @@ * - canGoForward - boolean, whether it is possible to request GO_FORWARD command */ @ReactModule(name = CustomWebviewManager.REACT_CLASS) -public class CustomWebviewManager extends SimpleViewManager { +public class CustomWebviewManager extends ReactWebViewManager { protected static final String REACT_CLASS = "CustomWebview"; + public final static String HEADER_CONTENT_TYPE = "content-type"; + private static final String MIME_TEXT_HTML = "text/html"; + private static final String MIME_UNKNOWN = "application/octet-stream"; protected static final String HTML_ENCODING = "UTF-8"; protected static final String HTML_MIME_TYPE = "text/html"; + protected static final String BRIDGE_NAME = "__REACT_WEB_VIEW_BRIDGE"; + private OkHttpClient httpClient; protected static final String HTTP_METHOD_POST = "POST"; @@ -108,9 +134,12 @@ public class CustomWebviewManager extends SimpleViewManager { protected static final String BLANK_URL = "about:blank"; protected WebViewConfig mWebViewConfig; + private static ReactApplicationContext reactNativeContext; + private static boolean debug; + private CustomWebviewPackage pkg; protected @Nullable WebView.PictureListener mPictureListener; - protected static class CustomWebviewClient extends WebViewClient { + protected class CustomWebviewClient extends WebViewClient { protected boolean mLastLoadFailed = false; protected @Nullable ReadableArray mUrlPrefixesForDefaultIntent; @@ -146,28 +175,28 @@ public void onPageStarted(final WebView webView, String url, Bitmap favicon) { @Override - public boolean shouldOverrideUrlLoading(WebView view, String url) { - if (url.equals(BLANK_URL)) return false; - - // url blacklisting - if (mUrlPrefixesForDefaultIntent != null && mUrlPrefixesForDefaultIntent.size() > 0) { - ArrayList urlPrefixesForDefaultIntent = - mUrlPrefixesForDefaultIntent.toArrayList(); - for (Object urlPrefix : urlPrefixesForDefaultIntent) { - if (url.startsWith((String) urlPrefix)) { - launchIntent(view.getContext(), url); - return true; - } + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { + if (request == null || view == null) { + return false; + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + /* + * In order to follow redirects properly, we return null in interceptRequest(). + * Doing this breaks the web3 injection on the resulting page, so we have to reload to + * make sure web3 is available. + * */ + if (request.isForMainFrame() && request.isRedirect()) { + view.loadUrl(request.getUrl().toString()); + return true; } } + /* + * API < 24: TODO: implement based on https://github.com/toshiapp/toshi-android-client/blob/f4840d3d24ff60223662eddddceca8586a1be8bb/app/src/main/java/com/toshi/view/activity/webView/ToshiWebClient.kt#L99 + * */ + return super.shouldOverrideUrlLoading(view, request); + } - if (mOriginWhitelist != null && shouldHandleURL(mOriginWhitelist, url)) { - return false; - } - launchIntent(view.getContext(), url); - return true; - } private void launchIntent(Context context, String url) { try { @@ -215,6 +244,16 @@ public void onReceivedError( new TopLoadingErrorEvent(webView.getId(), eventData)); } + @Override + public void doUpdateVisitedHistory(WebView webView, String url, boolean isReload) { + super.doUpdateVisitedHistory(webView, url, isReload); + dispatchEvent( + webView, + new TopLoadingStartEvent( + webView.getId(), + createWebViewEvent(webView, url))); + } + protected void emitFinishEvent(WebView webView, String url) { dispatchEvent( webView, @@ -236,6 +275,27 @@ protected WritableMap createWebViewEvent(WebView webView, String url) { return event; } + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, String url) { + return null; + } + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { + Log.d("CustomWebview", "shouldInterceptRequest / WebViewClient"); + WebResourceResponse response = null; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + response = CustomWebviewManager.this.shouldInterceptRequest(request, true, (CustomWebview) view); + if (response != null) { + Log.d("CustomWebview", "shouldInterceptRequest / WebViewClient -> return intercept response"); + return response; + } + } + + Log.d("CustomWebview", "shouldInterceptRequest / WebViewClient -> intercept response is nil, delegating up"); + return super.shouldInterceptRequest(view, request); + } + + public void setUrlPrefixesForDefaultIntent(ReadableArray specialUrls) { mUrlPrefixesForDefaultIntent = specialUrls; } @@ -251,6 +311,7 @@ public void setOriginWhitelist(List originWhitelist) { */ protected static class CustomWebview extends WebView implements LifecycleEventListener { protected @Nullable String injectedJS; + protected @Nullable String injectedOnStartLoadingJS; protected boolean messagingEnabled = false; protected @Nullable CustomWebviewClient mCustomWebviewClient; @@ -307,6 +368,10 @@ public void setInjectedJavaScript(@Nullable String js) { injectedJS = js; } + public void setInjectedOnStartLoadingJavaScript(@Nullable String js) { + injectedOnStartLoadingJS = js; + } + protected CustomWebviewBridge createCustomWebviewBridge(CustomWebview webView) { return new CustomWebviewBridge(webView); } @@ -367,22 +432,87 @@ protected void cleanupCallbacksAndDestroy() { } } - public CustomWebviewManager() { + public CustomWebviewManager(ReactApplicationContext context, CustomWebviewPackage pkg) { + this.reactNativeContext = context; + this.pkg = pkg; + Builder b = new Builder(); + httpClient = b + .followRedirects(false) + .followSslRedirects(false) + .build(); mWebViewConfig = new WebViewConfig() { public void configWebView(WebView webView) { } }; } - public CustomWebviewManager(WebViewConfig webViewConfig) { - mWebViewConfig = webViewConfig; - } - @Override public String getName() { return REACT_CLASS; } + public static Boolean urlStringLooksInvalid(String urlString) { + return urlString == null || + urlString.trim().equals("") || + !(urlString.startsWith("http") && !urlString.startsWith("www")) || + urlString.contains("|"); + } + + public static Boolean responseRequiresJSInjection(Response response) { + // we don't want to inject JS into redirects + if (response.isRedirect()) { + return false; + } + // ...okhttp appends charset to content type sometimes, like "text/html; charset=UTF8" + final String contentTypeAndCharset = response.header(HEADER_CONTENT_TYPE, MIME_UNKNOWN); + // ...and we only want to inject it in to HTML, really + return contentTypeAndCharset.startsWith(MIME_TEXT_HTML); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public WebResourceResponse shouldInterceptRequest(WebResourceRequest request, Boolean onlyMainFrame, CustomWebview webView) { + Uri url = request.getUrl(); + String urlStr = url.toString(); + Log.d("CustomWebview","new request "); + Log.d("CustomWebview","url " + urlStr); + Log.d("CustomWebview","host " + request.getUrl().getHost()); + Log.d("CustomWebview","path " + request.getUrl().getPath()); + Log.d("CustomWebview","main " + request.isForMainFrame()); + Log.d("CustomWebview","headers " + request.getRequestHeaders().toString()); + Log.d("CustomWebview","method " + request.getMethod()); + if (onlyMainFrame && !request.isForMainFrame()) { + return null; + } + if (CustomWebviewManager.urlStringLooksInvalid(urlStr)) { + return null; + } + try { + Request req = new Request.Builder() + .url(urlStr) + //.header("User-Agent", userAgent) + .build(); + Response response = httpClient.newCall(req).execute(); + Log.d("CustomWebview", "response headers " + response.headers().toString()); + Log.d("CustomWebview", "response code " + response.code()); + Log.d("CustomWebview", "response ok? " + response.isSuccessful()); + if (!CustomWebviewManager.responseRequiresJSInjection(response)) { + return null; + } + InputStream is = response.body().byteStream(); + MediaType contentType = response.body().contentType(); + Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8; + if (response.code() == HttpURLConnection.HTTP_OK) { + is = new InputStreamWithInjectedJS(is, webView.injectedOnStartLoadingJS, charset); + } + Log.d("CustomWebview", "inject our custom JS to this request"); + return new WebResourceResponse("text/html", charset.name(), is); + } catch (IOException e) { + return null; + } + } + + + protected CustomWebview createCustomWebviewInstance(ThemedReactContext reactContext) { return new CustomWebview(reactContext); } @@ -441,6 +571,23 @@ public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermiss WebView.setWebContentsDebuggingEnabled(true); } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + ServiceWorkerController swController = ServiceWorkerController.getInstance(); + swController.setServiceWorkerClient(new ServiceWorkerClient() { + @Override + public WebResourceResponse shouldInterceptRequest(WebResourceRequest request) { + Log.d("CustomWebview", "shouldInterceptRequest / ServiceWorkerClient"); + WebResourceResponse response = CustomWebviewManager.this.shouldInterceptRequest(request, false, webView); + if (response != null) { + Log.d("CustomWebview", "shouldInterceptRequest / ServiceWorkerClient -> return intersept response"); + return response; + } + Log.d("CustomWebview", "shouldInterceptRequest / ServiceWorkerClient -> intercept response is nil, delegating up"); + return super.shouldInterceptRequest(request); + } + }); + } + return webView; } @@ -496,6 +643,11 @@ public void setInjectedJavaScript(WebView view, @Nullable String injectedJavaScr ((CustomWebview) view).setInjectedJavaScript(injectedJavaScript); } + @ReactProp(name = "injectedOnStartLoadingJavaScript") + public void setInjectedOnStartLoadingJavaScript(WebView view, @Nullable String injectedJavaScript) { + ((CustomWebview) view).setInjectedOnStartLoadingJavaScript(injectedJavaScript); + } + @ReactProp(name = "messagingEnabled") public void setMessagingEnabled(WebView view, boolean enabled) { ((CustomWebview) view).setMessagingEnabled(enabled); diff --git a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewPackage.java b/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewPackage.java index 9a7390aa1fc..b752d1ac750 100644 --- a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewPackage.java +++ b/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewPackage.java @@ -14,7 +14,7 @@ public class CustomWebviewPackage implements ReactPackage { public List createViewManagers( ReactApplicationContext reactContext) { return Collections.singletonList( - new CustomWebviewManager() + new CustomWebviewManager(reactContext,this) ); } diff --git a/android/app/src/main/java/com/metamask/CustomWebview/InputStreamWithInjectedJS.java b/android/app/src/main/java/com/metamask/CustomWebview/InputStreamWithInjectedJS.java new file mode 100644 index 00000000000..90f2f57531c --- /dev/null +++ b/android/app/src/main/java/com/metamask/CustomWebview/InputStreamWithInjectedJS.java @@ -0,0 +1,85 @@ +package com.metamask.CustomWebview; + +import android.util.Log; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; +import java.util.HashMap; +import java.util.Map; + +import static java.nio.charset.StandardCharsets.*; + +public class InputStreamWithInjectedJS extends InputStream { + private InputStream pageIS; + private InputStream scriptIS; + private Charset charset; + private static final String TAG = "InputStreamWithInjectedJS"; + private static Map script = new HashMap<>(); + private boolean hasJS = false; + private boolean headWasFound = false; + private boolean scriptWasInjected = false; + private StringBuffer contentBuffer = new StringBuffer(); + private static Charset getCharset(String charsetName) { + Charset cs = UTF_8; + try { + if (charsetName != null) { + cs = Charset.forName(charsetName); + } + } catch (UnsupportedCharsetException e) { + Log.d("InputStreamJS", "wrong charset: " + charsetName); + } + return cs; + } + private static InputStream getScript(Charset charset) { + String js = script.get(charset); + if (js == null) { + String defaultJs = script.get(UTF_8); + js = new String(defaultJs.getBytes(UTF_8), charset); + script.put(charset, js); + } + return new ByteArrayInputStream(js.getBytes(charset)); + } + InputStreamWithInjectedJS(InputStream is, String js, Charset charset) { + if (js == null) { + this.pageIS = is; + } else { + this.hasJS = true; + this.charset = charset; + Charset cs = UTF_8; + String jsScript = ""; + script.put(cs, jsScript); + this.pageIS = is; + } + } + @Override + public int read() throws IOException { + if (scriptWasInjected || !hasJS) { + return pageIS.read(); + } + if (!scriptWasInjected && headWasFound) { + int nextByte = scriptIS.read(); + if (nextByte == -1) { + scriptIS.close(); + scriptWasInjected = true; + return pageIS.read(); + } else { + return nextByte; + } + } + if (!headWasFound) { + int nextByte = pageIS.read(); + contentBuffer.append((char) nextByte); + int bufferLength = contentBuffer.length(); + if (nextByte == 62 && bufferLength >= 6) { + if (contentBuffer.substring(bufferLength - 6).equals("")) { + this.scriptIS = getScript(this.charset); + headWasFound = true; + } + } + return nextByte; + } + return pageIS.read(); + } +} diff --git a/android/build.gradle b/android/build.gradle index 8a0dc15e4c2..f301fd2c783 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -7,9 +7,10 @@ buildscript { url 'https://maven.google.com/' name 'Google' } + google() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.0' + classpath 'com.android.tools.build:gradle:3.1.4' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -32,9 +33,9 @@ allprojects { } ext { - buildToolsVersion = "26.0.3" + buildToolsVersion = "27.0.3" minSdkVersion = 18 - compileSdkVersion = 26 - targetSdkVersion = 26 + compileSdkVersion = 27 + targetSdkVersion = 27 supportLibVersion = "26.1.0" } diff --git a/app/components/Browser/index.js b/app/components/Browser/index.js index 7b7e9796ab6..717f0ad751d 100644 --- a/app/components/Browser/index.js +++ b/app/components/Browser/index.js @@ -156,6 +156,14 @@ export class Browser extends Component { render() { const { canGoBack, canGoForward, entryScriptWeb3, inputValue, url } = this.state; + const injectionProps = {}; + + if (Platform.OS === 'android') { + injectionProps.injectedOnStartLoadingJavaScript = entryScriptWeb3; + } else { + injectionProps.injectJavaScript = entryScriptWeb3; + } + return ( @@ -192,7 +200,7 @@ export class Browser extends Component { Date: Fri, 31 Aug 2018 23:27:42 -0400 Subject: [PATCH 02/12] fix reload --- .../com/metamask/CustomWebview/CustomWebviewManager.java | 1 - app/components/Browser/index.js | 2 +- app/core/InpageBridge.js | 9 ++++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java b/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java index b497da52cdf..b9ed21d0476 100644 --- a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java +++ b/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java @@ -489,7 +489,6 @@ public WebResourceResponse shouldInterceptRequest(WebResourceRequest request, Bo try { Request req = new Request.Builder() .url(urlStr) - //.header("User-Agent", userAgent) .build(); Response response = httpClient.newCall(req).execute(); Log.d("CustomWebview", "response headers " + response.headers().toString()); diff --git a/app/components/Browser/index.js b/app/components/Browser/index.js index 717f0ad751d..b6d73fe39be 100644 --- a/app/components/Browser/index.js +++ b/app/components/Browser/index.js @@ -194,7 +194,7 @@ export class Browser extends Component { style={styles.urlInput} value={inputValue} /> - + diff --git a/app/core/InpageBridge.js b/app/core/InpageBridge.js index 3b6e6bfc297..521996a86c6 100644 --- a/app/core/InpageBridge.js +++ b/app/core/InpageBridge.js @@ -118,4 +118,11 @@ class InpageBridge { window.ethereum = new InpageBridge(); -window.originalPostMessage({ type: 'ETHEREUM_PROVIDER_SUCCESS' }, '*'); +function safePostMessage(msg) { + if (window.originalPostMessage) { + window.originalPostMessage(msg, '*'); + } else { + window.postMessage(msg, '*'); + } +} +safePostMessage({ type: 'ETHEREUM_PROVIDER_SUCCESS' }); From c0a93a78b22a04786eca2971944fc63ab7571c0f Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Sat, 1 Sep 2018 00:33:39 -0400 Subject: [PATCH 03/12] progress bar working on android --- .../CustomWebview/CustomWebviewManager.java | 23 ++++++++++++++ .../metamask/CustomWebview/ProgressEvent.java | 30 +++++++++++++++++++ app/components/CustomWebview/index.android.js | 7 +++++ 3 files changed, 60 insertions(+) create mode 100644 android/app/src/main/java/com/metamask/CustomWebview/ProgressEvent.java diff --git a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java b/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java index b9ed21d0476..26bd6d20400 100644 --- a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java +++ b/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java @@ -51,6 +51,7 @@ import com.facebook.react.uimanager.events.ContentSizeChangeEvent; import com.facebook.react.uimanager.events.Event; import com.facebook.react.uimanager.events.EventDispatcher; +import com.facebook.react.uimanager.events.RCTEventEmitter; import com.facebook.react.views.webview.ReactWebViewManager; import com.facebook.react.views.webview.WebViewConfig; import com.facebook.react.views.webview.events.TopLoadingErrorEvent; @@ -430,6 +431,15 @@ protected void cleanupCallbacksAndDestroy() { setWebViewClient(null); destroy(); } + + private void reactNativeEvent(String eventName, String message) { + WritableMap event = Arguments.createMap(); + event.putString("message", message); + ReactContext reactContext = (ReactContext) this.getContext(); + reactContext + .getJSModule(RCTEventEmitter.class) + .receiveEvent(this.getId(), eventName, event); + } } public CustomWebviewManager(ReactApplicationContext context, CustomWebviewPackage pkg) { @@ -533,11 +543,14 @@ public boolean onConsoleMessage(ConsoleMessage message) { return true; } public void onProgressChanged(WebView view, int progress) { + dispatchEvent(view, new ProgressEvent(view.getId(), progress)); if(webView.getProgress() >= 10){ webView.linkBridge(); } + Log.d("CustomWebviewProgress", Integer.toString(webView.getProgress())); + } @Override @@ -854,4 +867,14 @@ protected static void dispatchEvent(WebView webView, Event event) { reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); eventDispatcher.dispatchEvent(event); } + + @Override + public @Nullable Map getExportedCustomBubblingEventTypeConstants() { + return MapBuilder.builder() + .put("progress", + MapBuilder.of( + "phasedRegistrationNames", + MapBuilder.of("bubbled", "onProgress"))) + .build(); + } } diff --git a/android/app/src/main/java/com/metamask/CustomWebview/ProgressEvent.java b/android/app/src/main/java/com/metamask/CustomWebview/ProgressEvent.java new file mode 100644 index 00000000000..bc35742f44a --- /dev/null +++ b/android/app/src/main/java/com/metamask/CustomWebview/ProgressEvent.java @@ -0,0 +1,30 @@ +package com.metamask.CustomWebview; + +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.uimanager.events.Event; +import com.facebook.react.uimanager.events.RCTEventEmitter; + +public class ProgressEvent extends Event { + + public static final String EVENT_NAME = "progress"; + + private final int mProgress; + + public ProgressEvent(int viewId, int progress) { + super(viewId); + mProgress = progress; + } + + @Override + public String getEventName() { + return EVENT_NAME; + } + + @Override + public void dispatch(RCTEventEmitter rctEventEmitter) { + WritableMap data = Arguments.createMap(); + data.putInt("progress", mProgress); + rctEventEmitter.receiveEvent(getViewTag(), EVENT_NAME, data); + } +} diff --git a/app/components/CustomWebview/index.android.js b/app/components/CustomWebview/index.android.js index e8d0edac584..12e1f40f9d4 100644 --- a/app/components/CustomWebview/index.android.js +++ b/app/components/CustomWebview/index.android.js @@ -62,6 +62,7 @@ export default class WebView extends React.Component { onLoadEnd: PropTypes.func, onLoadStart: PropTypes.func, onError: PropTypes.func, + onProgress: PropTypes.func, automaticallyAdjustContentInsets: PropTypes.bool, contentInset: EdgeInsetsPropType, onNavigationStateChange: PropTypes.func, @@ -314,6 +315,7 @@ export default class WebView extends React.Component { domStorageEnabled={this.props.domStorageEnabled} messagingEnabled={typeof this.props.onMessage === 'function'} onMessage={this.onMessage} + onProgress={this.onProgress} contentInset={this.props.contentInset} automaticallyAdjustContentInsets={this.props.automaticallyAdjustContentInsets} onContentSizeChange={this.props.onContentSizeChange} @@ -423,6 +425,11 @@ export default class WebView extends React.Component { this.updateNavigationState(event); }; + onProgress = event => { + const { onProgress } = this.props; + onProgress && onProgress(parseFloat(event.nativeEvent.progress / 100)); + }; + onMessage = event => { const { onMessage } = this.props; onMessage && onMessage(event); From bea9ee98a4b6e7d19064472805ff6428f6686b0f Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Sat, 1 Sep 2018 02:32:16 -0400 Subject: [PATCH 04/12] working like a charm --- .../CustomWebview/CustomWebviewManager.java | 28 +++-------- .../InputStreamWithInjectedJS.java | 15 ++++-- android/build.gradle | 2 +- app/components/Browser/index.js | 46 +++++++++++++------ app/components/CustomWebview/index.android.js | 12 ++--- 5 files changed, 56 insertions(+), 47 deletions(-) diff --git a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java b/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java index 26bd6d20400..2ffada9c126 100644 --- a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java +++ b/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java @@ -175,25 +175,21 @@ public void onPageStarted(final WebView webView, String url, Bitmap favicon) { } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { if (request == null || view == null) { return false; } + + // This works only for API 24+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - /* - * In order to follow redirects properly, we return null in interceptRequest(). - * Doing this breaks the web3 injection on the resulting page, so we have to reload to - * make sure web3 is available. - * */ if (request.isForMainFrame() && request.isRedirect()) { view.loadUrl(request.getUrl().toString()); return true; } } - /* - * API < 24: TODO: implement based on https://github.com/toshiapp/toshi-android-client/blob/f4840d3d24ff60223662eddddceca8586a1be8bb/app/src/main/java/com/toshi/view/activity/webView/ToshiWebClient.kt#L99 - * */ + return super.shouldOverrideUrlLoading(view, request); } @@ -431,15 +427,6 @@ protected void cleanupCallbacksAndDestroy() { setWebViewClient(null); destroy(); } - - private void reactNativeEvent(String eventName, String message) { - WritableMap event = Arguments.createMap(); - event.putString("message", message); - ReactContext reactContext = (ReactContext) this.getContext(); - reactContext - .getJSModule(RCTEventEmitter.class) - .receiveEvent(this.getId(), eventName, event); - } } public CustomWebviewManager(ReactApplicationContext context, CustomWebviewPackage pkg) { @@ -469,13 +456,10 @@ public static Boolean urlStringLooksInvalid(String urlString) { } public static Boolean responseRequiresJSInjection(Response response) { - // we don't want to inject JS into redirects if (response.isRedirect()) { return false; } - // ...okhttp appends charset to content type sometimes, like "text/html; charset=UTF8" final String contentTypeAndCharset = response.header(HEADER_CONTENT_TYPE, MIME_UNKNOWN); - // ...and we only want to inject it in to HTML, really return contentTypeAndCharset.startsWith(MIME_TEXT_HTML); } @@ -511,11 +495,13 @@ public WebResourceResponse shouldInterceptRequest(WebResourceRequest request, Bo MediaType contentType = response.body().contentType(); Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8; if (response.code() == HttpURLConnection.HTTP_OK) { - is = new InputStreamWithInjectedJS(is, webView.injectedOnStartLoadingJS, charset); + is = new InputStreamWithInjectedJS(is, webView.injectedOnStartLoadingJS, charset, webView.getContext()); } Log.d("CustomWebview", "inject our custom JS to this request"); return new WebResourceResponse("text/html", charset.name(), is); } catch (IOException e) { + Log.e("CustomWebview", "injection failed"); + Log.e("CustomWebview", e.toString()); return null; } } diff --git a/android/app/src/main/java/com/metamask/CustomWebview/InputStreamWithInjectedJS.java b/android/app/src/main/java/com/metamask/CustomWebview/InputStreamWithInjectedJS.java index 90f2f57531c..c3e27ce3bce 100644 --- a/android/app/src/main/java/com/metamask/CustomWebview/InputStreamWithInjectedJS.java +++ b/android/app/src/main/java/com/metamask/CustomWebview/InputStreamWithInjectedJS.java @@ -1,6 +1,13 @@ package com.metamask.CustomWebview; +import android.content.Context; +import android.content.res.Resources; +import android.os.Build; +import android.support.annotation.RequiresApi; import android.util.Log; + +import com.metamask.R; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -9,8 +16,10 @@ import java.util.HashMap; import java.util.Map; -import static java.nio.charset.StandardCharsets.*; +import io.fabric.sdk.android.services.common.CommonUtils; +import static java.nio.charset.StandardCharsets.*; +@RequiresApi(api = Build.VERSION_CODES.KITKAT) public class InputStreamWithInjectedJS extends InputStream { private InputStream pageIS; private InputStream scriptIS; @@ -28,7 +37,7 @@ private static Charset getCharset(String charsetName) { cs = Charset.forName(charsetName); } } catch (UnsupportedCharsetException e) { - Log.d("InputStreamJS", "wrong charset: " + charsetName); + Log.d("CustomWebview", "wrong charset: " + charsetName); } return cs; } @@ -41,7 +50,7 @@ private static InputStream getScript(Charset charset) { } return new ByteArrayInputStream(js.getBytes(charset)); } - InputStreamWithInjectedJS(InputStream is, String js, Charset charset) { + InputStreamWithInjectedJS(InputStream is, String js, Charset charset, Context c) { if (js == null) { this.pageIS = is; } else { diff --git a/android/build.gradle b/android/build.gradle index f301fd2c783..3fa514c2ec2 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -34,7 +34,7 @@ allprojects { ext { buildToolsVersion = "27.0.3" - minSdkVersion = 18 + minSdkVersion = 19 compileSdkVersion = 27 targetSdkVersion = 27 supportLibVersion = "26.1.0" diff --git a/app/components/Browser/index.js b/app/components/Browser/index.js index b6d73fe39be..73535e13031 100644 --- a/app/components/Browser/index.js +++ b/app/components/Browser/index.js @@ -7,7 +7,7 @@ import PropTypes from 'prop-types'; import RNFS from 'react-native-fs'; import getNavbarOptions from '../Navbar'; import WebviewProgressBar from '../WebviewProgressBar'; -import { Platform, StyleSheet, TextInput, View } from 'react-native'; +import { ActivityIndicator, Platform, StyleSheet, TextInput, View } from 'react-native'; import { colors, baseStyles, fontStyles } from '../../styles/common'; import { connect } from 'react-redux'; import Networks from '../../util/networks'; @@ -42,6 +42,12 @@ const styles = StyleSheet.create({ progressBarWrapper: { height: 3, marginTop: -5 + }, + loader: { + backgroundColor: colors.white, + flex: 1, + justifyContent: 'center', + alignItems: 'center' } }); @@ -154,6 +160,14 @@ export class Browser extends Component { this.setState({ progress }); }; + renderLoader() { + return ( + + + + ); + } + render() { const { canGoBack, canGoForward, entryScriptWeb3, inputValue, url } = this.state; const injectionProps = {}; @@ -199,19 +213,23 @@ export class Browser extends Component { - + {entryScriptWeb3 ? ( + + ) : ( + this.renderLoader() + )} ); } diff --git a/app/components/CustomWebview/index.android.js b/app/components/CustomWebview/index.android.js index 12e1f40f9d4..77e640a5eff 100644 --- a/app/components/CustomWebview/index.android.js +++ b/app/components/CustomWebview/index.android.js @@ -20,7 +20,8 @@ import { const styles = StyleSheet.create({ container: { - flex: 1 + flex: 1, + backgroundColor: 'white' // eslint-disable-line }, hidden: { height: 0, @@ -270,7 +271,7 @@ export default class WebView extends React.Component { }; render() { - let otherView = null; + let otherView = null; // eslint-disable-line no-unused-vars if (this.state.viewState === WebViewState.LOADING) { otherView = (this.props.renderLoading || defaultRenderLoading)(); @@ -334,12 +335,7 @@ export default class WebView extends React.Component { /> ); - return ( - - {webView} - {otherView} - - ); + return {webView}; } goForward = () => { From d19bb4a277a725874beeef9d00c5d32ff640e611 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Sat, 1 Sep 2018 03:58:33 -0400 Subject: [PATCH 05/12] migrate to react-native-web3-webview --- android/app/build.gradle | 1 + .../CustomWebview/CustomWebviewManager.java | 866 ------------------ .../CustomWebview/CustomWebviewPackage.java | 27 - .../InputStreamWithInjectedJS.java | 94 -- .../metamask/CustomWebview/ProgressEvent.java | 30 - .../java/com/metamask/MainApplication.java | 6 +- android/settings.gradle | 2 + app/components/Browser/index.js | 8 +- .../__snapshots__/index.test.js.snap | 72 -- app/components/CustomWebview/index.android.js | 433 --------- app/components/CustomWebview/index.ios.js | 5 - app/components/CustomWebview/index.test.js | 21 - ios/MetaMask.xcodeproj/project.pbxproj | 95 +- package-lock.json | 6 +- package.json | 2 +- scripts/postinstall.sh | 24 +- 16 files changed, 81 insertions(+), 1611 deletions(-) delete mode 100644 android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java delete mode 100644 android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewPackage.java delete mode 100644 android/app/src/main/java/com/metamask/CustomWebview/InputStreamWithInjectedJS.java delete mode 100644 android/app/src/main/java/com/metamask/CustomWebview/ProgressEvent.java delete mode 100644 app/components/CustomWebview/__snapshots__/index.test.js.snap delete mode 100644 app/components/CustomWebview/index.android.js delete mode 100644 app/components/CustomWebview/index.ios.js delete mode 100644 app/components/CustomWebview/index.test.js diff --git a/android/app/build.gradle b/android/app/build.gradle index fd77ff6783d..cd303db9c1e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -163,6 +163,7 @@ android { } dependencies { + compile project(':react-native-web3-webview') compile project(':react-native-camera') compile project(':react-native-share') compile project(':react-native-i18n') diff --git a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java b/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java deleted file mode 100644 index 2ffada9c126..00000000000 --- a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewManager.java +++ /dev/null @@ -1,866 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.metamask.CustomWebview; -import android.annotation.TargetApi; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.Picture; -import android.net.Uri; -import android.os.Build; -import android.support.annotation.RequiresApi; -import android.text.TextUtils; -import android.util.Log; -import android.view.ViewGroup.LayoutParams; -import android.webkit.ConsoleMessage; -import android.webkit.CookieManager; -import android.webkit.GeolocationPermissions; -import android.webkit.JavascriptInterface; -import android.webkit.ServiceWorkerClient; -import android.webkit.ServiceWorkerController; -import android.webkit.WebChromeClient; -import android.webkit.WebResourceRequest; -import android.webkit.WebResourceResponse; -import android.webkit.WebSettings; -import android.webkit.WebView; -import android.webkit.WebViewClient; - -import com.facebook.common.logging.FLog; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.LifecycleEventListener; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.ReadableMapKeySetIterator; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.common.MapBuilder; -import com.facebook.react.common.ReactConstants; -import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.module.annotations.ReactModule; -import com.facebook.react.uimanager.SimpleViewManager; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.UIManagerModule; -import com.facebook.react.uimanager.annotations.ReactProp; -import com.facebook.react.uimanager.events.ContentSizeChangeEvent; -import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.EventDispatcher; -import com.facebook.react.uimanager.events.RCTEventEmitter; -import com.facebook.react.views.webview.ReactWebViewManager; -import com.facebook.react.views.webview.WebViewConfig; -import com.facebook.react.views.webview.events.TopLoadingErrorEvent; -import com.facebook.react.views.webview.events.TopLoadingFinishEvent; -import com.facebook.react.views.webview.events.TopLoadingStartEvent; -import com.facebook.react.views.webview.events.TopMessageEvent; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.HttpURLConnection; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.regex.Pattern; - -import javax.annotation.Nullable; - -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import okhttp3.OkHttpClient.Builder; - - -import static okhttp3.internal.Util.UTF_8; - -/** - * Manages instances of {@link WebView} - * - * Can accept following commands: - * - GO_BACK - * - GO_FORWARD - * - RELOAD - * - * {@link WebView} instances could emit following direct events: - * - topLoadingFinish - * - topLoadingStart - * - topLoadingError - * - * Each event will carry the following properties: - * - target - view's react tag - * - url - url set for the webview - * - loading - whether webview is in a loading state - * - title - title of the current page - * - canGoBack - boolean, whether there is anything on a history stack to go back - * - canGoForward - boolean, whether it is possible to request GO_FORWARD command - */ -@ReactModule(name = CustomWebviewManager.REACT_CLASS) -public class CustomWebviewManager extends ReactWebViewManager { - - protected static final String REACT_CLASS = "CustomWebview"; - - public final static String HEADER_CONTENT_TYPE = "content-type"; - private static final String MIME_TEXT_HTML = "text/html"; - private static final String MIME_UNKNOWN = "application/octet-stream"; - protected static final String HTML_ENCODING = "UTF-8"; - protected static final String HTML_MIME_TYPE = "text/html"; - - protected static final String BRIDGE_NAME = "__REACT_WEB_VIEW_BRIDGE"; - private OkHttpClient httpClient; - - protected static final String HTTP_METHOD_POST = "POST"; - - public static final int COMMAND_GO_BACK = 1; - public static final int COMMAND_GO_FORWARD = 2; - public static final int COMMAND_RELOAD = 3; - public static final int COMMAND_STOP_LOADING = 4; - public static final int COMMAND_POST_MESSAGE = 5; - public static final int COMMAND_INJECT_JAVASCRIPT = 6; - - // Use `webView.loadUrl("about:blank")` to reliably reset the view - // state and release page resources (including any running JavaScript). - protected static final String BLANK_URL = "about:blank"; - - protected WebViewConfig mWebViewConfig; - private static ReactApplicationContext reactNativeContext; - private static boolean debug; - private CustomWebviewPackage pkg; - protected @Nullable WebView.PictureListener mPictureListener; - - protected class CustomWebviewClient extends WebViewClient { - - protected boolean mLastLoadFailed = false; - protected @Nullable ReadableArray mUrlPrefixesForDefaultIntent; - protected @Nullable List mOriginWhitelist; - - - @Override - public void onPageFinished(WebView webView, String url) { - Log.d("CustomWebview", "onPageFinished: "+url); - super.onPageFinished(webView, url); - - if (!mLastLoadFailed) { - CustomWebview customWebview = (CustomWebview) webView; - customWebview.callInjectedJavaScript(); - emitFinishEvent(webView, url); - customWebview.linkBridge(); - } - } - - @Override - public void onPageStarted(final WebView webView, String url, Bitmap favicon) { - Log.d("CustomWebview", "onPageStarted: "+url); - super.onPageStarted(webView, url, favicon); - - mLastLoadFailed = false; - dispatchEvent( - webView, - new TopLoadingStartEvent( - webView.getId(), - createWebViewEvent(webView, url))); - CustomWebview customWebview = (CustomWebview) webView; - } - - - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - @Override - public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { - if (request == null || view == null) { - return false; - } - - // This works only for API 24+ - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - if (request.isForMainFrame() && request.isRedirect()) { - view.loadUrl(request.getUrl().toString()); - return true; - } - } - - return super.shouldOverrideUrlLoading(view, request); - } - - - - private void launchIntent(Context context, String url) { - try { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.addCategory(Intent.CATEGORY_BROWSABLE); - context.startActivity(intent); - } catch (ActivityNotFoundException e) { - FLog.w(ReactConstants.TAG, "activity not found to handle uri scheme for: " + url, e); - } - } - - private boolean shouldHandleURL(List originWhitelist, String url) { - Uri uri = Uri.parse(url); - String scheme = uri.getScheme() != null ? uri.getScheme() : ""; - String authority = uri.getAuthority() != null ? uri.getAuthority() : ""; - String urlToCheck = scheme + "://" + authority; - for (Pattern pattern : originWhitelist) { - if (pattern.matcher(urlToCheck).matches()) { - return true; - } - } - return false; - } - - @Override - public void onReceivedError( - WebView webView, - int errorCode, - String description, - String failingUrl) { - super.onReceivedError(webView, errorCode, description, failingUrl); - mLastLoadFailed = true; - - // In case of an error JS side expect to get a finish event first, and then get an error event - // Android WebView does it in the opposite way, so we need to simulate that behavior - emitFinishEvent(webView, failingUrl); - - WritableMap eventData = createWebViewEvent(webView, failingUrl); - eventData.putDouble("code", errorCode); - eventData.putString("description", description); - - dispatchEvent( - webView, - new TopLoadingErrorEvent(webView.getId(), eventData)); - } - - @Override - public void doUpdateVisitedHistory(WebView webView, String url, boolean isReload) { - super.doUpdateVisitedHistory(webView, url, isReload); - dispatchEvent( - webView, - new TopLoadingStartEvent( - webView.getId(), - createWebViewEvent(webView, url))); - } - - protected void emitFinishEvent(WebView webView, String url) { - dispatchEvent( - webView, - new TopLoadingFinishEvent( - webView.getId(), - createWebViewEvent(webView, url))); - } - - protected WritableMap createWebViewEvent(WebView webView, String url) { - WritableMap event = Arguments.createMap(); - event.putDouble("target", webView.getId()); - // Don't use webView.getUrl() here, the URL isn't updated to the new value yet in callbacks - // like onPageFinished - event.putString("url", url); - event.putBoolean("loading", !mLastLoadFailed && webView.getProgress() != 100); - event.putString("title", webView.getTitle()); - event.putBoolean("canGoBack", webView.canGoBack()); - event.putBoolean("canGoForward", webView.canGoForward()); - return event; - } - - @Override - public WebResourceResponse shouldInterceptRequest(WebView view, String url) { - return null; - } - @Override - public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { - Log.d("CustomWebview", "shouldInterceptRequest / WebViewClient"); - WebResourceResponse response = null; - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { - response = CustomWebviewManager.this.shouldInterceptRequest(request, true, (CustomWebview) view); - if (response != null) { - Log.d("CustomWebview", "shouldInterceptRequest / WebViewClient -> return intercept response"); - return response; - } - } - - Log.d("CustomWebview", "shouldInterceptRequest / WebViewClient -> intercept response is nil, delegating up"); - return super.shouldInterceptRequest(view, request); - } - - - public void setUrlPrefixesForDefaultIntent(ReadableArray specialUrls) { - mUrlPrefixesForDefaultIntent = specialUrls; - } - - public void setOriginWhitelist(List originWhitelist) { - mOriginWhitelist = originWhitelist; - } - } - - /** - * Subclass of {@link WebView} that implements {@link LifecycleEventListener} interface in order - * to call {@link WebView#destroy} on activity destroy event and also to clear the client - */ - protected static class CustomWebview extends WebView implements LifecycleEventListener { - protected @Nullable String injectedJS; - protected @Nullable String injectedOnStartLoadingJS; - protected boolean messagingEnabled = false; - protected @Nullable CustomWebviewClient mCustomWebviewClient; - - protected class CustomWebviewBridge { - CustomWebview mContext; - - CustomWebviewBridge(CustomWebview c) { - mContext = c; - } - - @JavascriptInterface - public void postMessage(String message) { - mContext.onMessage(message); - } - } - - /** - * WebView must be created with an context of the current activity - * - * Activity Context is required for creation of dialogs internally by WebView - * Reactive Native needed for access to ReactNative internal system functionality - * - */ - public CustomWebview(ThemedReactContext reactContext) { - super(reactContext); - } - - @Override - public void onHostResume() { - // do nothing - } - - @Override - public void onHostPause() { - // do nothing - } - - @Override - public void onHostDestroy() { - cleanupCallbacksAndDestroy(); - } - - @Override - public void setWebViewClient(WebViewClient client) { - super.setWebViewClient(client); - mCustomWebviewClient = (CustomWebviewClient)client; - } - - public @Nullable CustomWebviewClient getCustomWebviewClient() { - return mCustomWebviewClient; - } - - public void setInjectedJavaScript(@Nullable String js) { - injectedJS = js; - } - - public void setInjectedOnStartLoadingJavaScript(@Nullable String js) { - injectedOnStartLoadingJS = js; - } - - protected CustomWebviewBridge createCustomWebviewBridge(CustomWebview webView) { - return new CustomWebviewBridge(webView); - } - - public void setMessagingEnabled(boolean enabled) { - if (messagingEnabled == enabled) { - return; - } - - messagingEnabled = enabled; - if (enabled) { - addJavascriptInterface(createCustomWebviewBridge(this), BRIDGE_NAME); - Log.d("CustomWebviewBridge", "bridge linking complete"); - } else { - removeJavascriptInterface(BRIDGE_NAME); - } - } - - public void callInjectedJavaScript() { - if (getSettings().getJavaScriptEnabled() && - injectedJS != null && - !TextUtils.isEmpty(injectedJS)) { - loadUrl("javascript:(function() {\n" + injectedJS + ";\n})();"); - } - } - - public void linkBridge() { - if (messagingEnabled) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - evaluateJavascript("(" + - "console.log('postMessage has been polyfilled')," + - "window.originalPostMessage = window.postMessage," + - "window.postMessage = function(data) {" + - BRIDGE_NAME + ".postMessage(JSON.stringify(data));" + - "}" + - ")", null); - - }else{ - loadUrl("javascript:(" + - "console.log('postMessage has been polyfilled')," + - "window.originalPostMessage = window.postMessage," + - "window.postMessage = function(data) {" + - BRIDGE_NAME + ".postMessage(JSON.stringify(data));" + - "}" + - ")"); - } - - } - } - - public void onMessage(String message) { - dispatchEvent(this, new TopMessageEvent(this.getId(), message)); - } - - protected void cleanupCallbacksAndDestroy() { - setWebViewClient(null); - destroy(); - } - } - - public CustomWebviewManager(ReactApplicationContext context, CustomWebviewPackage pkg) { - this.reactNativeContext = context; - this.pkg = pkg; - Builder b = new Builder(); - httpClient = b - .followRedirects(false) - .followSslRedirects(false) - .build(); - mWebViewConfig = new WebViewConfig() { - public void configWebView(WebView webView) { - } - }; - } - - @Override - public String getName() { - return REACT_CLASS; - } - - public static Boolean urlStringLooksInvalid(String urlString) { - return urlString == null || - urlString.trim().equals("") || - !(urlString.startsWith("http") && !urlString.startsWith("www")) || - urlString.contains("|"); - } - - public static Boolean responseRequiresJSInjection(Response response) { - if (response.isRedirect()) { - return false; - } - final String contentTypeAndCharset = response.header(HEADER_CONTENT_TYPE, MIME_UNKNOWN); - return contentTypeAndCharset.startsWith(MIME_TEXT_HTML); - } - - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - public WebResourceResponse shouldInterceptRequest(WebResourceRequest request, Boolean onlyMainFrame, CustomWebview webView) { - Uri url = request.getUrl(); - String urlStr = url.toString(); - Log.d("CustomWebview","new request "); - Log.d("CustomWebview","url " + urlStr); - Log.d("CustomWebview","host " + request.getUrl().getHost()); - Log.d("CustomWebview","path " + request.getUrl().getPath()); - Log.d("CustomWebview","main " + request.isForMainFrame()); - Log.d("CustomWebview","headers " + request.getRequestHeaders().toString()); - Log.d("CustomWebview","method " + request.getMethod()); - if (onlyMainFrame && !request.isForMainFrame()) { - return null; - } - if (CustomWebviewManager.urlStringLooksInvalid(urlStr)) { - return null; - } - try { - Request req = new Request.Builder() - .url(urlStr) - .build(); - Response response = httpClient.newCall(req).execute(); - Log.d("CustomWebview", "response headers " + response.headers().toString()); - Log.d("CustomWebview", "response code " + response.code()); - Log.d("CustomWebview", "response ok? " + response.isSuccessful()); - if (!CustomWebviewManager.responseRequiresJSInjection(response)) { - return null; - } - InputStream is = response.body().byteStream(); - MediaType contentType = response.body().contentType(); - Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8; - if (response.code() == HttpURLConnection.HTTP_OK) { - is = new InputStreamWithInjectedJS(is, webView.injectedOnStartLoadingJS, charset, webView.getContext()); - } - Log.d("CustomWebview", "inject our custom JS to this request"); - return new WebResourceResponse("text/html", charset.name(), is); - } catch (IOException e) { - Log.e("CustomWebview", "injection failed"); - Log.e("CustomWebview", e.toString()); - return null; - } - } - - - - protected CustomWebview createCustomWebviewInstance(ThemedReactContext reactContext) { - return new CustomWebview(reactContext); - } - - @Override - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - protected WebView createViewInstance(ThemedReactContext reactContext) { - final CustomWebview webView = createCustomWebviewInstance(reactContext); - - - webView.setWebChromeClient(new WebChromeClient() { - @Override - public boolean onConsoleMessage(ConsoleMessage message) { - Log.d("CustomWebview", message.message()); - if (ReactBuildConfig.DEBUG) { - return super.onConsoleMessage(message); - } - // Ignore console logs in non debug builds. - return true; - } - public void onProgressChanged(WebView view, int progress) { - dispatchEvent(view, new ProgressEvent(view.getId(), progress)); - - if(webView.getProgress() >= 10){ - webView.linkBridge(); - } - - Log.d("CustomWebviewProgress", Integer.toString(webView.getProgress())); - - } - - @Override - public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) { - callback.invoke(origin, true, false); - } - }); - reactContext.addLifecycleEventListener(webView); - mWebViewConfig.configWebView(webView); - WebSettings settings = webView.getSettings(); - settings.setBuiltInZoomControls(true); - settings.setDisplayZoomControls(false); - settings.setDomStorageEnabled(true); - - settings.setAllowFileAccess(false); - settings.setAllowContentAccess(false); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - settings.setAllowFileAccessFromFileURLs(false); - setAllowUniversalAccessFromFileURLs(webView, false); - } - setMixedContentMode(webView, "never"); - - // Fixes broken full-screen modals/galleries due to body height being 0. - webView.setLayoutParams( - new LayoutParams(LayoutParams.MATCH_PARENT, - LayoutParams.MATCH_PARENT)); - - setGeolocationEnabled(webView, false); - if (ReactBuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - WebView.setWebContentsDebuggingEnabled(true); - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - ServiceWorkerController swController = ServiceWorkerController.getInstance(); - swController.setServiceWorkerClient(new ServiceWorkerClient() { - @Override - public WebResourceResponse shouldInterceptRequest(WebResourceRequest request) { - Log.d("CustomWebview", "shouldInterceptRequest / ServiceWorkerClient"); - WebResourceResponse response = CustomWebviewManager.this.shouldInterceptRequest(request, false, webView); - if (response != null) { - Log.d("CustomWebview", "shouldInterceptRequest / ServiceWorkerClient -> return intersept response"); - return response; - } - Log.d("CustomWebview", "shouldInterceptRequest / ServiceWorkerClient -> intercept response is nil, delegating up"); - return super.shouldInterceptRequest(request); - } - }); - } - - return webView; - } - - @ReactProp(name = "javaScriptEnabled") - public void setJavaScriptEnabled(WebView view, boolean enabled) { - view.getSettings().setJavaScriptEnabled(enabled); - } - - @ReactProp(name = "thirdPartyCookiesEnabled") - public void setThirdPartyCookiesEnabled(WebView view, boolean enabled) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - CookieManager.getInstance().setAcceptThirdPartyCookies(view, enabled); - } - } - - @ReactProp(name = "scalesPageToFit") - public void setScalesPageToFit(WebView view, boolean enabled) { - view.getSettings().setUseWideViewPort(!enabled); - } - - @ReactProp(name = "domStorageEnabled") - public void setDomStorageEnabled(WebView view, boolean enabled) { - view.getSettings().setDomStorageEnabled(enabled); - } - - @ReactProp(name = "userAgent") - public void setUserAgent(WebView view, @Nullable String userAgent) { - if (userAgent != null) { - // TODO(8496850): Fix incorrect behavior when property is unset (uA == null) - view.getSettings().setUserAgentString(userAgent); - } - } - - @ReactProp(name = "mediaPlaybackRequiresUserAction") - public void setMediaPlaybackRequiresUserAction(WebView view, boolean requires) { - if(Build.VERSION.SDK_INT >= 17) { - view.getSettings().setMediaPlaybackRequiresUserGesture(requires); - } - } - - @ReactProp(name = "allowUniversalAccessFromFileURLs") - public void setAllowUniversalAccessFromFileURLs(WebView view, boolean allow) { - view.getSettings().setAllowUniversalAccessFromFileURLs(allow); - } - - @ReactProp(name = "saveFormDataDisabled") - public void setSaveFormDataDisabled(WebView view, boolean disable) { - view.getSettings().setSaveFormData(!disable); - } - - @ReactProp(name = "injectedJavaScript") - public void setInjectedJavaScript(WebView view, @Nullable String injectedJavaScript) { - ((CustomWebview) view).setInjectedJavaScript(injectedJavaScript); - } - - @ReactProp(name = "injectedOnStartLoadingJavaScript") - public void setInjectedOnStartLoadingJavaScript(WebView view, @Nullable String injectedJavaScript) { - ((CustomWebview) view).setInjectedOnStartLoadingJavaScript(injectedJavaScript); - } - - @ReactProp(name = "messagingEnabled") - public void setMessagingEnabled(WebView view, boolean enabled) { - ((CustomWebview) view).setMessagingEnabled(enabled); - } - - @ReactProp(name = "source") - public void setSource(WebView view, @Nullable ReadableMap source) { - if (source != null) { - if (source.hasKey("html")) { - String html = source.getString("html"); - if (source.hasKey("baseUrl")) { - view.loadDataWithBaseURL( - source.getString("baseUrl"), html, HTML_MIME_TYPE, HTML_ENCODING, null); - } else { - view.loadData(html, HTML_MIME_TYPE, HTML_ENCODING); - } - return; - } - if (source.hasKey("uri")) { - String url = source.getString("uri"); - String previousUrl = view.getUrl(); - //if (previousUrl != null && previousUrl.equals(url)) { - // return; - //} - if (source.hasKey("method")) { - String method = source.getString("method"); - if (method.equals(HTTP_METHOD_POST)) { - byte[] postData = null; - if (source.hasKey("body")) { - String body = source.getString("body"); - try { - postData = body.getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - postData = body.getBytes(); - } - } - if (postData == null) { - postData = new byte[0]; - } - view.postUrl(url, postData); - return; - } - } - HashMap headerMap = new HashMap<>(); - if (source.hasKey("headers")) { - ReadableMap headers = source.getMap("headers"); - ReadableMapKeySetIterator iter = headers.keySetIterator(); - while (iter.hasNextKey()) { - String key = iter.nextKey(); - if ("user-agent".equals(key.toLowerCase(Locale.ENGLISH))) { - if (view.getSettings() != null) { - view.getSettings().setUserAgentString(headers.getString(key)); - } - } else { - headerMap.put(key, headers.getString(key)); - } - } - } - view.loadUrl(url, headerMap); - Log.d("CustomWebviewLoadUrl", "loading url: "+url); - return; - } - } - view.loadUrl(BLANK_URL); - } - - @ReactProp(name = "onContentSizeChange") - public void setOnContentSizeChange(WebView view, boolean sendContentSizeChangeEvents) { - if (sendContentSizeChangeEvents) { - view.setPictureListener(getPictureListener()); - } else { - view.setPictureListener(null); - } - } - - @ReactProp(name = "mixedContentMode") - public void setMixedContentMode(WebView view, @Nullable String mixedContentMode) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - if (mixedContentMode == null || "never".equals(mixedContentMode)) { - view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW); - } else if ("always".equals(mixedContentMode)) { - view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); - } else if ("compatibility".equals(mixedContentMode)) { - view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE); - } - } - } - - @ReactProp(name = "urlPrefixesForDefaultIntent") - public void setUrlPrefixesForDefaultIntent( - WebView view, - @Nullable ReadableArray urlPrefixesForDefaultIntent) { - CustomWebviewClient client = ((CustomWebview) view).getCustomWebviewClient(); - if (client != null && urlPrefixesForDefaultIntent != null) { - client.setUrlPrefixesForDefaultIntent(urlPrefixesForDefaultIntent); - } - } - - @ReactProp(name = "geolocationEnabled") - public void setGeolocationEnabled( - WebView view, - @Nullable Boolean isGeolocationEnabled) { - view.getSettings().setGeolocationEnabled(isGeolocationEnabled != null && isGeolocationEnabled); - } - - @ReactProp(name = "originWhitelist") - public void setOriginWhitelist( - WebView view, - @Nullable ReadableArray originWhitelist) { - CustomWebviewClient client = ((CustomWebview) view).getCustomWebviewClient(); - if (client != null && originWhitelist != null) { - List whiteList = new LinkedList<>(); - for (int i = 0 ; i < originWhitelist.size() ; i++) { - whiteList.add(Pattern.compile(originWhitelist.getString(i))); - } - client.setOriginWhitelist(whiteList); - } - } - - @Override - protected void addEventEmitters(ThemedReactContext reactContext, WebView view) { - // Do not register default touch emitter and let WebView implementation handle touches - view.setWebViewClient(new CustomWebviewClient()); - } - - @Override - public @Nullable Map getCommandsMap() { - return MapBuilder.of( - "goBack", COMMAND_GO_BACK, - "goForward", COMMAND_GO_FORWARD, - "reload", COMMAND_RELOAD, - "stopLoading", COMMAND_STOP_LOADING, - "postMessage", COMMAND_POST_MESSAGE, - "injectJavaScript", COMMAND_INJECT_JAVASCRIPT - ); - } - - @Override - public void receiveCommand(WebView root, int commandId, @Nullable ReadableArray args) { - switch (commandId) { - case COMMAND_GO_BACK: - root.goBack(); - break; - case COMMAND_GO_FORWARD: - root.goForward(); - break; - case COMMAND_RELOAD: - root.reload(); - break; - case COMMAND_STOP_LOADING: - root.stopLoading(); - break; - case COMMAND_POST_MESSAGE: - try { - JSONObject eventInitDict = new JSONObject(); - eventInitDict.put("data", args.getString(0)); - root.loadUrl("javascript:(function () {" + - "var event;" + - "var data = " + eventInitDict.toString() + ";" + - "try {" + - "event = new MessageEvent('message', data);" + - "} catch (e) {" + - "event = document.createEvent('MessageEvent');" + - "event.initMessageEvent('message', true, true, data.data, data.origin, data.lastEventId, data.source);" + - "}" + - "document.dispatchEvent(event);" + - "})();"); - } catch (JSONException e) { - throw new RuntimeException(e); - } - break; - case COMMAND_INJECT_JAVASCRIPT: - root.loadUrl("javascript:" + args.getString(0)); - break; - } - } - - @Override - public void onDropViewInstance(WebView webView) { - super.onDropViewInstance(webView); - ((ThemedReactContext) webView.getContext()).removeLifecycleEventListener((CustomWebview) webView); - ((CustomWebview) webView).cleanupCallbacksAndDestroy(); - } - - protected WebView.PictureListener getPictureListener() { - if (mPictureListener == null) { - mPictureListener = new WebView.PictureListener() { - @Override - public void onNewPicture(WebView webView, Picture picture) { - dispatchEvent( - webView, - new ContentSizeChangeEvent( - webView.getId(), - webView.getWidth(), - webView.getContentHeight())); - } - }; - } - return mPictureListener; - } - - protected static void dispatchEvent(WebView webView, Event event) { - ReactContext reactContext = (ReactContext) webView.getContext(); - EventDispatcher eventDispatcher = - reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher(); - eventDispatcher.dispatchEvent(event); - } - - @Override - public @Nullable Map getExportedCustomBubblingEventTypeConstants() { - return MapBuilder.builder() - .put("progress", - MapBuilder.of( - "phasedRegistrationNames", - MapBuilder.of("bubbled", "onProgress"))) - .build(); - } -} diff --git a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewPackage.java b/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewPackage.java deleted file mode 100644 index b752d1ac750..00000000000 --- a/android/app/src/main/java/com/metamask/CustomWebview/CustomWebviewPackage.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.metamask.CustomWebview; - -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; - -import java.util.Collections; -import java.util.List; - -public class CustomWebviewPackage implements ReactPackage { - - @Override - public List createViewManagers( - ReactApplicationContext reactContext) { - return Collections.singletonList( - new CustomWebviewManager(reactContext,this) - ); - } - - @Override - public List createNativeModules( - ReactApplicationContext reactContext) { - return Collections.emptyList(); - } - -} diff --git a/android/app/src/main/java/com/metamask/CustomWebview/InputStreamWithInjectedJS.java b/android/app/src/main/java/com/metamask/CustomWebview/InputStreamWithInjectedJS.java deleted file mode 100644 index c3e27ce3bce..00000000000 --- a/android/app/src/main/java/com/metamask/CustomWebview/InputStreamWithInjectedJS.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.metamask.CustomWebview; - -import android.content.Context; -import android.content.res.Resources; -import android.os.Build; -import android.support.annotation.RequiresApi; -import android.util.Log; - -import com.metamask.R; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.nio.charset.UnsupportedCharsetException; -import java.util.HashMap; -import java.util.Map; - -import io.fabric.sdk.android.services.common.CommonUtils; - -import static java.nio.charset.StandardCharsets.*; -@RequiresApi(api = Build.VERSION_CODES.KITKAT) -public class InputStreamWithInjectedJS extends InputStream { - private InputStream pageIS; - private InputStream scriptIS; - private Charset charset; - private static final String TAG = "InputStreamWithInjectedJS"; - private static Map script = new HashMap<>(); - private boolean hasJS = false; - private boolean headWasFound = false; - private boolean scriptWasInjected = false; - private StringBuffer contentBuffer = new StringBuffer(); - private static Charset getCharset(String charsetName) { - Charset cs = UTF_8; - try { - if (charsetName != null) { - cs = Charset.forName(charsetName); - } - } catch (UnsupportedCharsetException e) { - Log.d("CustomWebview", "wrong charset: " + charsetName); - } - return cs; - } - private static InputStream getScript(Charset charset) { - String js = script.get(charset); - if (js == null) { - String defaultJs = script.get(UTF_8); - js = new String(defaultJs.getBytes(UTF_8), charset); - script.put(charset, js); - } - return new ByteArrayInputStream(js.getBytes(charset)); - } - InputStreamWithInjectedJS(InputStream is, String js, Charset charset, Context c) { - if (js == null) { - this.pageIS = is; - } else { - this.hasJS = true; - this.charset = charset; - Charset cs = UTF_8; - String jsScript = ""; - script.put(cs, jsScript); - this.pageIS = is; - } - } - @Override - public int read() throws IOException { - if (scriptWasInjected || !hasJS) { - return pageIS.read(); - } - if (!scriptWasInjected && headWasFound) { - int nextByte = scriptIS.read(); - if (nextByte == -1) { - scriptIS.close(); - scriptWasInjected = true; - return pageIS.read(); - } else { - return nextByte; - } - } - if (!headWasFound) { - int nextByte = pageIS.read(); - contentBuffer.append((char) nextByte); - int bufferLength = contentBuffer.length(); - if (nextByte == 62 && bufferLength >= 6) { - if (contentBuffer.substring(bufferLength - 6).equals("")) { - this.scriptIS = getScript(this.charset); - headWasFound = true; - } - } - return nextByte; - } - return pageIS.read(); - } -} diff --git a/android/app/src/main/java/com/metamask/CustomWebview/ProgressEvent.java b/android/app/src/main/java/com/metamask/CustomWebview/ProgressEvent.java deleted file mode 100644 index bc35742f44a..00000000000 --- a/android/app/src/main/java/com/metamask/CustomWebview/ProgressEvent.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.metamask.CustomWebview; - -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; - -public class ProgressEvent extends Event { - - public static final String EVENT_NAME = "progress"; - - private final int mProgress; - - public ProgressEvent(int viewId, int progress) { - super(viewId); - mProgress = progress; - } - - @Override - public String getEventName() { - return EVENT_NAME; - } - - @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - WritableMap data = Arguments.createMap(); - data.putInt("progress", mProgress); - rctEventEmitter.receiveEvent(getViewTag(), EVENT_NAME, data); - } -} diff --git a/android/app/src/main/java/com/metamask/MainApplication.java b/android/app/src/main/java/com/metamask/MainApplication.java index 9af21aef6d3..3dd8bfe575c 100644 --- a/android/app/src/main/java/com/metamask/MainApplication.java +++ b/android/app/src/main/java/com/metamask/MainApplication.java @@ -4,6 +4,7 @@ import com.crashlytics.android.Crashlytics; import com.facebook.react.ReactApplication; +import com.metamask.Web3Webview.Web3WebviewPackage; import org.reactnative.camera.RNCameraPackage; import cl.json.RNSharePackage; import com.AlexanderZaytsev.RNI18n.RNI18nPackage; @@ -13,7 +14,6 @@ import com.peel.react.rnos.RNOSModule; import com.BV.LinearGradient.LinearGradientPackage; import com.bitgo.randombytes.RandomBytesPackage; -import com.metamask.CustomWebview.CustomWebviewPackage; import com.rnfs.RNFSPackage; import com.oblador.vectoricons.VectorIconsPackage; import com.facebook.react.ReactNativeHost; @@ -40,6 +40,7 @@ public boolean getUseDeveloperSupport() { protected List getPackages() { return Arrays.asList( new MainReactPackage(), + new Web3WebviewPackage(), new RNCameraPackage(), new RNSharePackage(), new RNI18nPackage(), @@ -50,8 +51,7 @@ protected List getPackages() { new LinearGradientPackage(), new RandomBytesPackage(), new RNFSPackage(), - new VectorIconsPackage(), - new CustomWebviewPackage() + new VectorIconsPackage() ); } diff --git a/android/settings.gradle b/android/settings.gradle index 03d1bdea6b5..d79ada04cd0 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,4 +1,6 @@ rootProject.name = 'MetaMask' +include ':react-native-web3-webview' +project(':react-native-web3-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-web3-webview/android') include ':react-native-camera' project(':react-native-camera').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-camera/android') include ':react-native-share' diff --git a/app/components/Browser/index.js b/app/components/Browser/index.js index 73535e13031..a174fe2a2c4 100644 --- a/app/components/Browser/index.js +++ b/app/components/Browser/index.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import BackgroundBridge from '../../core/BackgroundBridge'; -import CustomWebview from '../CustomWebview'; // eslint-disable-line import/no-unresolved +import Web3Webview from 'react-native-web3-webview'; import Engine from '../../core/Engine'; import Icon from 'react-native-vector-icons/FontAwesome'; import PropTypes from 'prop-types'; @@ -24,9 +24,9 @@ const styles = StyleSheet.create({ flex: 0, height: 28, lineHeight: 28, - paddingTop: 2, textAlign: 'center', - width: 36 + width: 36, + alignSelf: 'center' }, disabledIcon: { color: colors.ash @@ -214,7 +214,7 @@ export class Browser extends Component { {entryScriptWeb3 ? ( - - <_class - javaScriptEnabled={true} - key="webViewKey" - messagingEnabled={false} - onLoadingError={[Function]} - onLoadingFinish={[Function]} - onLoadingStart={[Function]} - onMessage={[Function]} - originWhitelist={ - Array [ - "http://.*", - "https://.*", - ] - } - saveFormDataDisabled={false} - scalesPageToFit={true} - source={Object {}} - style={ - Array [ - Object { - "flex": 1, - }, - undefined, - ] - } - thirdPartyCookiesEnabled={true} - /> - -`; - -exports[`CustomWebview should render correctly on iOS 1`] = ` - - <_class - key="webViewKey" - messagingEnabled={false} - onLoadingError={[Function]} - onLoadingFinish={[Function]} - onLoadingStart={[Function]} - onMessage={[Function]} - onProgress={[Function]} - onScroll={[Function]} - source={Object {}} - style={ - Array [ - Object { - "flex": 1, - }, - Object { - "backgroundColor": "#ffffff", - }, - undefined, - ] - } - /> - -`; diff --git a/app/components/CustomWebview/index.android.js b/app/components/CustomWebview/index.android.js deleted file mode 100644 index 77e640a5eff..00000000000 --- a/app/components/CustomWebview/index.android.js +++ /dev/null @@ -1,433 +0,0 @@ -'use strict'; - -import React from 'react'; -import PropTypes from 'prop-types'; -import deprecatedPropType from 'deprecatedPropType'; // eslint-disable-line import/no-unresolved -import keyMirror from 'fbjs/lib/keyMirror'; // eslint-disable-line import/no-extraneous-dependencies -import resolveAssetSource from 'resolveAssetSource'; // eslint-disable-line import/no-unresolved -import WebViewShared from 'WebViewShared'; // eslint-disable-line import/no-unresolved - -import { - requireNativeComponent, - ViewPropTypes, - EdgeInsetsPropType, - ActivityIndicator, - StyleSheet, - UIManager, - View, - findNodeHandle -} from 'react-native'; - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: 'white' // eslint-disable-line - }, - hidden: { - height: 0, - flex: 0 // disable 'flex:1' when hiding a View - }, - loadingView: { - flex: 1, - justifyContent: 'center', - alignItems: 'center' - }, - loadingProgressBar: { - height: 20 - } -}); - -const WebViewState = keyMirror({ - IDLE: null, - LOADING: null, - ERROR: null -}); - -const defaultRenderLoading = () => ( - - - -); - -/** - * Renders a native WebView. - */ -const CustomWebview = requireNativeComponent('CustomWebview'); - -export default class WebView extends React.Component { - static propTypes = { - ...ViewPropTypes, - renderError: PropTypes.func, - renderLoading: PropTypes.func, - onLoad: PropTypes.func, - onLoadEnd: PropTypes.func, - onLoadStart: PropTypes.func, - onError: PropTypes.func, - onProgress: PropTypes.func, - automaticallyAdjustContentInsets: PropTypes.bool, - contentInset: EdgeInsetsPropType, - onNavigationStateChange: PropTypes.func, - onMessage: PropTypes.func, - onContentSizeChange: PropTypes.func, - startInLoadingState: PropTypes.bool, // force WebView to show loadingView on first load - style: ViewPropTypes.style, - - html: deprecatedPropType(PropTypes.string, 'Use the `source` prop instead.'), - - url: deprecatedPropType(PropTypes.string, 'Use the `source` prop instead.'), - - /** - * Loads static html or a uri (with optional headers) in the WebView. - */ - source: PropTypes.oneOfType([ - PropTypes.shape({ - /* - * The URI to load in the WebView. Can be a local or remote file. - */ - uri: PropTypes.string, - /* - * The HTTP Method to use. Defaults to GET if not specified. - * NOTE: On Android, only GET and POST are supported. - */ - method: PropTypes.oneOf(['GET', 'POST']), - /* - * Additional HTTP headers to send with the request. - * NOTE: On Android, this can only be used with GET requests. - */ - headers: PropTypes.object, - /* - * The HTTP body to send with the request. This must be a valid - * UTF-8 string, and will be sent exactly as specified, with no - * additional encoding (e.g. URL-escaping or base64) applied. - * NOTE: On Android, this can only be used with POST requests. - */ - body: PropTypes.string - }), - PropTypes.shape({ - /* - * A static HTML page to display in the WebView. - */ - html: PropTypes.string, - /* - * The base URL to be used for any relative links in the HTML. - */ - baseUrl: PropTypes.string - }), - /* - * Used internally by packager. - */ - PropTypes.number - ]), - - /** - * Used on Android only, JS is enabled by default for WebView on iOS - * @platform android - */ - javaScriptEnabled: PropTypes.bool, - - /** - * Used on Android Lollipop and above only, third party cookies are enabled - * by default for WebView on Android Kitkat and below and on iOS - * @platform android - */ - thirdPartyCookiesEnabled: PropTypes.bool, - - /** - * Used on Android only, controls whether DOM Storage is enabled or not - * @platform android - */ - domStorageEnabled: PropTypes.bool, - - /** - * Sets whether Geolocation is enabled. The default is false. - * @platform android - */ - geolocationEnabled: PropTypes.bool, - - /** - * Sets the JS to be injected when the webpage loads. - */ - injectedJavaScript: PropTypes.string, - - /** - * Sets the JS to be injected when the webpage starts loading. - */ - injectedOnStartLoadingJavaScript: PropTypes.string, - /** - * Sets whether the webpage scales to fit the view and the user can change the scale. - */ - scalesPageToFit: PropTypes.bool, - - /** - * Sets the user-agent for this WebView. The user-agent can also be set in native using - * WebViewConfig. This prop will overwrite that config. - */ - userAgent: PropTypes.string, - - /** - * Used to locate this view in end-to-end tests. - */ - testID: PropTypes.string, - - /** - * Determines whether HTML5 audio & videos require the user to tap before they can - * start playing. The default value is `false`. - */ - mediaPlaybackRequiresUserAction: PropTypes.bool, - - /** - * Boolean that sets whether JavaScript running in the context of a file - * scheme URL should be allowed to access content from any origin. - * Including accessing content from other file scheme URLs - * @platform android - */ - allowUniversalAccessFromFileURLs: PropTypes.bool, - - /** - * List of origin strings to allow being navigated to. The strings allow - * wildcards and get matched against *just* the origin (not the full URL). - * If the user taps to navigate to a new page but the new page is not in - * this whitelist, the URL will be opened by the Android OS. - * The default whitelisted origins are "http://*" and "https://*". - */ - originWhitelist: PropTypes.arrayOf(PropTypes.string), - - /** - * Function that accepts a string that will be passed to the WebView and - * executed immediately as JavaScript. - */ - injectJavaScript: PropTypes.func, - - /** - * Specifies the mixed content mode. i.e WebView will allow a secure origin to load content from any other origin. - * - * Possible values for `mixedContentMode` are: - * - * - `'never'` (default) - WebView will not allow a secure origin to load content from an insecure origin. - * - `'always'` - WebView will allow a secure origin to load content from any other origin, even if that origin is insecure. - * - `'compatibility'` - WebView will attempt to be compatible with the approach of a modern web browser with regard to mixed content. - * @platform android - */ - mixedContentMode: PropTypes.oneOf(['never', 'always', 'compatibility']), - - /** - * Used on Android only, controls whether form autocomplete data should be saved - * @platform android - */ - saveFormDataDisabled: PropTypes.bool, - - /** - * Override the native component used to render the WebView. Enables a custom native - * WebView which uses the same JavaScript as the original WebView. - */ - nativeConfig: PropTypes.shape({ - /* - * The native component used to render the WebView. - */ - component: PropTypes.any, - /* - * Set props directly on the native component WebView. Enables custom props which the - * original WebView doesn't pass through. - */ - props: PropTypes.object, - /* - * Set the ViewManager to use for communication with the native side. - * @platform ios - */ - viewManager: PropTypes.object - }), - /* - * Used on Android only, controls whether the given list of URL prefixes should - * make {@link com.facebook.react.views.webview.ReactWebViewClient} to launch a - * default activity intent for those URL instead of loading it within the webview. - * Use this to list URLs that WebView cannot handle, e.g. a PDF url. - * @platform android - */ - urlPrefixesForDefaultIntent: PropTypes.arrayOf(PropTypes.string) - }; - - static defaultProps = { - javaScriptEnabled: true, - thirdPartyCookiesEnabled: true, - scalesPageToFit: true, - saveFormDataDisabled: false, - originWhitelist: WebViewShared.defaultOriginWhitelist - }; - - state = { - viewState: WebViewState.IDLE, - lastErrorEvent: null, - startInLoadingState: true - }; - - UNSAFE_componentWillMount() { - if (this.props.startInLoadingState) { - this.setState({ viewState: WebViewState.LOADING }); - } - } - - setWebviewRef = ref => { - this.webview = ref; - }; - - render() { - let otherView = null; // eslint-disable-line no-unused-vars - - if (this.state.viewState === WebViewState.LOADING) { - otherView = (this.props.renderLoading || defaultRenderLoading)(); - } else if (this.state.viewState === WebViewState.ERROR) { - const errorEvent = this.state.lastErrorEvent; - otherView = - this.props.renderError && - this.props.renderError(errorEvent.domain, errorEvent.code, errorEvent.description); - } - - const webViewStyles = [styles.container, this.props.style]; - if (this.state.viewState === WebViewState.LOADING || this.state.viewState === WebViewState.ERROR) { - // if we're in either LOADING or ERROR states, don't show the webView - webViewStyles.push(styles.hidden); - } - - const source = this.props.source || {}; - if (this.props.html) { - source.html = this.props.html; - } else if (this.props.url) { - source.uri = this.props.url; - } - - const nativeConfig = this.props.nativeConfig || {}; - - const originWhitelist = (this.props.originWhitelist || []).map(WebViewShared.originWhitelistToRegex); - - const NativeWebView = nativeConfig.component || CustomWebview; - - const webView = ( - - ); - - return {webView}; - } - - goForward = () => { - UIManager.dispatchViewManagerCommand(this.getWebViewHandle(), UIManager.CustomWebview.Commands.goForward, null); - }; - - goBack = () => { - UIManager.dispatchViewManagerCommand(this.getWebViewHandle(), UIManager.CustomWebview.Commands.goBack, null); - }; - - reload = () => { - this.setState({ - viewState: WebViewState.LOADING - }); - UIManager.dispatchViewManagerCommand(this.getWebViewHandle(), UIManager.CustomWebview.Commands.reload, null); - }; - - stopLoading = () => { - UIManager.dispatchViewManagerCommand( - this.getWebViewHandle(), - UIManager.CustomWebview.Commands.stopLoading, - null - ); - }; - - postMessage = data => { - UIManager.dispatchViewManagerCommand(this.getWebViewHandle(), UIManager.CustomWebview.Commands.postMessage, [ - String(data) - ]); - }; - - /** - * Injects a javascript string into the referenced WebView. Deliberately does not - * return a response because using eval() to return a response breaks this method - * on pages with a Content Security Policy that disallows eval(). If you need that - * functionality, look into postMessage/onMessage. - */ - injectJavaScript = data => { - UIManager.dispatchViewManagerCommand( - this.getWebViewHandle(), - UIManager.CustomWebview.Commands.injectJavaScript, - [data] - ); - }; - - /** - * We return an event with a bunch of fields including: - * url, title, loading, canGoBack, canGoForward - */ - updateNavigationState = event => { - if (this.props.onNavigationStateChange) { - this.props.onNavigationStateChange(event.nativeEvent); - } - }; - - getWebViewHandle = () => findNodeHandle(this.webview); - - onLoadingStart = event => { - const onLoadStart = this.props.onLoadStart; - onLoadStart && onLoadStart(event); - this.updateNavigationState(event); - }; - - onLoadingError = event => { - event.persist(); // persist this event because we need to store it - const { onError, onLoadEnd } = this.props; - onError && onError(event); - onLoadEnd && onLoadEnd(event); - - this.setState({ - lastErrorEvent: event.nativeEvent, - viewState: WebViewState.ERROR - }); - }; - - onLoadingFinish = event => { - const { onLoad, onLoadEnd } = this.props; - onLoad && onLoad(event); - onLoadEnd && onLoadEnd(event); - this.setState({ - viewState: WebViewState.IDLE - }); - this.updateNavigationState(event); - }; - - onProgress = event => { - const { onProgress } = this.props; - onProgress && onProgress(parseFloat(event.nativeEvent.progress / 100)); - }; - - onMessage = event => { - const { onMessage } = this.props; - onMessage && onMessage(event); - }; -} diff --git a/app/components/CustomWebview/index.ios.js b/app/components/CustomWebview/index.ios.js deleted file mode 100644 index 39c9ad55ab5..00000000000 --- a/app/components/CustomWebview/index.ios.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -import WKWebView from 'react-native-wkwebview-reborn'; - -export default WKWebView; diff --git a/app/components/CustomWebview/index.test.js b/app/components/CustomWebview/index.test.js deleted file mode 100644 index 65fd74648a7..00000000000 --- a/app/components/CustomWebview/index.test.js +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; -import { shallow } from 'enzyme'; -import CustomWebviewAndroid from './index.android'; -import CustomWebviewIos from './index.ios'; - -describe('CustomWebview', () => { - it('should render correctly on iOS', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); - - it('should render correctly on Android', () => { - jest.mock('Platform', () => { - const Platform = require.requireActual('Platform'); - Platform.OS = 'android'; - return Platform; - }); - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index 6f3990b690f..8ecc58758cb 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -14,7 +14,6 @@ 00E356F31AD99517003FC87E /* MetaMaskTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* MetaMaskTests.m */; }; 0A2ECB748D5D4A1696858CA2 /* libRNOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 417D7C2840F148F591AB0261 /* libRNOS.a */; }; 123752B9768C469A85058888 /* Feather.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E9629905BA1940ADA4189921 /* Feather.ttf */; }; - 131AA188550F45659821D213 /* (null) in Frameworks */ = {isa = PBXBuildFile; }; 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; }; @@ -64,10 +63,10 @@ 887E75FB64A54509A08D6C50 /* Roboto-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E020F42F788744B3BCE17F05 /* Roboto-LightItalic.ttf */; }; 900DAC87A8AB4C8092EA3682 /* libRNRandomBytes.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8ABF9E3C7C334558A19A8C88 /* libRNRandomBytes.a */; }; 9916CE03947044A781F61544 /* libRNI18n.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 138ABBB9E0B74423B1FEB949 /* libRNI18n.a */; }; - AAACFD03192C40F8A1B38A8A /* libRCTWKWebView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 893E46C6BCE84DC19E928BBD /* libRCTWKWebView.a */; }; AB0011D0A1224FD09AB255D3 /* libRCTAes.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BCC003A069E4228AE707B9A /* libRCTAes.a */; }; AD5E20E743784F76B8244798 /* libRNI18n-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 52F790B15AC44E6189F7E6D2 /* libRNI18n-tvOS.a */; }; ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */; }; + B9FD0E084B9642E68F7D3E46 /* libRNWeb3Webview.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E1CC67DB29F47E584AA47D1 /* libRNWeb3Webview.a */; }; C21D2E236D734B7CB2DFFC6E /* libSMXCrashlytics.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 84EF90ACE1B444F29DC69FF4 /* libSMXCrashlytics.a */; }; C5AD5D88262D40E8AD14096C /* FontAwesome.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5E32A09A7BDC431FA403BA73 /* FontAwesome.ttf */; }; CD13D926E1E84D9ABFE672C0 /* Roboto-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 3E2492C67CF345CABD7B8601 /* Roboto-BlackItalic.ttf */; }; @@ -146,6 +145,13 @@ remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; remoteInfo = React; }; + 151AF16A213A737900CBCC36 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F42ED3125EBF460CA78D606A /* RNWeb3Webview.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RNWeb3Webview; + }; 151FBD51212F822000AE84BB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 9A76C2FA10F2464D9211E0C0 /* SMXCrashlytics.xcodeproj */; @@ -237,13 +243,6 @@ remoteGlobalIDString = 5DBEB1501B18CEA900B34395; remoteInfo = RNVectorIcons; }; - 15C1F6A12100D07200DEA29E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 32DB6F5C92BA4F85979EF659 /* RCTWKWebView.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 0974579A1D2A440A000D9368; - remoteInfo = RCTWKWebView; - }; 15D70BF621376C7C00DC793B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A0BF502ED6414A349ED12B36 /* RNCamera.xcodeproj */; @@ -518,7 +517,6 @@ 2D02E47B1E0B4A5D006451C7 /* MetaMask-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "MetaMask-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 2D02E4901E0B4A5D006451C7 /* MetaMask-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "MetaMask-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 2D16E6891FA4F8E400B85C8A /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 32DB6F5C92BA4F85979EF659 /* RCTWKWebView.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTWKWebView.xcodeproj; path = "../node_modules/react-native-wkwebview-reborn/ios/RCTWKWebView.xcodeproj"; sourceTree = ""; }; 3BCC003A069E4228AE707B9A /* libRCTAes.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRCTAes.a; sourceTree = ""; }; 3E2492C67CF345CABD7B8601 /* Roboto-BlackItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-BlackItalic.ttf"; path = "../app/fonts/Roboto-BlackItalic.ttf"; sourceTree = ""; }; 417D7C2840F148F591AB0261 /* libRNOS.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNOS.a; sourceTree = ""; }; @@ -542,8 +540,8 @@ 7FF1597C0ACA4902B86140B2 /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = ""; }; 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; 84EF90ACE1B444F29DC69FF4 /* libSMXCrashlytics.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libSMXCrashlytics.a; sourceTree = ""; }; - 893E46C6BCE84DC19E928BBD /* libRCTWKWebView.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRCTWKWebView.a; sourceTree = ""; }; 8ABF9E3C7C334558A19A8C88 /* libRNRandomBytes.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNRandomBytes.a; sourceTree = ""; }; + 8E1CC67DB29F47E584AA47D1 /* libRNWeb3Webview.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNWeb3Webview.a; sourceTree = ""; }; 9A76C2FA10F2464D9211E0C0 /* SMXCrashlytics.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = SMXCrashlytics.xcodeproj; path = "../node_modules/react-native-fabric/ios/SMXCrashlytics.xcodeproj"; sourceTree = ""; }; 9AB328AA05904D6AA5C6A622 /* RNShare.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNShare.xcodeproj; path = "../node_modules/react-native-share/ios/RNShare.xcodeproj"; sourceTree = ""; }; A0BF502ED6414A349ED12B36 /* RNCamera.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNCamera.xcodeproj; path = "../node_modules/react-native-camera/ios/RNCamera.xcodeproj"; sourceTree = ""; }; @@ -564,6 +562,7 @@ E020F42F788744B3BCE17F05 /* Roboto-LightItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-LightItalic.ttf"; path = "../app/fonts/Roboto-LightItalic.ttf"; sourceTree = ""; }; E34F71B40BF74968A8800F3A /* RNVectorIcons.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNVectorIcons.xcodeproj; path = "../node_modules/react-native-vector-icons/RNVectorIcons.xcodeproj"; sourceTree = ""; }; E9629905BA1940ADA4189921 /* Feather.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Feather.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = ""; }; + F42ED3125EBF460CA78D606A /* RNWeb3Webview.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNWeb3Webview.xcodeproj; path = "../node_modules/react-native-web3-webview/ios/RNWeb3Webview.xcodeproj"; sourceTree = ""; }; F562CA6B28AA4A67AA29B61C /* MaterialIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -595,9 +594,7 @@ 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, FD9BDCD5059C483EAE9C0160 /* libRNVectorIcons.a in Frameworks */, 2EE92764CB2942ACBE6EABC8 /* libRNFS.a in Frameworks */, - AAACFD03192C40F8A1B38A8A /* libRCTWKWebView.a in Frameworks */, 900DAC87A8AB4C8092EA3682 /* libRNRandomBytes.a in Frameworks */, - 131AA188550F45659821D213 /* (null) in Frameworks */, 76AB602000D14AA58533641D /* libBVLinearGradient.a in Frameworks */, 0A2ECB748D5D4A1696858CA2 /* libRNOS.a in Frameworks */, AB0011D0A1224FD09AB255D3 /* libRCTAes.a in Frameworks */, @@ -607,6 +604,7 @@ 7E3066CD5F8E4BC1B3A5808D /* libRNCamera.a in Frameworks */, 9916CE03947044A781F61544 /* libRNI18n.a in Frameworks */, CFF4EF3E169746F79CF0D9EE /* libRNShare.a in Frameworks */, + B9FD0E084B9642E68F7D3E46 /* libRNWeb3Webview.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -756,6 +754,14 @@ name = Products; sourceTree = ""; }; + 151AF167213A737900CBCC36 /* Products */ = { + isa = PBXGroup; + children = ( + 151AF16B213A737900CBCC36 /* libRNWeb3Webview.a */, + ); + name = Products; + sourceTree = ""; + }; 151FBD4D212F822000AE84BB /* Products */ = { isa = PBXGroup; children = ( @@ -813,7 +819,6 @@ children = ( 70BCC86172F14AB2BF4DDA97 /* libRNVectorIcons.a */, CF0899B651A847EDB227BE12 /* libRNFS.a */, - 893E46C6BCE84DC19E928BBD /* libRCTWKWebView.a */, 8ABF9E3C7C334558A19A8C88 /* libRNRandomBytes.a */, 14E7DBD0B81B4F6087628BA0 /* libRNRandomBytes-tvOS.a */, 278065D027394AD9B2906E38 /* libBVLinearGradient.a */, @@ -825,6 +830,7 @@ 138ABBB9E0B74423B1FEB949 /* libRNI18n.a */, 204D40F66C724C47BF4D4911 /* libRNShare.a */, 52F790B15AC44E6189F7E6D2 /* libRNI18n-tvOS.a */, + 8E1CC67DB29F47E584AA47D1 /* libRNWeb3Webview.a */, ); name = "Recovered References"; sourceTree = ""; @@ -846,14 +852,6 @@ name = Products; sourceTree = ""; }; - 15C1F69E2100D06E00DEA29E /* Products */ = { - isa = PBXGroup; - children = ( - 15C1F6A22100D07200DEA29E /* libRCTWKWebView.a */, - ); - name = Products; - sourceTree = ""; - }; 15D70BF321376C7C00DC793B /* Products */ = { isa = PBXGroup; children = ( @@ -955,7 +953,6 @@ 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, E34F71B40BF74968A8800F3A /* RNVectorIcons.xcodeproj */, 6EFAC8C8B451455A999A0F09 /* RNFS.xcodeproj */, - 32DB6F5C92BA4F85979EF659 /* RCTWKWebView.xcodeproj */, 500343D7D81046209C481A89 /* RNRandomBytes.xcodeproj */, 41E97E0BCBAB4073990BFBFF /* BVLinearGradient.xcodeproj */, 1DF030904DE24B189311952F /* RNOS.xcodeproj */, @@ -965,6 +962,7 @@ A0BF502ED6414A349ED12B36 /* RNCamera.xcodeproj */, C64043A9D79F4CDBAAAB035B /* RNI18n.xcodeproj */, 9AB328AA05904D6AA5C6A622 /* RNShare.xcodeproj */, + F42ED3125EBF460CA78D606A /* RNWeb3Webview.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -981,7 +979,6 @@ 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( - A08F7F38212F69A30033B0A2 /* InputMask.framework */, 13B07FAE1A68108700A75B9A /* MetaMask */, 832341AE1AAA6A7D00B99B32 /* Libraries */, 00E356EF1AD99517003FC87E /* MetaMaskTests */, @@ -1102,14 +1099,20 @@ TargetAttributes = { 00E356ED1AD99517003FC87E = { CreatedOnToolsVersion = 6.2; + DevelopmentTeam = L8GS6GD649; TestTargetID = 13B07F861A680F5B00A75B9A; }; + 13B07F861A680F5B00A75B9A = { + DevelopmentTeam = L8GS6GD649; + }; 2D02E47A1E0B4A5D006451C7 = { CreatedOnToolsVersion = 8.2.1; + DevelopmentTeam = L8GS6GD649; ProvisioningStyle = Automatic; }; 2D02E48F1E0B4A5D006451C7 = { CreatedOnToolsVersion = 8.2.1; + DevelopmentTeam = L8GS6GD649; ProvisioningStyle = Automatic; TestTargetID = 2D02E47A1E0B4A5D006451C7; }; @@ -1179,10 +1182,6 @@ ProductGroup = 139FDEE71B06529A00C62182 /* Products */; ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; }, - { - ProductGroup = 15C1F69E2100D06E00DEA29E /* Products */; - ProjectRef = 32DB6F5C92BA4F85979EF659 /* RCTWKWebView.xcodeproj */; - }, { ProductGroup = 146834001AC3E56700842450 /* Products */; ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; @@ -1219,6 +1218,10 @@ ProductGroup = 15A2E6152100077700A1F331 /* Products */; ProjectRef = E34F71B40BF74968A8800F3A /* RNVectorIcons.xcodeproj */; }, + { + ProductGroup = 151AF167213A737900CBCC36 /* Products */; + ProjectRef = F42ED3125EBF460CA78D606A /* RNWeb3Webview.xcodeproj */; + }, { ProductGroup = 151FBD4D212F822000AE84BB /* Products */; ProjectRef = 9A76C2FA10F2464D9211E0C0 /* SMXCrashlytics.xcodeproj */; @@ -1291,6 +1294,13 @@ remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 151AF16B213A737900CBCC36 /* libRNWeb3Webview.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNWeb3Webview.a; + remoteRef = 151AF16A213A737900CBCC36 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 151FBD52212F822000AE84BB /* libSMXCrashlytics.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1382,13 +1392,6 @@ remoteRef = 15A2E6202100077800A1F331 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 15C1F6A22100D07200DEA29E /* libRCTWKWebView.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libRCTWKWebView.a; - remoteRef = 15C1F6A12100D07200DEA29E /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 15D70BF721376C7C00DC793B /* libRNCamera.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1793,6 +1796,7 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; + DEVELOPMENT_TEAM = L8GS6GD649; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -1812,6 +1816,7 @@ "$(SRCROOT)/../node_modules/react-native-camera/ios/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-web3-webview/ios", ); INFOPLIST_FILE = MetaMaskTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -1835,6 +1840,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1851,6 +1857,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = L8GS6GD649; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", @@ -1866,6 +1873,7 @@ "$(SRCROOT)/../node_modules/react-native-camera/ios/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-web3-webview/ios", ); INFOPLIST_FILE = MetaMaskTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -1889,6 +1897,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1906,6 +1915,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = 1; DEAD_CODE_STRIPPING = NO; + DEVELOPMENT_TEAM = L8GS6GD649; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", @@ -1925,6 +1935,7 @@ "$(SRCROOT)/../node_modules/react-native-camera/ios/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-web3-webview/ios", ); INFOPLIST_FILE = MetaMask/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1944,6 +1955,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = L8GS6GD649; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", @@ -1963,6 +1975,7 @@ "$(SRCROOT)/../node_modules/react-native-camera/ios/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-web3-webview/ios", ); INFOPLIST_FILE = MetaMask/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1987,6 +2000,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = L8GS6GD649; ENABLE_TESTABILITY = YES; GCC_NO_COMMON_BLOCKS = YES; HEADER_SEARCH_PATHS = ( @@ -2004,6 +2018,7 @@ "$(SRCROOT)/../node_modules/react-native-camera/ios/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-web3-webview/ios", ); INFOPLIST_FILE = "MetaMask-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -2026,6 +2041,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -2050,6 +2066,7 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = L8GS6GD649; GCC_NO_COMMON_BLOCKS = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -2066,6 +2083,7 @@ "$(SRCROOT)/../node_modules/react-native-camera/ios/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-web3-webview/ios", ); INFOPLIST_FILE = "MetaMask-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -2088,6 +2106,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -2110,6 +2129,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = L8GS6GD649; ENABLE_TESTABILITY = YES; GCC_NO_COMMON_BLOCKS = YES; HEADER_SEARCH_PATHS = ( @@ -2127,6 +2147,7 @@ "$(SRCROOT)/../node_modules/react-native-camera/ios/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-web3-webview/ios", ); INFOPLIST_FILE = "MetaMask-tvOSTests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -2149,6 +2170,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -2172,6 +2194,7 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = L8GS6GD649; GCC_NO_COMMON_BLOCKS = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -2188,6 +2211,7 @@ "$(SRCROOT)/../node_modules/react-native-camera/ios/**", "$(SRCROOT)/../node_modules/react-native-i18n/ios", "$(SRCROOT)/../node_modules/react-native-share/ios", + "$(SRCROOT)/../node_modules/react-native-web3-webview/ios", ); INFOPLIST_FILE = "MetaMask-tvOSTests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -2210,6 +2234,7 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", diff --git a/package-lock.json b/package-lock.json index bdae7effec0..5c0777ec8b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12544,10 +12544,8 @@ } } }, - "react-native-wkwebview-reborn": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/react-native-wkwebview-reborn/-/react-native-wkwebview-reborn-1.21.0.tgz", - "integrity": "sha512-rOxkZTRc9CZSngPY+xRfzrSdXlUGU5NIF8Ckur46D1awIsK4RsvDSO07+wFLk9pZ8PwyD82+D7IM3pPbRORjjA==", + "react-native-web3-webview": { + "version": "github:brunobar79/react-native-web3-webview#4e653d77b53d49751974710ebcb247debe7dd38d", "requires": { "fbjs": "0.8.17" } diff --git a/package.json b/package.json index 643058fa725..8d33e0b6b6f 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "react-native-settings-list": "^1.8.0", "react-native-share": "^1.1.1", "react-native-vector-icons": "^4.6.0", - "react-native-wkwebview-reborn": "1.21.0", + "react-native-web3-webview": "github:brunobar79/react-native-web3-webview#master", "react-navigation": "^2.6.2", "react-redux": "^5.0.7", "readable-stream": "^1.0.33", diff --git a/scripts/postinstall.sh b/scripts/postinstall.sh index ef6cd55199a..0cfb8f1398d 100755 --- a/scripts/postinstall.sh +++ b/scripts/postinstall.sh @@ -1,19 +1,11 @@ #!/bin/bash echo "PostInstall script:" -# Submitted a PR for this one: https://github.com/CRAlpha/react-native-wkwebview/pull/174 -# We should remove this once it gets merged -echo "1. Fixing WKWebView..." -WKWEBVIEW_FILE=$(find . -name RCTWKWebView.m); -sed -i '' -e '143s/WKUserScriptInjectionTimeAtDocumentEnd/WKUserScriptInjectionTimeAtDocumentStart/' $WKWEBVIEW_FILE; -echo "Done" - -echo "2. React Native nodeify..." +echo "1. React Native nodeify..." node_modules/.bin/rn-nodeify --install 'crypto,buffer,react-native-randombytes,vm,stream' --hack -sed -i '' -e '143s/WKUserScriptInjectionTimeAtDocumentEnd/WKUserScriptInjectionTimeAtDocumentStart/' $WKWEBVIEW_FILE; # We need to submit a PR for this one. -echo "3. Fix react-native-os buildTools version..." +echo "2. Fix react-native-os buildTools version..." TARGET="node_modules/react-native-os/android/build.gradle" sed -i '' -e 's/compileSdkVersion 23/compileSdkVersion 26/' $TARGET; sed -i '' -e 's/23.0.1/27.0.3/' $TARGET; @@ -21,7 +13,7 @@ echo "Done" # This one has been fixed on master # we can remove once they release a new version -echo "4. Fix react-native-fs buildTools version..." +echo "3. Fix react-native-fs buildTools version..." TARGET="node_modules/react-native-fs/android/build.gradle" sed -i '' -e 's/compileSdkVersion 25/compileSdkVersion 26/' $TARGET; sed -i '' -e 's/25.0.0/27.0.3/' $TARGET; @@ -29,31 +21,31 @@ echo "Done" # The build output from aes-js breaks the metro bundler. Until we safely upgrade # to a new version of aes-js, we patch it by removing the erroneous line. -echo "5. Fix aes-js build ouput..." +echo "4. Fix aes-js build ouput..." AES_OUTPUT_FILE="node_modules/aes-js/index.js"; sed -i '' -e 's/var previous_mymodule = root.mymodule;//g' $AES_OUTPUT_FILE; # Reported here https://github.com/skv-headless/react-native-scrollable-tab-view/issues/910 -echo "6. Fix react-native-scrollable-tab-view" +echo "5. Fix react-native-scrollable-tab-view" TARGET="node_modules/react-native-scrollable-tab-view/SceneComponent.js" sed -i '' -e 's/...props,/...props/' $TARGET; echo "Done" # Waiting for PR to get merged: https://github.com/seekshiva/react-native-remote-svg/pull/18 -echo "7. Fix react-native-remove-svg" +echo "6. Fix react-native-remove-svg" TARGET="node_modules/react-native-remote-svg/SvgImage.js" sed -i '' 's/ Date: Sat, 1 Sep 2018 14:02:06 -0400 Subject: [PATCH 06/12] fix unit tests --- .../Browser/__snapshots__/index.test.js.snap | 31 +++++++------------ app/components/Browser/index.js | 3 -- app/components/Browser/index.test.js | 17 ++++++---- .../Main/__snapshots__/index.test.js.snap | 2 +- 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/app/components/Browser/__snapshots__/index.test.js.snap b/app/components/Browser/__snapshots__/index.test.js.snap index 9fd0dae42d7..65b083c41ed 100644 --- a/app/components/Browser/__snapshots__/index.test.js.snap +++ b/app/components/Browser/__snapshots__/index.test.js.snap @@ -26,11 +26,11 @@ exports[`Browser should render correctly 1`] = ` size={30} style={ Object { + "alignSelf": "center", "color": "#ced6e0", "flex": 0, "height": 28, "lineHeight": 28, - "paddingTop": 2, "textAlign": "center", "width": 36, } @@ -44,11 +44,11 @@ exports[`Browser should render correctly 1`] = ` size={30} style={ Object { + "alignSelf": "center", "color": "#ced6e0", "flex": 0, "height": 28, "lineHeight": 28, - "paddingTop": 2, "textAlign": "center", "width": 36, } @@ -81,17 +81,16 @@ exports[`Browser should render correctly 1`] = ` /> - + > + + `; diff --git a/app/components/Browser/index.js b/app/components/Browser/index.js index a174fe2a2c4..9de1b3f19ec 100644 --- a/app/components/Browser/index.js +++ b/app/components/Browser/index.js @@ -217,12 +217,9 @@ export class Browser extends Component { { it('should enable back button', () => { const wrapper = shallow(); + wrapper.setState({ entryScriptWeb3: 'let inject=true;' }); expect(wrapper.find('[name="angle-left"]').prop('disabled')).toBe(true); - wrapper.find(WKWebView).simulate('NavigationStateChange', { canGoBack: true }); + wrapper.find(Web3Webview).simulate('NavigationStateChange', { canGoBack: true }); expect(wrapper.find('[name="angle-left"]').prop('disabled')).toBe(false); }); it('should enable forward button', () => { const wrapper = shallow(); + wrapper.setState({ entryScriptWeb3: 'let inject=true;' }); expect(wrapper.find('[name="angle-right"]').prop('disabled')).toBe(true); - wrapper.find(WKWebView).simulate('NavigationStateChange', { canGoForward: true }); + wrapper.find(Web3Webview).simulate('NavigationStateChange', { canGoForward: true }); expect(wrapper.find('[name="angle-right"]').prop('disabled')).toBe(false); }); @@ -48,7 +50,8 @@ describe('Browser', () => { const MockWebView = { goBack() {} }; // eslint-disable-line no-empty-function const stub = spyOn(MockWebView, 'goBack'); const wrapper = shallow(); - wrapper.find(WKWebView).simulate('NavigationStateChange', { canGoBack: true }); + wrapper.setState({ entryScriptWeb3: 'let inject=true;' }); + wrapper.find(Web3Webview).simulate('NavigationStateChange', { canGoBack: true }); wrapper.instance().webview = { current: MockWebView }; wrapper.find('[name="angle-left"]').simulate('press'); expect(stub).toBeCalled(); @@ -58,7 +61,8 @@ describe('Browser', () => { const MockWebView = { goForward() {} }; // eslint-disable-line no-empty-function const stub = spyOn(MockWebView, 'goForward'); const wrapper = shallow(); - wrapper.find(WKWebView).simulate('NavigationStateChange', { canGoBack: true }); + wrapper.setState({ entryScriptWeb3: 'let inject=true;' }); + wrapper.find(Web3Webview).simulate('NavigationStateChange', { canGoBack: true }); wrapper.instance().webview = { current: MockWebView }; wrapper.find('[name="angle-right"]').simulate('press'); expect(stub).toBeCalled(); @@ -68,7 +72,8 @@ describe('Browser', () => { const MockWebView = { reload() {} }; // eslint-disable-line no-empty-function const stub = spyOn(MockWebView, 'reload'); const wrapper = shallow(); - wrapper.find(WKWebView).simulate('NavigationStateChange', {}); + wrapper.setState({ entryScriptWeb3: 'let inject=true;' }); + wrapper.find(Web3Webview).simulate('NavigationStateChange', {}); wrapper.instance().webview = { current: MockWebView }; wrapper.find('[name="refresh"]').simulate('press'); expect(stub).toBeCalled(); diff --git a/app/components/Main/__snapshots__/index.test.js.snap b/app/components/Main/__snapshots__/index.test.js.snap index 56e4590e9be..4242092c985 100644 --- a/app/components/Main/__snapshots__/index.test.js.snap +++ b/app/components/Main/__snapshots__/index.test.js.snap @@ -69,7 +69,7 @@ exports[`Main should render correctly 1`] = ` }, "setParams": [Function], "state": Object { - "index": 1, + "index": 0, "isTransitioning": false, "routes": Array [ Object { From c5415f842d73e4258bf44513957c131fcb168b37 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Sat, 1 Sep 2018 14:29:24 -0400 Subject: [PATCH 07/12] update unit tests --- app/components/Browser/index.js | 9 +-------- package-lock.json | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/app/components/Browser/index.js b/app/components/Browser/index.js index 9de1b3f19ec..5391555231f 100644 --- a/app/components/Browser/index.js +++ b/app/components/Browser/index.js @@ -170,13 +170,6 @@ export class Browser extends Component { render() { const { canGoBack, canGoForward, entryScriptWeb3, inputValue, url } = this.state; - const injectionProps = {}; - - if (Platform.OS === 'android') { - injectionProps.injectedOnStartLoadingJavaScript = entryScriptWeb3; - } else { - injectionProps.injectJavaScript = entryScriptWeb3; - } return ( @@ -215,7 +208,7 @@ export class Browser extends Component { {entryScriptWeb3 ? ( Date: Sat, 1 Sep 2018 16:26:05 -0400 Subject: [PATCH 08/12] working --- android/app/build.gradle | 46 ++++++++-------- android/app/src/main/AndroidManifest.xml | 3 -- .../java/com/metamask/MainApplication.java | 24 ++++++++- android/build.gradle | 1 - android/settings.gradle | 3 ++ .../Browser/__snapshots__/index.test.js.snap | 12 +++-- app/components/Browser/index.js | 6 ++- .../Main/__snapshots__/index.test.js.snap | 2 +- app/components/Main/index.js | 2 +- package-lock.json | 54 +------------------ package.json | 2 +- scripts/postinstall.sh | 21 ++++++++ 12 files changed, 89 insertions(+), 87 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index cd303db9c1e..f82c337d2aa 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -132,6 +132,9 @@ android { ndk { abiFilters "armeabi-v7a", "x86" } + dexOptions { + javaMaxHeapSize "2048M" + } } splits { abi { @@ -163,31 +166,30 @@ android { } dependencies { - compile project(':react-native-web3-webview') - compile project(':react-native-camera') - compile project(':react-native-share') - compile project(':react-native-i18n') - compile project(':react-native-fabric') - compile 'com.android.support:multidex:1.0.1' - compile project(':react-native-aes-crypto') - compile project(':react-native-keychain') - compile project(':react-native-os') - compile project(':react-native-linear-gradient') - compile project(':react-native-randombytes') - compile project(':react-native-fs') - compile project(':react-native-vector-icons') - compile fileTree(dir: "libs", include: ["*.jar"]) - compile "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}" - compile "com.facebook.react:react-native:+" // From node_modules - compile('com.crashlytics.sdk.android:crashlytics:2.9.4@aar') { + api project(':react-native-web3-webview') + api project(':react-native-camera') + api project(':react-native-share') + api project(':react-native-i18n') + api project(':react-native-fabric') + api 'com.android.support:multidex:1.0.1' + api project(':react-native-aes-crypto') + api project(':react-native-keychain') + api project(':react-native-os') + api project(':react-native-linear-gradient') + api project(':react-native-randombytes') + api project(':react-native-fs') + api project(':react-native-vector-icons') + api fileTree(dir: "libs", include: ["*.jar"]) + api "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}" + api "com.facebook.react:react-native:+" // From node_modules + api('com.crashlytics.sdk.android:crashlytics:2.9.4@aar') { transitive = true; } - androidTestCompile(project(path: ":detox")) - androidTestCompile 'junit:junit:4.12' - androidTestCompile 'com.android.support.test:runner:1.0.1' - androidTestCompile 'com.android.support.test:rules:1.0.1' - + androidTestImplementation(project(path: ":detox")) + androidTestImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.1' + androidTestImplementation 'com.android.support.test:rules:1.0.1' } // Run this once to be able to run the application with BUCK diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 1b41fc63aac..77c05f1bd02 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -35,9 +35,6 @@ - diff --git a/android/app/src/main/java/com/metamask/MainApplication.java b/android/app/src/main/java/com/metamask/MainApplication.java index 3dd8bfe575c..4c2726dc375 100644 --- a/android/app/src/main/java/com/metamask/MainApplication.java +++ b/android/app/src/main/java/com/metamask/MainApplication.java @@ -4,7 +4,18 @@ import com.crashlytics.android.Crashlytics; import com.facebook.react.ReactApplication; -import com.metamask.Web3Webview.Web3WebviewPackage; +import com.web3webview.Web3WebviewPackage; +import com.oblador.vectoricons.VectorIconsPackage; +import cl.json.RNSharePackage; +import com.bitgo.randombytes.RandomBytesPackage; +import com.peel.react.rnos.RNOSModule; +import com.BV.LinearGradient.LinearGradientPackage; +import com.oblador.keychain.KeychainPackage; +import com.AlexanderZaytsev.RNI18n.RNI18nPackage; +import com.rnfs.RNFSPackage; +import com.smixx.fabric.FabricPackage; +import org.reactnative.camera.RNCameraPackage; +import com.tectiv3.aes.RCTAesPackage; import org.reactnative.camera.RNCameraPackage; import cl.json.RNSharePackage; import com.AlexanderZaytsev.RNI18n.RNI18nPackage; @@ -41,6 +52,17 @@ protected List getPackages() { return Arrays.asList( new MainReactPackage(), new Web3WebviewPackage(), + new VectorIconsPackage(), + new RNSharePackage(), + new RandomBytesPackage(), + new RNOSModule(), + new LinearGradientPackage(), + new KeychainPackage(), + new RNI18nPackage(), + new RNFSPackage(), + new FabricPackage(), + new RNCameraPackage(), + new RCTAesPackage(), new RNCameraPackage(), new RNSharePackage(), new RNI18nPackage(), diff --git a/android/build.gradle b/android/build.gradle index 3fa514c2ec2..bedca175dfb 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -7,7 +7,6 @@ buildscript { url 'https://maven.google.com/' name 'Google' } - google() } dependencies { classpath 'com.android.tools.build:gradle:3.1.4' diff --git a/android/settings.gradle b/android/settings.gradle index d79ada04cd0..218ed16fb0c 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,6 +1,9 @@ rootProject.name = 'MetaMask' + include ':react-native-web3-webview' project(':react-native-web3-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-web3-webview/android') +include ':react-native-aes-crypto' +project(':react-native-aes-crypto').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-aes-crypto/android') include ':react-native-camera' project(':react-native-camera').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-camera/android') include ':react-native-share' diff --git a/app/components/Browser/__snapshots__/index.test.js.snap b/app/components/Browser/__snapshots__/index.test.js.snap index 65b083c41ed..29a225a13ef 100644 --- a/app/components/Browser/__snapshots__/index.test.js.snap +++ b/app/components/Browser/__snapshots__/index.test.js.snap @@ -3,9 +3,15 @@ exports[`Browser should render correctly 1`] = ` + Date: Sat, 1 Sep 2018 17:00:10 -0400 Subject: [PATCH 09/12] clean up --- android/.project | 17 ++++++ .../org.eclipse.buildship.core.prefs | 2 + android/app/.classpath | 6 +++ android/app/.project | 23 ++++++++ .../org.eclipse.buildship.core.prefs | 2 + .../java/com/metamask/MainApplication.java | 36 +++---------- android/settings.gradle | 26 +++++---- package-lock.json | 54 ++++++++++++++++++- package.json | 2 +- 9 files changed, 123 insertions(+), 45 deletions(-) create mode 100644 android/.project create mode 100644 android/.settings/org.eclipse.buildship.core.prefs create mode 100644 android/app/.classpath create mode 100644 android/app/.project create mode 100644 android/app/.settings/org.eclipse.buildship.core.prefs diff --git a/android/.project b/android/.project new file mode 100644 index 00000000000..3cf8618bf4c --- /dev/null +++ b/android/.project @@ -0,0 +1,17 @@ + + + MetaMask + Project MetaMask created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 00000000000..e8895216fd3 --- /dev/null +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1 diff --git a/android/app/.classpath b/android/app/.classpath new file mode 100644 index 00000000000..eb19361b571 --- /dev/null +++ b/android/app/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/android/app/.project b/android/app/.project new file mode 100644 index 00000000000..ac485d7c3e6 --- /dev/null +++ b/android/app/.project @@ -0,0 +1,23 @@ + + + app + Project app created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/android/app/.settings/org.eclipse.buildship.core.prefs b/android/app/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 00000000000..b1886adb46c --- /dev/null +++ b/android/app/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1 diff --git a/android/app/src/main/java/com/metamask/MainApplication.java b/android/app/src/main/java/com/metamask/MainApplication.java index 4c2726dc375..469a420981e 100644 --- a/android/app/src/main/java/com/metamask/MainApplication.java +++ b/android/app/src/main/java/com/metamask/MainApplication.java @@ -16,17 +16,6 @@ import com.smixx.fabric.FabricPackage; import org.reactnative.camera.RNCameraPackage; import com.tectiv3.aes.RCTAesPackage; -import org.reactnative.camera.RNCameraPackage; -import cl.json.RNSharePackage; -import com.AlexanderZaytsev.RNI18n.RNI18nPackage; -import com.smixx.fabric.FabricPackage; -import com.tectiv3.aes.RCTAesPackage; -import com.oblador.keychain.KeychainPackage; -import com.peel.react.rnos.RNOSModule; -import com.BV.LinearGradient.LinearGradientPackage; -import com.bitgo.randombytes.RandomBytesPackage; -import com.rnfs.RNFSPackage; -import com.oblador.vectoricons.VectorIconsPackage; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; @@ -51,29 +40,18 @@ public boolean getUseDeveloperSupport() { protected List getPackages() { return Arrays.asList( new MainReactPackage(), - new Web3WebviewPackage(), - new VectorIconsPackage(), - new RNSharePackage(), - new RandomBytesPackage(), - new RNOSModule(), - new LinearGradientPackage(), - new KeychainPackage(), - new RNI18nPackage(), - new RNFSPackage(), - new FabricPackage(), - new RNCameraPackage(), - new RCTAesPackage(), - new RNCameraPackage(), - new RNSharePackage(), - new RNI18nPackage(), new FabricPackage(), - new RCTAesPackage(), new KeychainPackage(), - new RNOSModule(), new LinearGradientPackage(), new RandomBytesPackage(), + new RCTAesPackage(), + new RNCameraPackage(), new RNFSPackage(), - new VectorIconsPackage() + new RNI18nPackage(), + new RNOSModule(), + new RNSharePackage(), + new VectorIconsPackage(), + new Web3WebviewPackage() ); } diff --git a/android/settings.gradle b/android/settings.gradle index 218ed16fb0c..18b653c6ea0 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,32 +1,30 @@ rootProject.name = 'MetaMask' -include ':react-native-web3-webview' -project(':react-native-web3-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-web3-webview/android') +include ':detox' +project(':detox').projectDir = new File(rootProject.projectDir, '../node_modules/detox/android/detox') include ':react-native-aes-crypto' project(':react-native-aes-crypto').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-aes-crypto/android') include ':react-native-camera' project(':react-native-camera').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-camera/android') -include ':react-native-share' -project(':react-native-share').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-share/android') -include ':react-native-i18n' -project(':react-native-i18n').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-i18n/android') include ':react-native-fabric' project(':react-native-fabric').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fabric/android') -include ':react-native-aes-crypto' -project(':react-native-aes-crypto').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-aes-crypto/android') +include ':react-native-fs' +project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android') +include ':react-native-i18n' +project(':react-native-i18n').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-i18n/android') include ':react-native-keychain' project(':react-native-keychain').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keychain/android') -include ':react-native-os' -project(':react-native-os').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-os/android') include ':react-native-linear-gradient' project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android') +include ':react-native-os' +project(':react-native-os').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-os/android') +include ':react-native-share' +project(':react-native-share').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-share/android') include ':react-native-randombytes' project(':react-native-randombytes').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-randombytes/android') -include ':react-native-fs' -project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android') include ':react-native-vector-icons' project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android') -include ':detox' -project(':detox').projectDir = new File(rootProject.projectDir, '../node_modules/detox/android/detox') +include ':react-native-web3-webview' +project(':react-native-web3-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-web3-webview/android') include ':app' diff --git a/package-lock.json b/package-lock.json index c718e5b1e41..41ae2746de9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -754,6 +754,12 @@ "integrity": "sha512-6Qnb1gXbp3g1JX9QVJj3A6ORzc9XCyhokxUKaoonHgNXcQhmk8adhotxfkeK8El9TnFeUuH72yI6jQ5nDJKS6w==", "dev": true }, + "@yarnpkg/lockfile": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.0.2.tgz", + "integrity": "sha512-MqJ00WXw89ga0rK6GZkdmmgv3bAsxpJixyTthjcix73O44pBqotyU2BejBkLuIsaOBI6SEu77vAnSyLe5iIHkw==", + "dev": true + }, "abab": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", @@ -5718,6 +5724,12 @@ "pinkie-promise": "2.0.1" } }, + "findit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findit/-/findit-2.0.0.tgz", + "integrity": "sha1-ZQnwEmr0wXhVHPqZOU4DLhOk1W4=", + "dev": true + }, "flat-cache": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", @@ -12533,7 +12545,7 @@ } }, "react-native-web3-webview": { - "version": "github:brunobar79/react-native-web3-webview#0dba7eac694c6f0a850fce613e91ae9884cc5472", + "version": "github:brunobar79/react-native-web3-webview#2ff4f74002fc5e00cc6043a1b3ca30a9cd6b01ea", "requires": { "fbjs": "0.8.17" } @@ -13037,6 +13049,40 @@ "safe-buffer": "5.1.2" } }, + "rn-nodeify": { + "version": "github:tradle/rn-nodeify#f871fadfed6edef6e208bb3293e66f27466122da", + "dev": true, + "requires": { + "@yarnpkg/lockfile": "1.0.2", + "deep-equal": "1.0.1", + "findit": "2.0.0", + "fs-extra": "0.22.1", + "minimist": "1.2.0", + "object.pick": "1.3.0", + "run-parallel": "1.1.9", + "semver": "5.5.0", + "xtend": "4.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "0.22.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.22.1.tgz", + "integrity": "sha1-X9b4BJ3JdsoZ6yNV1lgXPKvM4FY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "rimraf": "2.6.2" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "rst-selector-parser": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", @@ -13066,6 +13112,12 @@ "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", "dev": true }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true + }, "rustbn.js": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.1.2.tgz", diff --git a/package.json b/package.json index 9e939b56e46..76e4dd1bdcf 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "react-native-settings-list": "^1.8.0", "react-native-share": "^1.1.1", "react-native-vector-icons": "^4.6.0", - "react-native-web3-webview": "github:brunobar79/react-native-web3-webview#0dba7eac694c6f0a850fce613e91ae9884cc5472", + "react-native-web3-webview": "^1.0.0", "react-navigation": "^2.6.2", "react-redux": "^5.0.7", "readable-stream": "^1.0.33", From 620fc3004d26afedec7975082b9ffe3246afdd7a Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Sat, 1 Sep 2018 17:09:32 -0400 Subject: [PATCH 10/12] cleanup --- android/.project | 17 -------------- .../org.eclipse.buildship.core.prefs | 2 -- android/app/.classpath | 6 ----- android/app/.project | 23 ------------------- .../org.eclipse.buildship.core.prefs | 2 -- .../Browser/__snapshots__/index.test.js.snap | 13 ++++------- app/components/Browser/index.js | 2 +- 7 files changed, 5 insertions(+), 60 deletions(-) delete mode 100644 android/.project delete mode 100644 android/.settings/org.eclipse.buildship.core.prefs delete mode 100644 android/app/.classpath delete mode 100644 android/app/.project delete mode 100644 android/app/.settings/org.eclipse.buildship.core.prefs diff --git a/android/.project b/android/.project deleted file mode 100644 index 3cf8618bf4c..00000000000 --- a/android/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - MetaMask - Project MetaMask created by Buildship. - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.buildship.core.gradleprojectnature - - diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index e8895216fd3..00000000000 --- a/android/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,2 +0,0 @@ -connection.project.dir= -eclipse.preferences.version=1 diff --git a/android/app/.classpath b/android/app/.classpath deleted file mode 100644 index eb19361b571..00000000000 --- a/android/app/.classpath +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/android/app/.project b/android/app/.project deleted file mode 100644 index ac485d7c3e6..00000000000 --- a/android/app/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - app - Project app created by Buildship. - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.buildship.core.gradleprojectnature - - diff --git a/android/app/.settings/org.eclipse.buildship.core.prefs b/android/app/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index b1886adb46c..00000000000 --- a/android/app/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,2 +0,0 @@ -connection.project.dir=.. -eclipse.preferences.version=1 diff --git a/app/components/Browser/__snapshots__/index.test.js.snap b/app/components/Browser/__snapshots__/index.test.js.snap index 29a225a13ef..b36a5d8ebc8 100644 --- a/app/components/Browser/__snapshots__/index.test.js.snap +++ b/app/components/Browser/__snapshots__/index.test.js.snap @@ -3,15 +3,10 @@ exports[`Browser should render correctly 1`] = ` + Date: Sat, 1 Sep 2018 18:07:50 -0400 Subject: [PATCH 11/12] use mac osx for builds --- .circleci/config.yml | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ff683cdc0f1..1dce956a1bf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -20,8 +20,8 @@ version: 2 jobs: prep-deps: <<: *defaults - docker: - - image: circleci/node:9 + macos: + xcode: "9.4.1" steps: - checkout - restore_cache: *restore-cache @@ -34,8 +34,8 @@ jobs: lint: <<: *defaults - docker: - - image: circleci/node:9 + macos: + xcode: "9.4.1" steps: - checkout - attach_workspace: @@ -44,8 +44,8 @@ jobs: test-unit: <<: *defaults - docker: - - image: circleci/node:9 + macos: + xcode: "9.4.1" steps: - checkout - attach_workspace: @@ -65,7 +65,6 @@ jobs: - checkout - attach_workspace: at: . - - run: npm rebuild - run: name: Load dependencies command: @@ -78,8 +77,8 @@ jobs: upload-coverage: <<: *defaults - docker: - - image: circleci/node:9 + macos: + xcode: "9.4.1" steps: - checkout - attach_workspace: @@ -88,8 +87,8 @@ jobs: - run: codecov all-tests-pass: - docker: - - image: circleci/node:9 + macos: + xcode: "9.4.1" steps: - run: name: All Tests Passed From 458c037f6c866eb7bfec995389cb9189e3dc4ae3 Mon Sep 17 00:00:00 2001 From: brunobar79 Date: Sat, 1 Sep 2018 18:10:29 -0400 Subject: [PATCH 12/12] fix circle config --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1dce956a1bf..5ec7f33e70d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -60,7 +60,6 @@ jobs: <<: *defaults macos: xcode: "9.4.1" - steps: - checkout - attach_workspace: @@ -87,9 +86,10 @@ jobs: - run: codecov all-tests-pass: - macos: + <<: *defaults + macos: xcode: "9.4.1" - steps: + steps: - run: name: All Tests Passed command: echo 'weew - everything passed!'