Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

TIMOB-5824-2_1_X: Android: WebView.evalJS Causes Form Input Fields to Lost/Not Retain Focus #2558

Merged
merged 5 commits into from
Jul 13, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -311,26 +311,18 @@ public void release()

@Override
public void onStart(Activity activity) {
// TODO Auto-generated method stub

}

@Override
public void onResume(Activity activity) {
// TODO Auto-generated method stub

}

@Override
public void onPause(Activity activity) {
// TODO Auto-generated method stub

}

@Override
public void onStop(Activity activity) {
// TODO Auto-generated method stub

}

@Override
Expand All @@ -340,6 +332,11 @@ public void onDestroy(Activity activity) {
return;
}

// We allow JS polling to continue until we exit the app. If we want to stop the polling when the app is
// backgrounded, we would need to move this to onStop(), and add the appropriate logic in onResume() to restart
// the polling.
webView.destroyWebViewBinding();

WebView nativeWebView = webView.getWebView();
if (nativeWebView == null) {
return;
Expand All @@ -348,6 +345,5 @@ public void onDestroy(Activity activity) {
nativeWebView.stopLoading();
super.releaseViews();
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,6 @@ public void setUrl(String url)
getWebView().getSettings().setLoadWithOverviewMode(true);
}
getWebView().loadUrl(finalUrl);

}

public void changeProxyUrl(String url)
Expand Down Expand Up @@ -465,6 +464,11 @@ public void setBasicAuthentication(String username, String password)
client.setBasicAuthentication(username, password);
}

public void destroyWebViewBinding()
{
client.getBinding().destroy();
}

public void setPluginState(int pluginState)
{
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ECLAIR_MR1) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2009-2011 by Appcelerator, Inc. All Rights Reserved.
* Copyright (c) 2009-2012 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
Expand All @@ -11,7 +11,9 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Stack;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import org.appcelerator.kroll.KrollDict;
import org.appcelerator.kroll.KrollEventCallback;
Expand All @@ -35,9 +37,22 @@ public class TiWebViewBinding
// - minify binding.js to create binding.min.js
protected final static String SCRIPT_INJECTION_ID = "__ti_injection";
protected final static String INJECTION_CODE;

// This is based on polling.min.js. If you have to change anything...
// - change polling.js
// - minify polling.js to create polling.min.js
protected static String POLLING_CODE = "";
static {
StringBuilder jsonCode = readResourceFile("json2.js");
StringBuilder tiCode = readResourceFile("binding.min.js");
StringBuilder pollingCode = readResourceFile("polling.min.js");

if (pollingCode == null) {
Log.w(LCAT, "Unable to read polling code");
} else {
POLLING_CODE = pollingCode.toString();
}

StringBuilder allCode = new StringBuilder();
allCode.append("\n<script id=\"" + SCRIPT_INJECTION_ID + "\">\n");
if (jsonCode == null) {
Expand All @@ -59,13 +74,15 @@ public class TiWebViewBinding
allCode = null;
}

private WebView webView;
private Stack<String> codeSnippets;
private boolean destroyed;

private KrollLogging apiBinding;
private AppBinding appBinding;

public TiWebViewBinding(WebView webView)
{
this.webView = webView;
codeSnippets = new Stack<String>();

apiBinding = KrollLogging.getDefault();
appBinding = new AppBinding();
Expand All @@ -84,6 +101,10 @@ public void destroy()
// remove any event listener that have already been added to the Ti.APP through
// this web view instance
appBinding.clearEventListeners();

returnSemaphore.release();
codeSnippets.clear();
destroyed = true;
}

private static StringBuilder readResourceFile(String fileName)
Expand Down Expand Up @@ -111,25 +132,27 @@ private static StringBuilder readResourceFile(String fileName)
return code;
}

private void evalJS(String code)
{
webView.loadUrl("javascript:" + code);
}

private Semaphore returnSemaphore = new Semaphore(0);
private String returnValue;

public String getJSValue(String expression)
synchronized public String getJSValue(String expression)
{
String code = "javascript:_TiReturn.setValue((function(){try{return " + expression
+ "+\"\";}catch(ti_eval_err){return '';}})());";
Log.d(LCAT, "getJSValue:" + code);
webView.loadUrl(code);
try {
returnSemaphore.acquire();
return returnValue;
} catch (InterruptedException e) {
Log.e(LCAT, "Interrupted", e);
// Don't try to evaluate js code again if the binding has already been destroyed
if (!destroyed) {
String code = "_TiReturn.setValue((function(){try{return " + expression
+ "+\"\";}catch(ti_eval_err){return '';}})());";
Log.d(LCAT, "getJSValue:" + code);
synchronized (codeSnippets) {
codeSnippets.push(code);
}
try {
if (!returnSemaphore.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
Log.w(LCAT, "Timeout waiting to evaluate JS");
}
return returnValue;
} catch (InterruptedException e) {
Log.e(LCAT, "Interrupted", e);
}
}
return null;
}
Expand Down Expand Up @@ -168,7 +191,9 @@ public void call(Object data)
}

String code = "Ti.executeListener(" + id + dataString + ");";
evalJS(code);
synchronized (codeSnippets) {
codeSnippets.push(code);
}
}
}

Expand Down Expand Up @@ -217,5 +242,18 @@ public void clearEventListeners()
removeEventListener(event, appListeners.get(event));
}
}

public String getJSCode()
{
if (destroyed) {
return null;
}

String code;
synchronized (codeSnippets) {
code = codeSnippets.empty() ? "" : codeSnippets.pop();
}
return code;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ public void onPageFinished(WebView view, String url)
KrollDict data = new KrollDict();
data.put("url", url);
webView.getProxy().fireEvent("load", data);
WebView nativeWebView = webView.getWebView();

if (nativeWebView != null) {
webView.getWebView().loadUrl("javascript:" + TiWebViewBinding.POLLING_CODE);
}
}

public TiWebViewBinding getBinding()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,5 @@ var Ti = {
}
}
};

var Titanium = Ti;

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
function checkForJSCode() {
var code = TiApp.getJSCode();
if ( code != undefined) {
eval(code);
} else {
clearInterval(refreshIntervalId);
}
}

var refreshIntervalId = setInterval(checkForJSCode, 250);

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.