Bug fixes

This commit is contained in:
Vitaliy Vlasov 2020-05-04 20:55:55 +03:00
parent 25fbd400cf
commit a169a696b4
No known key found for this signature in database
GPG Key ID: A7D57C347F2B2964
1 changed files with 173 additions and 74 deletions

View File

@ -12,6 +12,7 @@ import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.OkHttpClient.Builder;
import okhttp3.Request;
import okhttp3.HttpUrl;
import okhttp3.Response;
import org.json.JSONException;
import org.json.JSONObject;
@ -295,10 +296,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
}
private Boolean urlStringLooksInvalid(String urlString) {
return urlString == null ||
urlString.trim().equals("") ||
!(urlString.startsWith("http") && !urlString.startsWith("www")) ||
urlString.contains("|");
return urlString == null || HttpUrl.parse(urlString) == null;
}
private Boolean responseRequiresJSInjection(Response response) {
@ -318,7 +316,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
Uri url = request.getUrl();
String urlStr = url.toString();
Log.i("StatusNativeLogs", "###shouldInterceptRequest 1");
Log.d(REACT_CLASS, "new request ");
Log.d(REACT_CLASS, "url " + urlStr);
Log.d(REACT_CLASS, "host " + request.getUrl().getHost());
@ -327,27 +324,36 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
Log.d(REACT_CLASS, "headers " + request.getRequestHeaders().toString());
Log.d(REACT_CLASS, "method " + request.getMethod());
Log.i("StatusNativeLogs", "###shouldInterceptRequest 2");
if (onlyMainFrame && !request.isForMainFrame() ||
urlStringLooksInvalid(urlStr)) {
return null;//super.shouldInterceptRequest(webView, request);
}
Log.i("StatusNativeLogs", "###shouldInterceptRequest 3");
Response response = null;
try {
Log.i("StatusNativeLogs", "###shouldInterceptRequest 4");
Request req = new Request.Builder()
.url(urlStr)
.header("User-Agent", userAgent)
.build();
Request.Builder reqBuilder = new Request.Builder().url(urlStr);
Log.i("StatusNativeLogs", "### httpCall " + new Boolean(httpClient != null).toString());
Response response = httpClient.newCall(req).execute();
Map<String, String> requestHeaders = request.getRequestHeaders();
for(String header: requestHeaders.keySet()) {
reqBuilder.header(header, requestHeaders.get(header));
}
Request httpRequest = reqBuilder.build();
response = httpClient.newCall(httpRequest).execute();
} catch (Exception e) {
Log.w(REACT_CLASS, "Error executing URL, ignoring: " + urlStr);
return null;
}
if (response == null) {
Log.w(REACT_CLASS, "Unexpected null response, ignore: " + urlStr);
}
Log.d(REACT_CLASS, "response headers " + response.headers().toString());
Log.d(REACT_CLASS, "response code " + response.code());
Log.d(REACT_CLASS, "response suc " + response.isSuccessful());
if (!responseRequiresJSInjection(response)) {
return null;
}
@ -357,15 +363,21 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8;
RNCWebView reactWebView = (RNCWebView) webView;
if (response.code() == HttpURLConnection.HTTP_OK) {
if (response.code() == HttpURLConnection.HTTP_OK ||
response.headers().get("content-type").toLowerCase().equals(HTML_MIME_TYPE)) {
is = new InputStreamWithInjectedJS(is, reactWebView.injectedJSBeforeContentLoaded, charset);
}
Log.d(REACT_CLASS, "inject our custom JS to this request");
return new WebResourceResponse("text/html", charset.name(), is);
} catch (IOException e) {
return null;
Map<String, String> responseHeaders = new HashMap<>();
for (String hname: response.headers().names()) {
Log.d(REACT_CLASS, "HEAD " + hname + " " + response.headers().get(hname));
responseHeaders.put(hname, response.headers().get(hname));
}
return new WebResourceResponse("text/html", charset.name(), response.code(), "phrase", responseHeaders, is);
}
@ReactProp(name = "javaScriptEnabled")
@ -874,11 +886,18 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
private InputStream pageIS;
private InputStream scriptIS;
private Charset charset;
private static final String REACT_CLASS = "InputStreamWithInjectedJS";
private static final String REACT_CLASS = "InpStreamWithInjectedJS";
private static Map<Charset, String> script = new HashMap<>();
private int GREATER_THAN_SIGN = 62;
private int LESS_THAN_SIGN = 60;
private int SCRIPT_TAG_LENGTH = 7;
private boolean hasJS = false;
private boolean headWasFound = false;
private boolean tagWasFound = false;
private int[] tag = new int[SCRIPT_TAG_LENGTH];
private boolean readFromTagVector = false;
private int tagVectorIdx = 0;
private int maxTagVectorIdx = SCRIPT_TAG_LENGTH;
private boolean scriptWasInjected = false;
private StringBuffer contentBuffer = new StringBuffer();
@ -919,38 +938,118 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
}
}
@Override
public int read() throws IOException {
if (scriptWasInjected || !hasJS) {
return pageIS.read();
}
if (!scriptWasInjected && headWasFound) {
private int readScript() throws IOException {
int nextByte = scriptIS.read();
if (nextByte == -1) {
scriptIS.close();
scriptWasInjected = true;
if(readFromTagVector) {
return readTag();
} else {
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("<head>")) {
this.scriptIS = getScript(this.charset);
headWasFound = true;
}
private int readTag() {
int nextByte = tag[tagVectorIdx];
tagVectorIdx++;
if(tagVectorIdx > maxTagVectorIdx) {
readFromTagVector = false;
}
return nextByte;
}
private boolean checkHeadTag(int nextByte) {
int bufferLength = contentBuffer.length();
if (nextByte == GREATER_THAN_SIGN &&
bufferLength >= 6 &&
contentBuffer.substring(bufferLength - 6).equals("<head>")) {
Log.d(REACT_CLASS, "<head> tag was found");
this.scriptIS = getScript(this.charset);
tagWasFound = true;
return true;
}
return false;
}
private boolean checkScriptTagByByte(int index, int anotherByte) {
if(index == 1) {
// 115 = "s"
return anotherByte == 115;
} else if(index == 2) {
// 99 = "c"
return anotherByte == 99;
}
return true;
}
private boolean checkScriptTag(int nextByte) throws IOException {
if (nextByte == LESS_THAN_SIGN) {
StringBuilder tagBuffer = new StringBuilder();
tag[0] = nextByte;
tagBuffer.append((char) nextByte);
readFromTagVector = true;
tagVectorIdx = 1;
maxTagVectorIdx = SCRIPT_TAG_LENGTH - 1;
for (int i = 1; i < SCRIPT_TAG_LENGTH; i++) {
int anotherByte = pageIS.read();
tag[i] = anotherByte;
tagBuffer.append((char) anotherByte);
contentBuffer.append((char) anotherByte);
if (!checkScriptTagByByte(i, anotherByte) || anotherByte == -1) {
maxTagVectorIdx = i;
return false;
}
}
if(tagBuffer.length() == SCRIPT_TAG_LENGTH) {
String sub = tagBuffer.substring(0, SCRIPT_TAG_LENGTH);
if (sub.equals("<script")) {
tagVectorIdx = 0;
Log.d(REACT_CLASS, "<script tag was found");
this.scriptIS = getScript(this.charset);
tagWasFound = true;
return true;
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
}
@Override
public int read() throws IOException {
if ((scriptWasInjected || !hasJS) && !readFromTagVector) {
return pageIS.read();
} else if (!scriptWasInjected && tagWasFound) {
return readScript();
} else if (readFromTagVector) {
return readTag();
} else {
int nextByte = pageIS.read();
contentBuffer.append((char) nextByte);
if (checkHeadTag(nextByte)) {
return nextByte;
} else if (checkScriptTag(nextByte)) {
return scriptIS.read();
} else {
return nextByte;
}
}
}
}