Bug fixes
This commit is contained in:
parent
52bb4d3f35
commit
e25b2b5ab4
|
@ -12,6 +12,7 @@ import okhttp3.MediaType;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.OkHttpClient.Builder;
|
import okhttp3.OkHttpClient.Builder;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
@ -293,10 +294,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Boolean urlStringLooksInvalid(String urlString) {
|
private Boolean urlStringLooksInvalid(String urlString) {
|
||||||
return urlString == null ||
|
return urlString == null || HttpUrl.parse(urlString) == null;
|
||||||
urlString.trim().equals("") ||
|
|
||||||
!(urlString.startsWith("http") && !urlString.startsWith("www")) ||
|
|
||||||
urlString.contains("|");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Boolean responseRequiresJSInjection(Response response) {
|
private Boolean responseRequiresJSInjection(Response response) {
|
||||||
|
@ -313,57 +311,71 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||||
|
|
||||||
|
|
||||||
public WebResourceResponse shouldInterceptRequest(WebResourceRequest request, Boolean onlyMainFrame, RNCWebView webView) {
|
public WebResourceResponse shouldInterceptRequest(WebResourceRequest request, Boolean onlyMainFrame, RNCWebView webView) {
|
||||||
Uri url = request.getUrl();
|
Uri url = request.getUrl();
|
||||||
String urlStr = url.toString();
|
String urlStr = url.toString();
|
||||||
|
|
||||||
Log.i("StatusNativeLogs", "###shouldInterceptRequest 1");
|
Log.d(REACT_CLASS, "new request ");
|
||||||
Log.d(REACT_CLASS, "new request ");
|
Log.d(REACT_CLASS, "url " + urlStr);
|
||||||
Log.d(REACT_CLASS, "url " + urlStr);
|
Log.d(REACT_CLASS, "host " + request.getUrl().getHost());
|
||||||
Log.d(REACT_CLASS, "host " + request.getUrl().getHost());
|
Log.d(REACT_CLASS, "path " + request.getUrl().getPath());
|
||||||
Log.d(REACT_CLASS, "path " + request.getUrl().getPath());
|
Log.d(REACT_CLASS, "main " + request.isForMainFrame());
|
||||||
Log.d(REACT_CLASS, "main " + request.isForMainFrame());
|
Log.d(REACT_CLASS, "headers " + request.getRequestHeaders().toString());
|
||||||
Log.d(REACT_CLASS, "headers " + request.getRequestHeaders().toString());
|
Log.d(REACT_CLASS, "method " + request.getMethod());
|
||||||
Log.d(REACT_CLASS, "method " + request.getMethod());
|
|
||||||
|
|
||||||
Log.i("StatusNativeLogs", "###shouldInterceptRequest 2");
|
if (onlyMainFrame && !request.isForMainFrame() ||
|
||||||
if (onlyMainFrame && !request.isForMainFrame() ||
|
urlStringLooksInvalid(urlStr)) {
|
||||||
urlStringLooksInvalid(urlStr)) {
|
return null;//super.shouldInterceptRequest(webView, request);
|
||||||
return null;//super.shouldInterceptRequest(webView, request);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Log.i("StatusNativeLogs", "###shouldInterceptRequest 3");
|
Response response = null;
|
||||||
try {
|
try {
|
||||||
Log.i("StatusNativeLogs", "###shouldInterceptRequest 4");
|
Request.Builder reqBuilder = new Request.Builder().url(urlStr);
|
||||||
Request req = new Request.Builder()
|
|
||||||
.url(urlStr)
|
|
||||||
.header("User-Agent", userAgent)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
Log.i("StatusNativeLogs", "### httpCall " + new Boolean(httpClient != null).toString());
|
Map<String, String> requestHeaders = request.getRequestHeaders();
|
||||||
Response response = httpClient.newCall(req).execute();
|
for(String header: requestHeaders.keySet()) {
|
||||||
|
reqBuilder.header(header, requestHeaders.get(header));
|
||||||
|
}
|
||||||
|
|
||||||
Log.d(REACT_CLASS, "response headers " + response.headers().toString());
|
Request httpRequest = reqBuilder.build();
|
||||||
Log.d(REACT_CLASS, "response code " + response.code());
|
response = httpClient.newCall(httpRequest).execute();
|
||||||
Log.d(REACT_CLASS, "response suc " + response.isSuccessful());
|
|
||||||
|
|
||||||
if (!responseRequiresJSInjection(response)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
InputStream is = response.body().byteStream();
|
} catch (Exception e) {
|
||||||
MediaType contentType = response.body().contentType();
|
Log.w(REACT_CLASS, "Error executing URL, ignoring: " + urlStr);
|
||||||
Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream is = response.body().byteStream();
|
||||||
|
MediaType contentType = response.body().contentType();
|
||||||
|
Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8;
|
||||||
|
|
||||||
|
RNCWebView reactWebView = (RNCWebView) webView;
|
||||||
|
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");
|
||||||
|
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);
|
||||||
|
|
||||||
RNCWebView reactWebView = (RNCWebView) webView;
|
|
||||||
if (response.code() == HttpURLConnection.HTTP_OK) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = "javaScriptEnabled")
|
@ReactProp(name = "javaScriptEnabled")
|
||||||
|
@ -862,11 +874,18 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||||
private InputStream pageIS;
|
private InputStream pageIS;
|
||||||
private InputStream scriptIS;
|
private InputStream scriptIS;
|
||||||
private Charset charset;
|
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 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 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 boolean scriptWasInjected = false;
|
||||||
private StringBuffer contentBuffer = new StringBuffer();
|
private StringBuffer contentBuffer = new StringBuffer();
|
||||||
|
|
||||||
|
@ -907,38 +926,118 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private int readScript() throws IOException {
|
||||||
public int read() throws IOException {
|
int nextByte = scriptIS.read();
|
||||||
if (scriptWasInjected || !hasJS) {
|
if (nextByte == -1) {
|
||||||
return pageIS.read();
|
scriptIS.close();
|
||||||
|
scriptWasInjected = true;
|
||||||
|
if(readFromTagVector) {
|
||||||
|
return readTag();
|
||||||
|
} else {
|
||||||
|
return pageIS.read();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nextByte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int readTag() {
|
||||||
|
int nextByte = tag[tagVectorIdx];
|
||||||
|
tagVectorIdx++;
|
||||||
|
if(tagVectorIdx > maxTagVectorIdx) {
|
||||||
|
readFromTagVector = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!scriptWasInjected && headWasFound) {
|
return nextByte;
|
||||||
int nextByte = scriptIS.read();
|
}
|
||||||
if (nextByte == -1) {
|
|
||||||
scriptIS.close();
|
private boolean checkHeadTag(int nextByte) {
|
||||||
scriptWasInjected = true;
|
int bufferLength = contentBuffer.length();
|
||||||
return pageIS.read();
|
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 {
|
} else {
|
||||||
return nextByte;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nextByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pageIS.read();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue