mirror of
https://github.com/apache/cordova-android.git
synced 2025-02-26 12:03:28 +08:00
Delete Cordova*Client classes, Create CordovaBridge, Delete more CordovaWebView symbols
Changes made in order to get xwalk working again
This commit is contained in:
parent
25a7b66296
commit
efcedabee0
@ -20,8 +20,6 @@ package org.apache.cordova;
|
||||
|
||||
import org.apache.cordova.CordovaInterface;
|
||||
import org.apache.cordova.LOG;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.AlertDialog;
|
||||
@ -44,7 +42,6 @@ import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* This class is the WebChromeClient that implements callbacks for our web view.
|
||||
@ -57,7 +54,7 @@ import android.util.Log;
|
||||
* @see CordovaWebViewClient
|
||||
* @see CordovaWebView
|
||||
*/
|
||||
public class AndroidChromeClient extends WebChromeClient implements CordovaChromeClient {
|
||||
public class AndroidChromeClient extends WebChromeClient {
|
||||
|
||||
public static final int FILECHOOSER_RESULTCODE = 5173;
|
||||
private static final String LOG_TAG = "AndroidChromeClient";
|
||||
@ -69,7 +66,7 @@ public class AndroidChromeClient extends WebChromeClient implements CordovaChrom
|
||||
private View mVideoProgressView;
|
||||
|
||||
// File Chooser
|
||||
public ValueCallback<Uri> mUploadMessage;
|
||||
protected ValueCallback<Uri> mUploadMessage;
|
||||
|
||||
public AndroidChromeClient(CordovaInterface ctx, AndroidWebView app) {
|
||||
this.cordova = ctx;
|
||||
@ -182,67 +179,9 @@ public class AndroidChromeClient extends WebChromeClient implements CordovaChrom
|
||||
@Override
|
||||
public boolean onJsPrompt(WebView view, String origin, String message, String defaultValue, JsPromptResult result) {
|
||||
// Unlike the @JavascriptInterface bridge, this method is always called on the UI thread.
|
||||
if (defaultValue != null && defaultValue.length() > 3 && defaultValue.startsWith("gap:")) {
|
||||
JSONArray array;
|
||||
try {
|
||||
array = new JSONArray(defaultValue.substring(4));
|
||||
int bridgeSecret = array.getInt(0);
|
||||
String service = array.getString(1);
|
||||
String action = array.getString(2);
|
||||
String callbackId = array.getString(3);
|
||||
String r = appView.exposedJsApi.exec(bridgeSecret, service, action, callbackId, message);
|
||||
result.confirm(r == null ? "" : r);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
result.cancel();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
result.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the native->JS bridge mode.
|
||||
else if (defaultValue != null && defaultValue.startsWith("gap_bridge_mode:")) {
|
||||
try {
|
||||
int bridgeSecret = Integer.parseInt(defaultValue.substring(16));
|
||||
appView.exposedJsApi.setNativeToJsBridgeMode(bridgeSecret, Integer.parseInt(message));
|
||||
result.cancel();
|
||||
} catch (NumberFormatException e){
|
||||
e.printStackTrace();
|
||||
result.cancel();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
result.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
// Polling for JavaScript messages
|
||||
else if (defaultValue != null && defaultValue.startsWith("gap_poll:")) {
|
||||
int bridgeSecret = Integer.parseInt(defaultValue.substring(9));
|
||||
try {
|
||||
String r = appView.exposedJsApi.retrieveJsMessages(bridgeSecret, "1".equals(message));
|
||||
result.confirm(r == null ? "" : r);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
result.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
else if (defaultValue != null && defaultValue.startsWith("gap_init:")) {
|
||||
// Protect against random iframes being able to talk through the bridge.
|
||||
// Trust only file URLs and the start URL's domain.
|
||||
// The extra origin.startsWith("http") is to protect against iframes with data: having "" as origin.
|
||||
if (origin.startsWith("file:") || (origin.startsWith("http") && appView.loadedUrl.startsWith(origin))) {
|
||||
// Enable the bridge
|
||||
int bridgeMode = Integer.parseInt(defaultValue.substring(9));
|
||||
appView.jsMessageQueue.setBridgeMode(bridgeMode);
|
||||
// Tell JS the bridge secret.
|
||||
int secret = appView.exposedJsApi.generateBridgeSecret();
|
||||
result.confirm(""+secret);
|
||||
} else {
|
||||
Log.e(LOG_TAG, "gap_init called from restricted origin: " + origin);
|
||||
result.cancel();
|
||||
}
|
||||
String handledRet = appView.bridge.promptOnJsPrompt(origin, message, defaultValue);
|
||||
if (handledRet != null) {
|
||||
result.confirm(handledRet);
|
||||
} else {
|
||||
// Returning false would also show a dialog, but the default one shows the origin (ugly).
|
||||
final JsPromptResult res = result;
|
||||
@ -375,8 +314,4 @@ public class AndroidChromeClient extends WebChromeClient implements CordovaChrom
|
||||
this.cordova.getActivity().startActivityForResult(Intent.createChooser(i, "File Browser"),
|
||||
FILECHOOSER_RESULTCODE);
|
||||
}
|
||||
|
||||
public ValueCallback<Uri> getValueCallback() {
|
||||
return this.mUploadMessage;
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.webkit.JavascriptInterface;
|
||||
import org.apache.cordova.PluginManager;
|
||||
import org.json.JSONException;
|
||||
|
||||
/**
|
||||
@ -28,70 +27,24 @@ import org.json.JSONException;
|
||||
* cordova-js/lib/android/plugin/android/promptbasednativeapi.js
|
||||
*/
|
||||
class AndroidExposedJsApi implements ExposedJsApi {
|
||||
private final CordovaBridge bridge;
|
||||
|
||||
private PluginManager pluginManager;
|
||||
private NativeToJsMessageQueue jsMessageQueue;
|
||||
private volatile int bridgeSecret = -1; // written by UI thread, read by JS thread.
|
||||
|
||||
public AndroidExposedJsApi(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue) {
|
||||
this.pluginManager = pluginManager;
|
||||
this.jsMessageQueue = jsMessageQueue;
|
||||
AndroidExposedJsApi(CordovaBridge bridge) {
|
||||
this.bridge = bridge;
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public String exec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException {
|
||||
verifySecret(bridgeSecret);
|
||||
// If the arguments weren't received, send a message back to JS. It will switch bridge modes and try again. See CB-2666.
|
||||
// We send a message meant specifically for this case. It starts with "@" so no other message can be encoded into the same string.
|
||||
if (arguments == null) {
|
||||
return "@Null arguments.";
|
||||
}
|
||||
|
||||
jsMessageQueue.setPaused(true);
|
||||
try {
|
||||
// Tell the resourceApi what thread the JS is running on.
|
||||
CordovaResourceApi.jsThread = Thread.currentThread();
|
||||
|
||||
pluginManager.exec(service, action, callbackId, arguments);
|
||||
String ret = "";
|
||||
if (!NativeToJsMessageQueue.DISABLE_EXEC_CHAINING) {
|
||||
ret = jsMessageQueue.popAndEncode(false);
|
||||
}
|
||||
return ret;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
} finally {
|
||||
jsMessageQueue.setPaused(false);
|
||||
}
|
||||
return bridge.jsExec(bridgeSecret, service, action, callbackId, arguments);
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public void setNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException {
|
||||
verifySecret(bridgeSecret);
|
||||
jsMessageQueue.setBridgeMode(value);
|
||||
bridge.jsSetNativeToJsBridgeMode(bridgeSecret, value);
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public String retrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException {
|
||||
verifySecret(bridgeSecret);
|
||||
return jsMessageQueue.popAndEncode(fromOnlineEvent);
|
||||
}
|
||||
|
||||
private void verifySecret(int value) throws IllegalAccessException {
|
||||
if (bridgeSecret < 0 || value != bridgeSecret) {
|
||||
throw new IllegalAccessException();
|
||||
}
|
||||
}
|
||||
|
||||
/** Called on page transitions */
|
||||
void clearBridgeSecret() {
|
||||
bridgeSecret = -1;
|
||||
}
|
||||
|
||||
/** Called by cordova.js to initialize the bridge. */
|
||||
int generateBridgeSecret() {
|
||||
bridgeSecret = (int)(Math.random() * Integer.MAX_VALUE);
|
||||
return bridgeSecret;
|
||||
return bridge.jsRetrieveJsMessages(bridgeSecret, fromOnlineEvent);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
@ -66,23 +65,21 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
private HashSet<Integer> boundKeyCodes = new HashSet<Integer>();
|
||||
|
||||
PluginManager pluginManager;
|
||||
private boolean paused;
|
||||
|
||||
private BroadcastReceiver receiver;
|
||||
|
||||
|
||||
/** Activities and other important classes **/
|
||||
private CordovaInterface cordova;
|
||||
CordovaWebViewClient viewClient;
|
||||
private CordovaChromeClient chromeClient;
|
||||
AndroidWebViewClient viewClient;
|
||||
private AndroidChromeClient chromeClient;
|
||||
|
||||
// Flag to track that a loadUrl timeout occurred
|
||||
int loadUrlTimeout = 0;
|
||||
|
||||
private long lastMenuEventTime = 0;
|
||||
|
||||
NativeToJsMessageQueue jsMessageQueue;
|
||||
AndroidExposedJsApi exposedJsApi;
|
||||
CordovaBridge bridge;
|
||||
|
||||
/** custom view created by the browser (a video player for example) */
|
||||
private View mCustomView;
|
||||
@ -94,21 +91,6 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
// The URL passed to loadUrl(), not necessarily the URL of the current page.
|
||||
String loadedUrl;
|
||||
|
||||
class ActivityResult {
|
||||
|
||||
int request;
|
||||
int result;
|
||||
Intent incoming;
|
||||
|
||||
public ActivityResult(int req, int res, Intent intent) {
|
||||
request = req;
|
||||
result = res;
|
||||
incoming = intent;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static final FrameLayout.LayoutParams COVER_SCREEN_GRAVITY_CENTER =
|
||||
new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
@ -127,24 +109,30 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
|
||||
// Use two-phase init so that the control will work with XML layouts.
|
||||
@Override
|
||||
public void init(CordovaInterface cordova, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient,
|
||||
List<PluginEntry> pluginEntries, Whitelist whitelist, CordovaPreferences preferences) {
|
||||
public void init(CordovaInterface cordova, List<PluginEntry> pluginEntries,
|
||||
Whitelist whitelist, CordovaPreferences preferences) {
|
||||
if (this.cordova != null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
this.cordova = cordova;
|
||||
setWebChromeClient(webChromeClient);
|
||||
setWebViewClient(webViewClient);
|
||||
this.whitelist = whitelist;
|
||||
this.preferences = preferences;
|
||||
|
||||
pluginManager = new PluginManager(this, this.cordova, pluginEntries);
|
||||
jsMessageQueue = new NativeToJsMessageQueue(this, cordova);
|
||||
exposedJsApi = new AndroidExposedJsApi(pluginManager, jsMessageQueue);
|
||||
resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
|
||||
|
||||
bridge = new CordovaBridge(pluginManager, new NativeToJsMessageQueue(this, cordova));
|
||||
pluginManager.addService("App", "org.apache.cordova.CoreAndroid");
|
||||
initWebViewSettings();
|
||||
|
||||
if (this.viewClient == null) {
|
||||
setWebViewClient(Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH ?
|
||||
new AndroidWebViewClient(cordova, this) :
|
||||
new IceCreamCordovaWebViewClient(cordova, this));
|
||||
}
|
||||
if (this.chromeClient == null) {
|
||||
setWebChromeClient(new AndroidChromeClient(cordova, this));
|
||||
}
|
||||
|
||||
exposeJsInterface();
|
||||
}
|
||||
|
||||
@ -253,19 +241,6 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CordovaChromeClient makeWebChromeClient(CordovaInterface cordova) {
|
||||
return new AndroidChromeClient(cordova, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CordovaWebViewClient makeWebViewClient(CordovaInterface cordova) {
|
||||
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
return new AndroidWebViewClient(cordova, this);
|
||||
}
|
||||
return new IceCreamCordovaWebViewClient(cordova, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to decide whether or not you need to request the
|
||||
* focus when your application start
|
||||
@ -284,80 +259,42 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
// use the prompt bridge instead.
|
||||
return;
|
||||
}
|
||||
AndroidExposedJsApi exposedJsApi = new AndroidExposedJsApi(bridge);
|
||||
this.addJavascriptInterface(exposedJsApi, "_cordovaNative");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWebViewClient(WebViewClient client) {
|
||||
this.viewClient = (CordovaWebViewClient)client;
|
||||
this.viewClient = (AndroidWebViewClient)client;
|
||||
super.setWebViewClient(client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWebChromeClient(WebChromeClient client) {
|
||||
this.chromeClient = (CordovaChromeClient)client;
|
||||
this.chromeClient = (AndroidChromeClient)client;
|
||||
super.setWebChromeClient(client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWebViewClient(CordovaWebViewClient client) {
|
||||
setWebViewClient((WebViewClient) client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWebChromeClient(CordovaChromeClient client) {
|
||||
setWebChromeClient((WebChromeClient) client);
|
||||
}
|
||||
|
||||
public CordovaChromeClient getWebChromeClient() {
|
||||
return this.chromeClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the url into the webview.
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
@Override
|
||||
public void loadUrl(String url) {
|
||||
if (url.equals("about:blank") || url.startsWith("javascript:")) {
|
||||
this.loadUrlNow(url);
|
||||
}
|
||||
else {
|
||||
this.loadUrlIntoView(url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the url into the webview after waiting for period of time.
|
||||
* This is used to display the splashscreen for certain amount of time.
|
||||
*
|
||||
* @param url
|
||||
* @param time The number of ms to wait before loading webview
|
||||
*/
|
||||
@Deprecated
|
||||
public void loadUrl(final String url, int time) {
|
||||
if(url == null)
|
||||
{
|
||||
this.loadUrlIntoView(Config.getStartUrl());
|
||||
}
|
||||
else
|
||||
{
|
||||
this.loadUrlIntoView(url);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadUrlIntoView(final String url) {
|
||||
loadUrlIntoView(url, true);
|
||||
this.loadUrlIntoView(url, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the url into the webview.
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
@Override
|
||||
public void loadUrlIntoView(final String url, boolean recreatePlugins) {
|
||||
if (url.equals("about:blank") || url.startsWith("javascript:")) {
|
||||
this.loadUrlNow(url);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.d(TAG, ">>> loadUrl(" + url + ")");
|
||||
recreatePlugins = recreatePlugins || (loadedUrl == null);
|
||||
|
||||
if (recreatePlugins) {
|
||||
this.loadedUrl = url;
|
||||
@ -367,7 +304,7 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
// Create a timeout timer for loadUrl
|
||||
final AndroidWebView me = this;
|
||||
final int currentLoadUrlTimeout = me.loadUrlTimeout;
|
||||
final int loadUrlTimeoutValue = Integer.parseInt(this.getProperty("LoadUrlTimeoutValue", "20000"));
|
||||
final int loadUrlTimeoutValue = preferences.getInteger("LoadUrlTimeoutValue", 20000);
|
||||
|
||||
// Timeout error method
|
||||
final Runnable loadError = new Runnable() {
|
||||
@ -375,7 +312,7 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
me.stopLoading();
|
||||
LOG.e(TAG, "CordovaWebView: TIMEOUT ERROR!");
|
||||
if (viewClient != null) {
|
||||
viewClient.onReceivedError(-6, "The connection to the server was unsuccessful.", url);
|
||||
viewClient.onReceivedError(AndroidWebView.this, -6, "The connection to the server was unsuccessful.", url);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -409,10 +346,8 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
|
||||
/**
|
||||
* Load URL in webview.
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
public void loadUrlNow(String url) {
|
||||
private void loadUrlNow(String url) {
|
||||
if (LOG.isLoggable(LOG.DEBUG) && !url.startsWith("javascript:")) {
|
||||
LOG.d(TAG, ">>> loadUrlNow()");
|
||||
}
|
||||
@ -421,33 +356,6 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the url into the webview after waiting for period of time.
|
||||
* This is used to display the splashscreen for certain amount of time.
|
||||
*
|
||||
* @param url
|
||||
* @param time The number of ms to wait before loading webview
|
||||
*/
|
||||
public void loadUrlIntoView(final String url, final int time) {
|
||||
|
||||
// If not first page of app, then load immediately
|
||||
// Add support for browser history if we use it.
|
||||
if ((url.startsWith("javascript:")) || this.canGoBack()) {
|
||||
}
|
||||
|
||||
// If first page, then show splashscreen
|
||||
else {
|
||||
|
||||
LOG.d(TAG, "loadUrlIntoView(%s, %d)", url, time);
|
||||
|
||||
// Send message to show splashscreen now if desired
|
||||
this.postMessage("splashscreen", "show");
|
||||
}
|
||||
|
||||
// Load url
|
||||
this.loadUrlIntoView(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLoading() {
|
||||
//viewClient.isCurrentlyLoading = false;
|
||||
@ -459,43 +367,24 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
super.onScrollChanged(l, t, oldl, oldt);
|
||||
//We should post a message that the scroll changed
|
||||
ScrollEvent myEvent = new ScrollEvent(l, t, oldl, oldt, this);
|
||||
this.postMessage("onScrollChanged", myEvent);
|
||||
pluginManager.postMessage("onScrollChanged", myEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send JavaScript statement back to JavaScript.
|
||||
* (This is a convenience method)
|
||||
*
|
||||
* @param statement
|
||||
*/
|
||||
public void sendJavascript(String statement) {
|
||||
this.jsMessageQueue.addJavaScript(statement);
|
||||
bridge.getMessageQueue().addJavaScript(statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a plugin result back to JavaScript.
|
||||
* (This is a convenience method)
|
||||
*
|
||||
* @param result
|
||||
* @param callbackId
|
||||
*/
|
||||
public void sendPluginResult(PluginResult result, String callbackId) {
|
||||
this.jsMessageQueue.addPluginResult(result, callbackId);
|
||||
bridge.getMessageQueue().addPluginResult(result, callbackId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to all plugins.
|
||||
*
|
||||
* @param id The message id
|
||||
* @param data The message data
|
||||
*/
|
||||
public void postMessage(String id, Object data) {
|
||||
if (this.pluginManager != null) {
|
||||
this.pluginManager.postMessage(id, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Go to previous page in history. (We manage our own history)
|
||||
*
|
||||
@ -540,7 +429,7 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
if (url.startsWith("file://") || whitelist.isUrlWhiteListed(url)) {
|
||||
// TODO: What about params?
|
||||
// Load new URL
|
||||
this.loadUrl(url);
|
||||
loadUrlIntoView(url, true);
|
||||
return;
|
||||
}
|
||||
// Load in default viewer if not
|
||||
@ -562,26 +451,6 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string property for activity.
|
||||
*
|
||||
* @param name
|
||||
* @param defaultValue
|
||||
* @return the String value for the named property
|
||||
*/
|
||||
public String getProperty(String name, String defaultValue) {
|
||||
Bundle bundle = this.cordova.getActivity().getIntent().getExtras();
|
||||
if (bundle == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
name = name.toLowerCase(Locale.getDefault());
|
||||
Object p = bundle.get(name);
|
||||
if (p == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return p.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* onKeyDown
|
||||
*/
|
||||
@ -705,13 +574,10 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
// Pause JavaScript timers (including setInterval)
|
||||
this.pauseTimers();
|
||||
}
|
||||
paused = true;
|
||||
|
||||
}
|
||||
|
||||
public void handleResume(boolean keepRunning, boolean activityResultKeepRunning)
|
||||
{
|
||||
|
||||
this.loadUrl("javascript:try{cordova.fireDocumentEvent('resume');}catch(e){console.log('exception firing resume event from native');};");
|
||||
|
||||
// Forward to plugins
|
||||
@ -721,7 +587,6 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
|
||||
// Resume JavaScript timers (including setInterval)
|
||||
this.resumeTimers();
|
||||
paused = false;
|
||||
}
|
||||
|
||||
public void handleDestroy()
|
||||
@ -755,11 +620,6 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPaused()
|
||||
{
|
||||
return paused;
|
||||
}
|
||||
|
||||
// Wrapping these functions in their own class prevents warnings in adb like:
|
||||
// VFY: unable to resolve virtual method 285: Landroid/webkit/WebSettings;.setAllowUniversalAccessFromFileURLs
|
||||
@TargetApi(16)
|
||||
@ -862,57 +722,17 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
return resourceApi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayoutParams(
|
||||
android.widget.LinearLayout.LayoutParams layoutParams) {
|
||||
super.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOverScrollMode(int mode) {
|
||||
super.setOverScrollMode(mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addJavascript(String statement) {
|
||||
this.jsMessageQueue.addJavaScript(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CordovaPlugin getPlugin(String initCallbackClass) {
|
||||
// TODO Auto-generated method stub
|
||||
return this.pluginManager.getPlugin(initCallbackClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOverrideUrlLoading(String url) {
|
||||
return this.pluginManager.onOverrideUrlLoading(url);
|
||||
}
|
||||
|
||||
void onPageReset() {
|
||||
boundKeyCodes.clear();
|
||||
pluginManager.onReset();
|
||||
jsMessageQueue.reset();
|
||||
exposedJsApi.clearBridgeSecret();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incUrlTimeout() {
|
||||
this.loadUrlTimeout++;
|
||||
bridge.reset(loadedUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginManager getPluginManager() {
|
||||
// TODO Auto-generated method stub
|
||||
return this.pluginManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayoutParams(
|
||||
android.widget.FrameLayout.LayoutParams layoutParams) {
|
||||
super.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView() {
|
||||
return this;
|
||||
@ -927,4 +747,17 @@ public class AndroidWebView extends WebView implements CordovaWebView {
|
||||
public CordovaPreferences getPreferences() {
|
||||
return preferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFilePickerResult(Uri uri) {
|
||||
if (null == chromeClient.mUploadMessage)
|
||||
return;
|
||||
chromeClient.mUploadMessage.onReceiveValue(uri);
|
||||
chromeClient.mUploadMessage = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postMessage(String id, Object data) {
|
||||
return pluginManager.postMessage(id, data);
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ import android.webkit.WebViewClient;
|
||||
* @see CordovaChromeClient
|
||||
* @see CordovaWebView
|
||||
*/
|
||||
public class AndroidWebViewClient extends WebViewClient implements CordovaWebViewClient{
|
||||
public class AndroidWebViewClient extends WebViewClient {
|
||||
|
||||
private static final String TAG = "AndroidWebViewClient";
|
||||
protected final CordovaInterface cordova;
|
||||
@ -60,12 +60,6 @@ public class AndroidWebViewClient extends WebViewClient implements CordovaWebVie
|
||||
/** The authorization tokens. */
|
||||
private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param cordova
|
||||
* @param view
|
||||
*/
|
||||
public AndroidWebViewClient(CordovaInterface cordova, AndroidWebView view) {
|
||||
this.cordova = cordova;
|
||||
this.appView = view;
|
||||
@ -82,17 +76,12 @@ public class AndroidWebViewClient extends WebViewClient implements CordovaWebVie
|
||||
*/
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
return helper.shouldOverrideUrlLoading(view, url);
|
||||
return helper.shouldOverrideUrlLoading(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* On received http auth request.
|
||||
* The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination
|
||||
*
|
||||
* @param view
|
||||
* @param handler
|
||||
* @param host
|
||||
* @param realm
|
||||
*/
|
||||
@Override
|
||||
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
|
||||
@ -126,7 +115,7 @@ public class AndroidWebViewClient extends WebViewClient implements CordovaWebVie
|
||||
this.appView.onPageReset();
|
||||
|
||||
// Broadcast message that page has loaded
|
||||
this.appView.postMessage("onPageStarted", url);
|
||||
this.appView.getPluginManager().postMessage("onPageStarted", url);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,10 +148,10 @@ public class AndroidWebViewClient extends WebViewClient implements CordovaWebVie
|
||||
}
|
||||
|
||||
// Clear timeout flag
|
||||
this.appView.incUrlTimeout();
|
||||
appView.loadUrlTimeout++;
|
||||
|
||||
// Broadcast message that page has loaded
|
||||
this.appView.postMessage("onPageFinished", url);
|
||||
this.appView.getPluginManager().postMessage("onPageFinished", url);
|
||||
|
||||
// Make app visible after 2 sec in case there was a JS error and Cordova JS never initialized correctly
|
||||
if (this.appView.getVisibility() == View.INVISIBLE) {
|
||||
@ -172,7 +161,7 @@ public class AndroidWebViewClient extends WebViewClient implements CordovaWebVie
|
||||
Thread.sleep(2000);
|
||||
cordova.getActivity().runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
appView.postMessage("spinner", "stop");
|
||||
appView.getPluginManager().postMessage("spinner", "stop");
|
||||
}
|
||||
});
|
||||
} catch (InterruptedException e) {
|
||||
@ -184,7 +173,7 @@ public class AndroidWebViewClient extends WebViewClient implements CordovaWebVie
|
||||
|
||||
// Shutdown if blank loaded
|
||||
if (url.equals("about:blank")) {
|
||||
appView.postMessage("exit", null);
|
||||
appView.getPluginManager().postMessage("exit", null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,7 +195,7 @@ public class AndroidWebViewClient extends WebViewClient implements CordovaWebVie
|
||||
LOG.d(TAG, "CordovaWebViewClient.onReceivedError: Error code=%s Description=%s URL=%s", errorCode, description, failingUrl);
|
||||
|
||||
// Clear timeout flag
|
||||
this.appView.incUrlTimeout();
|
||||
appView.loadUrlTimeout++;
|
||||
|
||||
// Handle error
|
||||
JSONObject data = new JSONObject();
|
||||
@ -217,7 +206,7 @@ public class AndroidWebViewClient extends WebViewClient implements CordovaWebVie
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.appView.postMessage("onReceivedError", data);
|
||||
this.appView.getPluginManager().postMessage("onReceivedError", data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -326,10 +315,4 @@ public class AndroidWebViewClient extends WebViewClient implements CordovaWebVie
|
||||
public void clearAuthenticationTokens() {
|
||||
this.authenticationTokens.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedError(int errorCode, String description, String url) {
|
||||
this.onReceivedError(appView, errorCode, description, url);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -50,7 +50,6 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
@ -162,11 +161,10 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
}
|
||||
|
||||
appView = makeWebView();
|
||||
appView.init(this, makeWebViewClient(appView), makeChromeClient(appView), pluginEntries, whitelist, preferences);
|
||||
|
||||
// TODO: Have the views set this themselves.
|
||||
if (preferences.getBoolean("DisallowOverscroll", false)) {
|
||||
appView.setOverScrollMode(View.OVER_SCROLL_NEVER);
|
||||
appView.getView().setOverScrollMode(View.OVER_SCROLL_NEVER);
|
||||
}
|
||||
createViews();
|
||||
|
||||
@ -190,7 +188,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void createViews() {
|
||||
// This builds the view. We could probably get away with NOT having a LinearLayout, but I like having a bucket!
|
||||
// This builds the view. We could probably get away with NOT having a LinearLayout, but I like having a bucket!
|
||||
Display display = getWindowManager().getDefaultDisplay();
|
||||
int width = display.getWidth();
|
||||
@ -201,15 +198,15 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, 0.0F));
|
||||
|
||||
appView.setId(100);
|
||||
appView.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
appView.getView().setId(100);
|
||||
appView.getView().setLayoutParams(new LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
1.0F));
|
||||
|
||||
// Add web view but make it invisible while loading URL
|
||||
appView.setVisibility(View.INVISIBLE);
|
||||
root.addView((View) appView);
|
||||
appView.getView().setVisibility(View.INVISIBLE);
|
||||
root.addView(appView.getView());
|
||||
setContentView(root);
|
||||
|
||||
// TODO: Setting this on the appView causes it to show when <html style="opacity:0">.
|
||||
@ -231,63 +228,34 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
* require a more specialized web view.
|
||||
*/
|
||||
protected CordovaWebView makeWebView() {
|
||||
String r = preferences.getString("webView", "org.apache.cordova.AndroidWebView");
|
||||
|
||||
try {
|
||||
Class<?> webViewClass = Class.forName(r);
|
||||
Constructor<?>[] webViewConstructors = webViewClass.getConstructors();
|
||||
|
||||
if(CordovaWebView.class.isAssignableFrom(webViewClass)) {
|
||||
for (Constructor<?> constructor : webViewConstructors) {
|
||||
try {
|
||||
CordovaWebView webView = (CordovaWebView) constructor.newInstance((Context)this);
|
||||
return webView;
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.d(TAG, "Illegal arguments; trying next constructor.");
|
||||
}
|
||||
}
|
||||
String r = preferences.getString("webView", null);
|
||||
CordovaWebView ret = null;
|
||||
if (r != null) {
|
||||
try {
|
||||
Class<?> webViewClass = Class.forName(r);
|
||||
Constructor<?> constructor = webViewClass.getConstructor(Context.class);
|
||||
ret = (CordovaWebView) constructor.newInstance((Context)this);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
LOG.e(TAG, "The WebView Engine is NOT a proper WebView, defaulting to system WebView");
|
||||
} catch (ClassNotFoundException e) {
|
||||
LOG.e(TAG, "The WebView Engine was not found, defaulting to system WebView");
|
||||
} catch (InstantiationException e) {
|
||||
LOG.e(TAG, "Unable to instantiate the WebView, defaulting to system WebView");
|
||||
} catch (IllegalAccessException e) {
|
||||
LOG.e(TAG, "Illegal Access to Constructor. This should never happen, defaulting to system WebView");
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.e(TAG, "The WebView does not implement the default constructor, defaulting to system WebView");
|
||||
} catch (InvocationTargetException e) {
|
||||
LOG.e(TAG, "Invocation Target Exception! Reflection is hard, defaulting to system WebView");
|
||||
}
|
||||
|
||||
// If all else fails, return a default WebView
|
||||
return (CordovaWebView) new AndroidWebView(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the client for the default web view object.
|
||||
*
|
||||
* This is intended to be overridable by subclasses of CordovaActivity which
|
||||
* require a more specialized web view. By default, it allows the webView
|
||||
* to create its own client objects.
|
||||
*
|
||||
* @param webView the default constructed web view object
|
||||
*/
|
||||
protected CordovaWebViewClient makeWebViewClient(CordovaWebView webView) {
|
||||
return webView.makeWebViewClient(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the chrome client for the default web view object.
|
||||
*
|
||||
* This is intended to be overridable by subclasses of CordovaActivity which
|
||||
* require a more specialized web view. By default, it allows the webView
|
||||
* to create its own client objects.
|
||||
*
|
||||
* @param webView the default constructed web view object
|
||||
*/
|
||||
protected CordovaChromeClient makeChromeClient(CordovaWebView webView) {
|
||||
return webView.makeWebChromeClient(this);
|
||||
if (ret == null) {
|
||||
// If all else fails, return a default WebView
|
||||
ret = new AndroidWebView(this);
|
||||
}
|
||||
ret.init(this, pluginEntries, whitelist, preferences);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -309,21 +277,17 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
this.keepRunning = preferences.getBoolean("KeepRunning", true);
|
||||
|
||||
//Check if the view is attached to anything
|
||||
if(appView.getParent() != null)
|
||||
if(appView.getView().getParent() != null)
|
||||
{
|
||||
// Then load the spinner
|
||||
this.loadSpinner();
|
||||
}
|
||||
//Load the correct splashscreen
|
||||
|
||||
if(this.splashscreen != 0)
|
||||
{
|
||||
this.appView.loadUrl(url, this.splashscreenTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.appView.loadUrl(url);
|
||||
appView.getPluginManager().postMessage("splashscreen", "show");
|
||||
}
|
||||
this.appView.loadUrlIntoView(url, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -458,15 +422,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to all plugins.
|
||||
*/
|
||||
public void postMessage(String id, Object data) {
|
||||
if (this.appView != null) {
|
||||
this.appView.postMessage(id, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the spinner. Must be called from the UI thread.
|
||||
*
|
||||
@ -542,21 +497,15 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
Log.d(TAG, "Request code = " + requestCode);
|
||||
if (appView != null && requestCode == AndroidChromeClient.FILECHOOSER_RESULTCODE) {
|
||||
ValueCallback<Uri> mUploadMessage = ((CordovaChromeClient) this.appView.getWebChromeClient()).getValueCallback();
|
||||
Log.d(TAG, "did we get here?");
|
||||
if (null == mUploadMessage)
|
||||
return;
|
||||
Uri result = intent == null || resultCode != Activity.RESULT_OK ? null : intent.getData();
|
||||
Log.d(TAG, "result = " + result);
|
||||
mUploadMessage.onReceiveValue(result);
|
||||
mUploadMessage = null;
|
||||
appView.onFilePickerResult(result);
|
||||
}
|
||||
CordovaPlugin callback = this.activityResultCallback;
|
||||
if(callback == null && initCallbackClass != null) {
|
||||
// The application was restarted, but had defined an initial callback
|
||||
// before being shut down.
|
||||
//this.activityResultCallback = appView.pluginManager.getPlugin(initCallbackClass);
|
||||
this.activityResultCallback = appView.getPlugin(initCallbackClass);
|
||||
this.activityResultCallback = appView.getPluginManager().getPlugin(initCallbackClass);
|
||||
callback = this.activityResultCallback;
|
||||
}
|
||||
if(callback != null) {
|
||||
@ -598,7 +547,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
me.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
if (exit) {
|
||||
me.appView.setVisibility(View.GONE);
|
||||
me.appView.getView().setVisibility(View.GONE);
|
||||
me.displayError("Application Error", description + " (" + failingUrl + ")", "OK", exit);
|
||||
}
|
||||
}
|
||||
@ -636,32 +585,24 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if URL is in approved list of URLs to load.
|
||||
*/
|
||||
@Deprecated // Use whitelist object directly.
|
||||
public boolean isUrlWhiteListed(String url) {
|
||||
return whitelist.isUrlWhiteListed(url);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hook in Cordova for menu plugins
|
||||
*/
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
this.postMessage("onCreateOptionsMenu", menu);
|
||||
appView.getPluginManager().postMessage("onCreateOptionsMenu", menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
this.postMessage("onPrepareOptionsMenu", menu);
|
||||
appView.getPluginManager().postMessage("onPrepareOptionsMenu", menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
this.postMessage("onOptionsItemSelected", item);
|
||||
appView.getPluginManager().postMessage("onOptionsItemSelected", item);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -753,7 +694,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
|
||||
else if ("spinner".equals(id)) {
|
||||
if ("stop".equals(data.toString())) {
|
||||
this.spinnerStop();
|
||||
this.appView.setVisibility(View.VISIBLE);
|
||||
this.appView.getView().setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
else if ("onReceivedError".equals(id)) {
|
||||
|
167
framework/src/org/apache/cordova/CordovaBridge.java
Normal file
167
framework/src/org/apache/cordova/CordovaBridge.java
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import org.apache.cordova.PluginManager;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Contains APIs that the JS can call. All functions in here should also have
|
||||
* an equivalent entry in CordovaChromeClient.java, and be added to
|
||||
* cordova-js/lib/android/plugin/android/promptbasednativeapi.js
|
||||
*/
|
||||
public class CordovaBridge {
|
||||
private static final String LOG_TAG = "CordovaBridge";
|
||||
private PluginManager pluginManager;
|
||||
private NativeToJsMessageQueue jsMessageQueue;
|
||||
private volatile int bridgeSecret = -1; // written by UI thread, read by JS thread.
|
||||
private String loadedUrl;
|
||||
|
||||
public CordovaBridge(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue) {
|
||||
this.pluginManager = pluginManager;
|
||||
this.jsMessageQueue = jsMessageQueue;
|
||||
}
|
||||
|
||||
public String jsExec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException {
|
||||
verifySecret(bridgeSecret);
|
||||
// If the arguments weren't received, send a message back to JS. It will switch bridge modes and try again. See CB-2666.
|
||||
// We send a message meant specifically for this case. It starts with "@" so no other message can be encoded into the same string.
|
||||
if (arguments == null) {
|
||||
return "@Null arguments.";
|
||||
}
|
||||
|
||||
jsMessageQueue.setPaused(true);
|
||||
try {
|
||||
// Tell the resourceApi what thread the JS is running on.
|
||||
CordovaResourceApi.jsThread = Thread.currentThread();
|
||||
|
||||
pluginManager.exec(service, action, callbackId, arguments);
|
||||
String ret = "";
|
||||
if (!NativeToJsMessageQueue.DISABLE_EXEC_CHAINING) {
|
||||
ret = jsMessageQueue.popAndEncode(false);
|
||||
}
|
||||
return ret;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
} finally {
|
||||
jsMessageQueue.setPaused(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void jsSetNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException {
|
||||
verifySecret(bridgeSecret);
|
||||
jsMessageQueue.setBridgeMode(value);
|
||||
}
|
||||
|
||||
public String jsRetrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException {
|
||||
verifySecret(bridgeSecret);
|
||||
return jsMessageQueue.popAndEncode(fromOnlineEvent);
|
||||
}
|
||||
|
||||
private void verifySecret(int value) throws IllegalAccessException {
|
||||
if (bridgeSecret < 0 || value != bridgeSecret) {
|
||||
throw new IllegalAccessException();
|
||||
}
|
||||
}
|
||||
|
||||
/** Called on page transitions */
|
||||
void clearBridgeSecret() {
|
||||
bridgeSecret = -1;
|
||||
}
|
||||
|
||||
/** Called by cordova.js to initialize the bridge. */
|
||||
int generateBridgeSecret() {
|
||||
bridgeSecret = (int)(Math.random() * Integer.MAX_VALUE);
|
||||
return bridgeSecret;
|
||||
}
|
||||
|
||||
public void reset(String loadedUrl) {
|
||||
jsMessageQueue.reset();
|
||||
clearBridgeSecret();
|
||||
this.loadedUrl = loadedUrl;
|
||||
}
|
||||
|
||||
public String promptOnJsPrompt(String origin, String message, String defaultValue) {
|
||||
if (defaultValue != null && defaultValue.length() > 3 && defaultValue.startsWith("gap:")) {
|
||||
JSONArray array;
|
||||
try {
|
||||
array = new JSONArray(defaultValue.substring(4));
|
||||
int bridgeSecret = array.getInt(0);
|
||||
String service = array.getString(1);
|
||||
String action = array.getString(2);
|
||||
String callbackId = array.getString(3);
|
||||
String r = jsExec(bridgeSecret, service, action, callbackId, message);
|
||||
return r == null ? "" : r;
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
// Sets the native->JS bridge mode.
|
||||
else if (defaultValue != null && defaultValue.startsWith("gap_bridge_mode:")) {
|
||||
try {
|
||||
int bridgeSecret = Integer.parseInt(defaultValue.substring(16));
|
||||
jsSetNativeToJsBridgeMode(bridgeSecret, Integer.parseInt(message));
|
||||
} catch (NumberFormatException e){
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
// Polling for JavaScript messages
|
||||
else if (defaultValue != null && defaultValue.startsWith("gap_poll:")) {
|
||||
int bridgeSecret = Integer.parseInt(defaultValue.substring(9));
|
||||
try {
|
||||
String r = jsRetrieveJsMessages(bridgeSecret, "1".equals(message));
|
||||
return r == null ? "" : r;
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
else if (defaultValue != null && defaultValue.startsWith("gap_init:")) {
|
||||
// Protect against random iframes being able to talk through the bridge.
|
||||
// Trust only file URLs and the start URL's domain.
|
||||
// The extra origin.startsWith("http") is to protect against iframes with data: having "" as origin.
|
||||
if (origin.startsWith("file:") || (origin.startsWith("http") && loadedUrl.startsWith(origin))) {
|
||||
// Enable the bridge
|
||||
int bridgeMode = Integer.parseInt(defaultValue.substring(9));
|
||||
jsMessageQueue.setBridgeMode(bridgeMode);
|
||||
// Tell JS the bridge secret.
|
||||
int secret = generateBridgeSecret();
|
||||
return ""+secret;
|
||||
} else {
|
||||
Log.e(LOG_TAG, "gap_init called from restricted origin: " + origin);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public NativeToJsMessageQueue getMessageQueue() {
|
||||
return jsMessageQueue;
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.webkit.ValueCallback;
|
||||
|
||||
public interface CordovaChromeClient {
|
||||
ValueCallback<Uri> getValueCallback();
|
||||
}
|
@ -21,16 +21,15 @@ package org.apache.cordova;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.webkit.WebView;
|
||||
|
||||
class CordovaUriHelper {
|
||||
public class CordovaUriHelper {
|
||||
|
||||
private static final String TAG = "CordovaUriHelper";
|
||||
|
||||
private CordovaWebView appView;
|
||||
private CordovaInterface cordova;
|
||||
|
||||
CordovaUriHelper(CordovaInterface cdv, CordovaWebView webView)
|
||||
public CordovaUriHelper(CordovaInterface cdv, CordovaWebView webView)
|
||||
{
|
||||
appView = webView;
|
||||
cordova = cdv;
|
||||
@ -44,7 +43,7 @@ class CordovaUriHelper {
|
||||
* @param url The url to be loaded.
|
||||
* @return true to override, false for default behavior
|
||||
*/
|
||||
boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
public boolean shouldOverrideUrlLoading(String url) {
|
||||
// The WebView should support http and https when going on the Internet
|
||||
if(url.startsWith("http:") || url.startsWith("https:"))
|
||||
{
|
||||
@ -55,7 +54,7 @@ class CordovaUriHelper {
|
||||
}
|
||||
}
|
||||
// Give plugins the chance to handle the url
|
||||
else if (this.appView.onOverrideUrlLoading(url)) {
|
||||
else if (this.appView.getPluginManager().onOverrideUrlLoading(url)) {
|
||||
|
||||
}
|
||||
else if(url.startsWith("file://") | url.startsWith("data:"))
|
||||
|
@ -5,45 +5,19 @@ import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.view.View;
|
||||
import android.webkit.WebChromeClient.CustomViewCallback;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
|
||||
public interface CordovaWebView {
|
||||
public static final String CORDOVA_VERSION = "4.0.0-dev";
|
||||
|
||||
void init(CordovaInterface cordova, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient,
|
||||
List<PluginEntry> pluginEntries, Whitelist whitelist, CordovaPreferences preferences);
|
||||
void init(CordovaInterface cordova, List<PluginEntry> pluginEntries,
|
||||
Whitelist whitelist, CordovaPreferences preferences);
|
||||
|
||||
View getView();
|
||||
|
||||
CordovaWebViewClient makeWebViewClient(CordovaInterface cordova);
|
||||
|
||||
CordovaChromeClient makeWebChromeClient(CordovaInterface cordova);
|
||||
|
||||
void setWebViewClient(CordovaWebViewClient webViewClient);
|
||||
|
||||
void setWebChromeClient(CordovaChromeClient webChromeClient);
|
||||
|
||||
void setId(int i);
|
||||
|
||||
void setLayoutParams(LayoutParams layoutParams);
|
||||
|
||||
void setVisibility(int invisible);
|
||||
|
||||
Object getParent();
|
||||
|
||||
void loadUrl(String url);
|
||||
|
||||
void loadUrl(String url, int splashscreenTime);
|
||||
|
||||
void loadUrlNow(String url);
|
||||
|
||||
void loadUrlIntoView(final String url);
|
||||
|
||||
void loadUrlIntoView(final String url, boolean recreatePlugins);
|
||||
|
||||
void loadUrlIntoView(final String url, final int splashscreenTime);
|
||||
void loadUrlIntoView(String url, boolean recreatePlugins);
|
||||
|
||||
void stopLoading();
|
||||
|
||||
@ -63,10 +37,6 @@ public interface CordovaWebView {
|
||||
|
||||
void handleDestroy();
|
||||
|
||||
void postMessage(String id, Object data);
|
||||
|
||||
void addJavascript(String statement);
|
||||
|
||||
/**
|
||||
* Send JavaScript statement back to JavaScript.
|
||||
* (This is a convenience method)
|
||||
@ -93,32 +63,14 @@ public interface CordovaWebView {
|
||||
@Deprecated
|
||||
void sendJavascript(String statememt);
|
||||
|
||||
CordovaChromeClient getWebChromeClient();
|
||||
|
||||
CordovaPlugin getPlugin(String initCallbackClass);
|
||||
|
||||
void showWebPage(String errorUrl, boolean b, boolean c, HashMap<String, Object> params);
|
||||
|
||||
Object getFocusedChild();
|
||||
|
||||
boolean isCustomViewShowing();
|
||||
|
||||
void showCustomView(View view, CustomViewCallback callback);
|
||||
|
||||
void hideCustomView();
|
||||
|
||||
Context getContext();
|
||||
|
||||
boolean onOverrideUrlLoading(String url);
|
||||
|
||||
int getVisibility();
|
||||
|
||||
void incUrlTimeout();
|
||||
|
||||
void setOverScrollMode(int overScrollNever);
|
||||
|
||||
void setNetworkAvailable(boolean online);
|
||||
|
||||
CordovaResourceApi getResourceApi();
|
||||
|
||||
void setButtonPlumbedToJs(int keyCode, boolean override);
|
||||
@ -128,12 +80,15 @@ public interface CordovaWebView {
|
||||
|
||||
PluginManager getPluginManager();
|
||||
|
||||
void setLayoutParams(android.widget.FrameLayout.LayoutParams layoutParams);
|
||||
|
||||
// Required for test
|
||||
String getUrl();
|
||||
boolean isPaused();
|
||||
|
||||
Whitelist getWhitelist();
|
||||
CordovaPreferences getPreferences();
|
||||
|
||||
void onFilePickerResult(Uri uri);
|
||||
|
||||
void setNetworkAvailable(boolean online);
|
||||
|
||||
// TODO: Work on deleting these by removing refs from plugins.
|
||||
Context getContext();
|
||||
void loadUrl(String url);
|
||||
Object postMessage(String id, Object data);
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
package org.apache.cordova;
|
||||
|
||||
public interface CordovaWebViewClient {
|
||||
void onReceivedError(int errorCode, String description, String url);
|
||||
}
|
@ -75,7 +75,7 @@ public class CoreAndroid extends CordovaPlugin {
|
||||
// indicative of what this actually does (shows the webview).
|
||||
cordova.getActivity().runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
webView.postMessage("spinner", "stop");
|
||||
webView.getPluginManager().postMessage("spinner", "stop");
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -247,7 +247,7 @@ public class CoreAndroid extends CordovaPlugin {
|
||||
* Exit the Android application.
|
||||
*/
|
||||
public void exitApp() {
|
||||
this.webView.postMessage("exit", null);
|
||||
this.webView.getPluginManager().postMessage("exit", null);
|
||||
}
|
||||
|
||||
|
||||
@ -271,15 +271,15 @@ public class CoreAndroid extends CordovaPlugin {
|
||||
String extraData = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
|
||||
if (extraData.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
|
||||
LOG.i(TAG, "Telephone RINGING");
|
||||
webView.postMessage("telephone", "ringing");
|
||||
webView.getPluginManager().postMessage("telephone", "ringing");
|
||||
}
|
||||
else if (extraData.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
|
||||
LOG.i(TAG, "Telephone OFFHOOK");
|
||||
webView.postMessage("telephone", "offhook");
|
||||
webView.getPluginManager().postMessage("telephone", "offhook");
|
||||
}
|
||||
else if (extraData.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
|
||||
LOG.i(TAG, "Telephone IDLE");
|
||||
webView.postMessage("telephone", "idle");
|
||||
webView.getPluginManager().postMessage("telephone", "idle");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebView;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public class IceCreamCordovaWebViewClient extends AndroidWebViewClient implements CordovaWebViewClient{
|
||||
public class IceCreamCordovaWebViewClient extends AndroidWebViewClient {
|
||||
|
||||
private static final String TAG = "IceCreamCordovaWebViewClient";
|
||||
|
||||
|
@ -294,7 +294,7 @@ public class NativeToJsMessageQueue {
|
||||
public void run() {
|
||||
String js = popAndEncodeAsJs();
|
||||
if (js != null) {
|
||||
webView.loadUrlNow("javascript:" + js);
|
||||
webView.loadUrlIntoView("javascript:" + js, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -53,17 +53,9 @@ public class PluginManager {
|
||||
|
||||
private Set<String> pluginIdWhitelist;
|
||||
|
||||
PluginManager(CordovaWebView cordovaWebView, CordovaInterface cordova, List<PluginEntry> pluginEntries) {
|
||||
public PluginManager(CordovaWebView cordovaWebView, CordovaInterface cordova, List<PluginEntry> pluginEntries) {
|
||||
this.ctx = cordova;
|
||||
this.app = cordovaWebView;
|
||||
setPluginEntries(pluginEntries);
|
||||
}
|
||||
|
||||
public void setPluginEntries(List<PluginEntry> pluginEntries) {
|
||||
this.onPause(false);
|
||||
this.onDestroy();
|
||||
this.clearPluginObjects();
|
||||
entries.clear();
|
||||
for (PluginEntry entry : pluginEntries) {
|
||||
addService(entry);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user