Merge branch 'master' into 4.0.x (ConfigXmlParser + two-phase init)

Conflicts:
	framework/src/org/apache/cordova/CordovaActivity.java
	framework/src/org/apache/cordova/CordovaChromeClient.java
	framework/src/org/apache/cordova/CordovaWebView.java
	framework/src/org/apache/cordova/CordovaWebViewClient.java
	framework/src/org/apache/cordova/PluginManager.java
This commit is contained in:
Andrew Grieve 2014-07-07 16:23:51 -04:00
commit 1571b26a65
13 changed files with 261 additions and 467 deletions

View File

@ -22,16 +22,13 @@ package __ID__;
import android.os.Bundle; import android.os.Bundle;
import org.apache.cordova.*; import org.apache.cordova.*;
public class __ACTIVITY__ extends CordovaActivity public class __ACTIVITY__ extends CordovaActivity
{ {
@Override @Override
public void onCreate(Bundle savedInstanceState) public void onCreate(Bundle savedInstanceState)
{ {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
super.init();
// Set by <content src="index.html" /> in config.xml // Set by <content src="index.html" /> in config.xml
super.loadUrl(Config.getStartUrl()); loadUrl(launchUrl);
//super.loadUrl("file:///android_asset/www/index.html");
} }
} }

View File

@ -38,7 +38,7 @@
android:label="@string/activity_name" android:label="@string/activity_name"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@android:style/Theme.Black.NoTitleBar" android:theme="@android:style/Theme.Black.NoTitleBar"
android:windowSoftInputMode="adjustPan" android:windowSoftInputMode="adjustResize"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"> android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale">
<intent-filter android:label="@string/launcher_name"> <intent-filter android:label="@string/launcher_name">
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

View File

@ -46,8 +46,6 @@ import android.widget.ProgressBar;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.util.Log; import android.util.Log;
/** /**
* This class is the WebChromeClient that implements callbacks for our web view. * This class is the WebChromeClient that implements callbacks for our web view.
* The kind of callbacks that happen here are on the chrome outside the document, * The kind of callbacks that happen here are on the chrome outside the document,
@ -62,10 +60,10 @@ import android.util.Log;
public class AndroidChromeClient extends WebChromeClient implements CordovaChromeClient { public class AndroidChromeClient extends WebChromeClient implements CordovaChromeClient {
public static final int FILECHOOSER_RESULTCODE = 5173; public static final int FILECHOOSER_RESULTCODE = 5173;
private static final String LOG_TAG = "CordovaChromeClient"; private static final String LOG_TAG = "AndroidChromeClient";
private long MAX_QUOTA = 100 * 1024 * 1024; private long MAX_QUOTA = 100 * 1024 * 1024;
protected CordovaInterface cordova; protected final CordovaInterface cordova;
protected AndroidWebView appView; protected final AndroidWebView appView;
// the video progress view // the video progress view
private View mVideoProgressView; private View mVideoProgressView;
@ -73,12 +71,6 @@ public class AndroidChromeClient extends WebChromeClient implements CordovaChrom
// File Chooser // File Chooser
public ValueCallback<Uri> mUploadMessage; public ValueCallback<Uri> mUploadMessage;
/**
* Constructor.
*
* @param ctx
* @param app
*/
public AndroidChromeClient(CordovaInterface ctx, AndroidWebView app) { public AndroidChromeClient(CordovaInterface ctx, AndroidWebView app) {
this.cordova = ctx; this.cordova = ctx;
this.appView = app; this.appView = app;

View File

@ -23,6 +23,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import org.apache.cordova.Config; import org.apache.cordova.Config;
@ -30,7 +31,6 @@ import org.apache.cordova.CordovaInterface;
import org.apache.cordova.LOG; import org.apache.cordova.LOG;
import org.apache.cordova.PluginManager; import org.apache.cordova.PluginManager;
import org.apache.cordova.PluginResult; import org.apache.cordova.PluginResult;
import org.json.JSONException;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.annotation.TargetApi; import android.annotation.TargetApi;
@ -39,8 +39,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
@ -50,7 +48,6 @@ import android.view.Gravity;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.webkit.WebBackForwardList; import android.webkit.WebBackForwardList;
import android.webkit.WebHistoryItem; import android.webkit.WebHistoryItem;
@ -61,6 +58,7 @@ import android.webkit.WebSettings.LayoutAlgorithm;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.widget.FrameLayout; import android.widget.FrameLayout;
/* /*
* This class is our web view. * This class is our web view.
* *
@ -124,133 +122,51 @@ public class AndroidWebView extends WebView implements CordovaWebView {
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
Gravity.CENTER); Gravity.CENTER);
/** Used when created via reflection. */
/**
* Constructor.
*
* @param context
*/
public AndroidWebView(Context context) { public AndroidWebView(Context context) {
super(context); this(context, null);
if (CordovaInterface.class.isInstance(context))
{
this.cordova = (CordovaInterface) context;
}
else
{
Log.d(TAG, "Your activity must implement CordovaInterface to work");
}
this.loadConfiguration();
this.setup();
} }
/** /** Required to allow view to be used within XML layouts. */
* Constructor.
*
* @param context
* @param attrs
*/
public AndroidWebView(Context context, AttributeSet attrs) { public AndroidWebView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
if (CordovaInterface.class.isInstance(context))
{
this.cordova = (CordovaInterface) context;
}
else
{
Log.d(TAG, "Your activity must implement CordovaInterface to work");
}
this.loadConfiguration();
this.setup();
} }
/** // Use two-phase init so that the control will work with XML layouts.
* Constructor.
*
* @param context
* @param attrs
* @param defStyle
*
*/
public AndroidWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if (CordovaInterface.class.isInstance(context))
{
this.cordova = (CordovaInterface) context;
}
else
{
Log.d(TAG, "Your activity must implement CordovaInterface to work");
}
this.loadConfiguration();
this.setup();
}
/**
* Constructor.
*
* @param context
* @param attrs
* @param defStyle
* @param privateBrowsing
*/
@TargetApi(11)
public AndroidWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) {
super(context, attrs, defStyle, privateBrowsing);
if (CordovaInterface.class.isInstance(context))
{
this.cordova = (CordovaInterface) context;
}
else
{
Log.d(TAG, "Your activity must implement CordovaInterface to work");
}
this.loadConfiguration();
this.setup();
}
/**
* Create a default WebViewClient object for this webview. This can be overridden by the
* main application's CordovaActivity subclass.
*
* There are two possible client objects that can be returned:
* AndroidWebViewClient for android < 3.0
* IceCreamCordovaWebViewClient for Android >= 3.0 (Supports shouldInterceptRequest)
*/
@Override @Override
public CordovaWebViewClient makeWebViewClient() { public void init(CordovaInterface cordova, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient, List<PluginEntry> pluginEntries) {
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) if (this.cordova != null) {
{ throw new IllegalStateException();
return (CordovaWebViewClient) new AndroidWebViewClient(this.cordova, this);
}
else
{
return (CordovaWebViewClient) new IceCreamCordovaWebViewClient(this.cordova, this);
} }
this.cordova = cordova;
setWebChromeClient(webChromeClient);
setWebViewClient(webViewClient);
pluginManager = new PluginManager(this, this.cordova, pluginEntries);
jsMessageQueue = new NativeToJsMessageQueue(this, cordova);
exposedJsApi = new AndroidExposedJsApi(pluginManager, jsMessageQueue);
resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
initWebViewSettings();
exposeJsInterface();
} }
/** @SuppressLint("SetJavaScriptEnabled")
* Create a default WebViewClient object for this webview. This can be overridden by the
* main application's CordovaActivity subclass.
*/
@Override
public CordovaChromeClient makeWebChromeClient() {
return (CordovaChromeClient) new AndroidChromeClient(this.cordova, this);
}
/**
* Initialize webview.
*/
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@SuppressLint("NewApi") private void initWebViewSettings() {
private void setup() { this.setInitialScale(0);
this.setVerticalScrollBarEnabled(false);
// TODO: The Activity is the one that should call requestFocus().
if (shouldRequestFocusOnInit()) {
this.requestFocusFromTouch();
}
this.setInitialScale(0); this.setInitialScale(0);
this.setVerticalScrollBarEnabled(false); this.setVerticalScrollBarEnabled(false);
if (shouldRequestFocusOnInit()) { if (shouldRequestFocusOnInit()) {
this.requestFocusFromTouch(); this.requestFocusFromTouch();
} }
// Enable JavaScript // Enable JavaScript
WebSettings settings = this.getSettings(); final WebSettings settings = this.getSettings();
settings.setJavaScriptEnabled(true); settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true); settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL); settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
@ -286,31 +202,17 @@ public class AndroidWebView extends WebView implements CordovaWebView {
Level16Apis.enableUniversalAccess(settings); Level16Apis.enableUniversalAccess(settings);
// Enable database // Enable database
// We keep this disabled because we use or shim to get around DOM_EXCEPTION_ERROR_16 // We keep this disabled because we use or shim to get around DOM_EXCEPTION_ERROR_16
String databasePath = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); String databasePath = getContext().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
settings.setDatabaseEnabled(true); settings.setDatabaseEnabled(true);
settings.setDatabasePath(databasePath); settings.setDatabasePath(databasePath);
//Determine whether we're in debug or release mode, and turn on Debugging! //Determine whether we're in debug or release mode, and turn on Debugging!
try { ApplicationInfo appInfo = getContext().getApplicationContext().getApplicationInfo();
final String packageName = this.cordova.getActivity().getPackageName(); if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0 &&
final PackageManager pm = this.cordova.getActivity().getPackageManager(); android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
ApplicationInfo appInfo; enableRemoteDebugging();
}
appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
if((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0 &&
android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT)
{
setWebContentsDebuggingEnabled(true);
}
} catch (IllegalArgumentException e) {
Log.d(TAG, "You have one job! To turn on Remote Web Debugging! YOU HAVE FAILED! ");
e.printStackTrace();
} catch (NameNotFoundException e) {
Log.d(TAG, "This should never happen: Your application's package can't be found.");
e.printStackTrace();
}
settings.setGeolocationDatabasePath(databasePath); settings.setGeolocationDatabasePath(databasePath);
@ -323,13 +225,12 @@ public class AndroidWebView extends WebView implements CordovaWebView {
// Enable AppCache // Enable AppCache
// Fix for CB-2282 // Fix for CB-2282
settings.setAppCacheMaxSize(5 * 1048576); settings.setAppCacheMaxSize(5 * 1048576);
String pathToCache = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); settings.setAppCachePath(databasePath);
settings.setAppCachePath(pathToCache);
settings.setAppCacheEnabled(true); settings.setAppCacheEnabled(true);
// Fix for CB-1405 // Fix for CB-1405
// Google issue 4641 // Google issue 4641
this.updateUserAgentString(); settings.getUserAgentString();
IntentFilter intentFilter = new IntentFilter(); IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
@ -337,18 +238,35 @@ public class AndroidWebView extends WebView implements CordovaWebView {
this.receiver = new BroadcastReceiver() { this.receiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
updateUserAgentString(); settings.getUserAgentString();
} }
}; };
this.cordova.getActivity().registerReceiver(this.receiver, intentFilter); getContext().registerReceiver(this.receiver, intentFilter);
} }
// end CB-1405 // end CB-1405
}
pluginManager = new PluginManager(this, this.cordova); @TargetApi(Build.VERSION_CODES.KITKAT)
jsMessageQueue = new NativeToJsMessageQueue(this, cordova); private void enableRemoteDebugging() {
exposedJsApi = new AndroidExposedJsApi(pluginManager, jsMessageQueue); try {
resourceApi = new CordovaResourceApi(this.getContext(), pluginManager); WebView.setWebContentsDebuggingEnabled(true);
exposeJsInterface(); } catch (IllegalArgumentException e) {
Log.d(TAG, "You have one job! To turn on Remote Web Debugging! YOU HAVE FAILED! ");
e.printStackTrace();
}
}
@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);
} }
/** /**
@ -361,13 +279,8 @@ public class AndroidWebView extends WebView implements CordovaWebView {
return true; return true;
} }
private void updateUserAgentString() {
this.getSettings().getUserAgentString();
}
private void exposeJsInterface() { private void exposeJsInterface() {
int SDK_INT = Build.VERSION.SDK_INT; if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)) {
if ((SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)) {
Log.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old."); Log.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old.");
// Bug being that Java Strings do not get converted to JS strings automatically. // Bug being that Java Strings do not get converted to JS strings automatically.
// This isn't hard to work-around on the JS side, but it's easier to just // This isn't hard to work-around on the JS side, but it's easier to just
@ -377,21 +290,13 @@ public class AndroidWebView extends WebView implements CordovaWebView {
this.addJavascriptInterface(exposedJsApi, "_cordovaNative"); this.addJavascriptInterface(exposedJsApi, "_cordovaNative");
} }
/** @Override
* Set the WebViewClient.
*
* @param client
*/
public void setWebViewClient(CordovaWebViewClient client) { public void setWebViewClient(CordovaWebViewClient client) {
this.viewClient = client; this.viewClient = client;
super.setWebViewClient((WebViewClient) client); super.setWebViewClient((WebViewClient) client);
} }
/** @Override
* Set the WebChromeClient.
*
* @param client
*/
public void setWebChromeClient(CordovaChromeClient client) { public void setWebChromeClient(CordovaChromeClient client) {
this.chromeClient = client; this.chromeClient = client;
super.setWebChromeClient((WebChromeClient) client); super.setWebChromeClient((WebChromeClient) client);
@ -650,21 +555,6 @@ public class AndroidWebView extends WebView implements CordovaWebView {
} }
} }
/**
* Check configuration parameters from Config.
* Approved list of URLs that can be loaded into Cordova
* <access origin="http://server regexp" subdomains="true" />
* Log level: ERROR, WARN, INFO, DEBUG, VERBOSE (default=ERROR)
* <log level="DEBUG" />
*/
private void loadConfiguration() {
if ("true".equals(this.getProperty("Fullscreen", "false"))) {
this.cordova.getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
this.cordova.getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
/** /**
* Get string property for activity. * Get string property for activity.
* *
@ -843,7 +733,7 @@ public class AndroidWebView extends WebView implements CordovaWebView {
// unregister the receiver // unregister the receiver
if (this.receiver != null) { if (this.receiver != null) {
try { try {
this.cordova.getActivity().unregisterReceiver(this.receiver); getContext().unregisterReceiver(this.receiver);
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e); Log.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e);
} }

View File

@ -18,20 +18,17 @@
*/ */
package org.apache.cordova; package org.apache.cordova;
import java.io.ByteArrayInputStream;
import java.util.Hashtable; import java.util.Hashtable;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.http.SslError; import android.net.http.SslError;
import android.util.Log;
import android.view.View; import android.view.View;
import android.webkit.HttpAuthHandler; import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler; import android.webkit.SslErrorHandler;
@ -54,25 +51,15 @@ import android.webkit.WebViewClient;
public class AndroidWebViewClient extends WebViewClient implements CordovaWebViewClient{ public class AndroidWebViewClient extends WebViewClient implements CordovaWebViewClient{
private static final String TAG = "AndroidWebViewClient"; private static final String TAG = "AndroidWebViewClient";
private static final String CORDOVA_EXEC_URL_PREFIX = "http://cdv_exec/"; protected final CordovaInterface cordova;
CordovaInterface cordova; protected final AndroidWebView appView;
AndroidWebView appView; protected final CordovaUriHelper helper;
CordovaUriHelper helper;
private boolean doClearHistory = false; private boolean doClearHistory = false;
boolean isCurrentlyLoading; boolean isCurrentlyLoading;
/** The authorization tokens. */ /** The authorization tokens. */
private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>(); private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
/**
* Constructor.
*
* @param cordova
*/
public AndroidWebViewClient(CordovaInterface cordova) {
this.cordova = cordova;
}
/** /**
* Constructor. * Constructor.
* *
@ -85,16 +72,6 @@ public class AndroidWebViewClient extends WebViewClient implements CordovaWebVie
helper = new CordovaUriHelper(cordova, view); helper = new CordovaUriHelper(cordova, view);
} }
/**
* Constructor.
*
* @param view
*/
public void setWebView(AndroidWebView view) {
this.appView = view;
helper = new CordovaUriHelper(cordova, view);
}
/** /**
* Give the host application a chance to take over the control when a new url * Give the host application a chance to take over the control when a new url
* is about to be loaded in the current WebView. * is about to be loaded in the current WebView.

View File

@ -25,7 +25,7 @@ import android.util.Log;
public class Config { public class Config {
private static final String TAG = "Config"; private static final String TAG = "Config";
private static ConfigXmlParser parser; static ConfigXmlParser parser;
private Config() { private Config() {
} }

View File

@ -21,8 +21,6 @@ package org.apache.cordova;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -41,7 +39,6 @@ public class ConfigXmlParser {
private CordovaPreferences prefs = new CordovaPreferences(); private CordovaPreferences prefs = new CordovaPreferences();
private Whitelist whitelist = new Whitelist(); private Whitelist whitelist = new Whitelist();
private ArrayList<PluginEntry> pluginEntries = new ArrayList<PluginEntry>(20); private ArrayList<PluginEntry> pluginEntries = new ArrayList<PluginEntry>(20);
private HashMap<String, List<String>> urlMap = new HashMap<String, List<String>>();
public Whitelist getWhitelist() { public Whitelist getWhitelist() {
return whitelist; return whitelist;
@ -59,10 +56,6 @@ public class ConfigXmlParser {
return launchUrl; return launchUrl;
} }
public HashMap<String, List<String>> getPluginUrlMap() {
return urlMap;
}
public void parse(Activity action) { public void parse(Activity action) {
// First checking the class namespace for config.xml // First checking the class namespace for config.xml
int id = action.getResources().getIdentifier("config", "xml", action.getClass().getPackage().getName()); int id = action.getResources().getIdentifier("config", "xml", action.getClass().getPackage().getName());
@ -82,16 +75,17 @@ public class ConfigXmlParser {
String service = "", pluginClass = "", paramType = ""; String service = "", pluginClass = "", paramType = "";
boolean onload = false; boolean onload = false;
boolean insideFeature = false; boolean insideFeature = false;
ArrayList<String> urlMap = null;
while (eventType != XmlResourceParser.END_DOCUMENT) { while (eventType != XmlResourceParser.END_DOCUMENT) {
if (eventType == XmlResourceParser.START_TAG) { if (eventType == XmlResourceParser.START_TAG) {
String strNode = xml.getName(); String strNode = xml.getName();
if (strNode.equals("url-filter")) { if (strNode.equals("url-filter")) {
Log.w(TAG, "Plugin " + service + " is using deprecated tag <url-filter>"); Log.w(TAG, "Plugin " + service + " is using deprecated tag <url-filter>");
if (urlMap.get(service) == null) { if (urlMap == null) {
urlMap.put(service, new ArrayList<String>(2)); urlMap = new ArrayList<String>(2);
} }
List<String> filters = urlMap.get(service); urlMap.add(xml.getAttributeValue(null, "value"));
filters.add(xml.getAttributeValue(null, "value"));
} else if (strNode.equals("feature")) { } else if (strNode.equals("feature")) {
//Check for supported feature sets aka. plugins (Accelerometer, Geolocation, etc) //Check for supported feature sets aka. plugins (Accelerometer, Geolocation, etc)
//Set the bit for reading params //Set the bit for reading params
@ -130,12 +124,13 @@ public class ConfigXmlParser {
{ {
String strNode = xml.getName(); String strNode = xml.getName();
if (strNode.equals("feature")) { if (strNode.equals("feature")) {
pluginEntries.add(new PluginEntry(service, pluginClass, onload)); pluginEntries.add(new PluginEntry(service, pluginClass, onload, urlMap));
service = ""; service = "";
pluginClass = ""; pluginClass = "";
insideFeature = false; insideFeature = false;
onload = false; onload = false;
urlMap = null;
} }
} }
try { try {

View File

@ -20,8 +20,8 @@ package org.apache.cordova;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@ -46,7 +46,6 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.util.Log; import android.util.Log;
import android.view.Display; import android.view.Display;
import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
@ -59,7 +58,7 @@ import android.widget.LinearLayout;
/** /**
* This class is the main Android activity that represents the Cordova * This class is the main Android activity that represents the Cordova
* application. It should be extended by the user to load the specific * application. It should be extended by the user to load the specific
* html file that contains the application. * html file that contains the application.
* *
* As an example: * As an example:
@ -74,9 +73,8 @@ import android.widget.LinearLayout;
* &#64;Override * &#64;Override
* public void onCreate(Bundle savedInstanceState) { * public void onCreate(Bundle savedInstanceState) {
* super.onCreate(savedInstanceState); * super.onCreate(savedInstanceState);
* super.init();
* // Load your application * // Load your application
* super.loadUrl(Config.getStartUrl()); * loadUrl(launchUrl);
* } * }
* } * }
* </pre> * </pre>
@ -93,9 +91,13 @@ public class CordovaActivity extends Activity implements CordovaInterface {
// The webview for our app // The webview for our app
protected CordovaWebView appView; protected CordovaWebView appView;
@Deprecated // unused.
protected CordovaWebViewClient webViewClient; protected CordovaWebViewClient webViewClient;
@Deprecated // Will be removed. Use findViewById() to retrieve views.
protected LinearLayout root; protected LinearLayout root;
protected ProgressDialog spinnerDialog = null; protected ProgressDialog spinnerDialog = null;
private final ExecutorService threadPool = Executors.newCachedThreadPool(); private final ExecutorService threadPool = Executors.newCachedThreadPool();
@ -108,10 +110,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
protected CordovaPlugin activityResultCallback = null; protected CordovaPlugin activityResultCallback = null;
protected boolean activityResultKeepRunning; protected boolean activityResultKeepRunning;
// Default background color for activity
// (this is not the color for the webview, which is set in HTML)
private int backgroundColor = Color.BLACK;
/* /*
* The variables below are used to cache some of the activity properties. * The variables below are used to cache some of the activity properties.
*/ */
@ -131,13 +129,17 @@ public class CordovaActivity extends Activity implements CordovaInterface {
private String initCallbackClass; private String initCallbackClass;
// Read from config.xml:
protected CordovaPreferences preferences;
protected Whitelist whitelist;
protected String launchUrl;
protected ArrayList<PluginEntry> pluginEntries;
/** /**
* Called when the activity is first created. * Called when the activity is first created.
*/ */
@SuppressWarnings("deprecation")
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
Config.init(this);
LOG.i(TAG, "Apache Cordova native platform version " + CordovaWebView.CORDOVA_VERSION + " is starting"); LOG.i(TAG, "Apache Cordova native platform version " + CordovaWebView.CORDOVA_VERSION + " is starting");
LOG.d(TAG, "CordovaActivity.onCreate()"); LOG.d(TAG, "CordovaActivity.onCreate()");
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -147,22 +149,55 @@ public class CordovaActivity extends Activity implements CordovaInterface {
initCallbackClass = savedInstanceState.getString("callbackClass"); initCallbackClass = savedInstanceState.getString("callbackClass");
} }
if(!this.getBooleanProperty("ShowTitle", false)) loadConfig();
if(!preferences.getBoolean("ShowTitle", false))
{ {
getWindow().requestFeature(Window.FEATURE_NO_TITLE); getWindow().requestFeature(Window.FEATURE_NO_TITLE);
} }
if(this.getBooleanProperty("SetFullscreen", false)) if(preferences.getBoolean("SetFullscreen", false))
{ {
Log.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version."); Log.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version.");
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); WindowManager.LayoutParams.FLAG_FULLSCREEN);
} } else if (preferences.getBoolean("Fullscreen", false)) {
else getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
{ WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
} }
appView = makeWebView();
appView.init(this, makeWebViewClient(appView), makeChromeClient(appView), pluginEntries);
// TODO: Have the views set this themselves.
if (preferences.getBoolean("DisallowOverscroll", false)) {
appView.setOverScrollMode(View.OVER_SCROLL_NEVER);
}
createViews();
// TODO: Make this a preference (CB-6153)
// Setup the hardware volume controls to handle volume control
setVolumeControlStream(AudioManager.STREAM_MUSIC);
}
protected void loadConfig() {
ConfigXmlParser parser = new ConfigXmlParser();
parser.parse(this);
preferences = parser.getPreferences();
preferences.setPreferencesBundle(getIntent().getExtras());
preferences.copyIntoIntentExtras(this);
whitelist = parser.getWhitelist();
launchUrl = parser.getLaunchUrl();
pluginEntries = parser.getPluginEntries();
Config.parser = parser;
}
@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! // This builds the view. We could probably get away with NOT having a LinearLayout, but I like having a bucket!
Display display = getWindowManager().getDefaultDisplay(); Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth(); int width = display.getWidth();
@ -170,20 +205,29 @@ public class CordovaActivity extends Activity implements CordovaInterface {
root = new LinearLayoutSoftKeyboardDetect(this, width, height); root = new LinearLayoutSoftKeyboardDetect(this, width, height);
root.setOrientation(LinearLayout.VERTICAL); root.setOrientation(LinearLayout.VERTICAL);
root.setBackgroundColor(this.backgroundColor);
root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT, 0.0F)); ViewGroup.LayoutParams.MATCH_PARENT, 0.0F));
// Setup the hardware volume controls to handle volume control appView.setId(100);
setVolumeControlStream(AudioManager.STREAM_MUSIC); appView.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);
setContentView(root);
// TODO: Setting this on the appView causes it to show when <html style="opacity:0">.
int backgroundColor = preferences.getInteger("BackgroundColor", Color.BLACK);
root.setBackgroundColor(backgroundColor);
} }
/** /**
* Get the Android activity. * Get the Android activity.
*
* @return the Activity
*/ */
public Activity getActivity() { @Override public Activity getActivity() {
return this; return this;
} }
@ -194,16 +238,16 @@ public class CordovaActivity extends Activity implements CordovaInterface {
* require a more specialized web view. * require a more specialized web view.
*/ */
protected CordovaWebView makeWebView() { protected CordovaWebView makeWebView() {
String r = this.getStringProperty("webView", "org.apache.cordova.AndroidWebView"); String r = preferences.getString("webView", "org.apache.cordova.AndroidWebView");
try { try {
Class webViewClass = Class.forName(r); Class<?> webViewClass = Class.forName(r);
Constructor<CordovaWebView> [] webViewConstructors = webViewClass.getConstructors(); Constructor<?>[] webViewConstructors = webViewClass.getConstructors();
if(CordovaWebView.class.isAssignableFrom(webViewClass)) { if(CordovaWebView.class.isAssignableFrom(webViewClass)) {
for (Constructor<CordovaWebView> constructor : webViewConstructors) { for (Constructor<?> constructor : webViewConstructors) {
try { try {
CordovaWebView webView = (CordovaWebView) constructor.newInstance(this); CordovaWebView webView = (CordovaWebView) constructor.newInstance((Context)this);
return webView; return webView;
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
LOG.d(TAG, "Illegal arguments; trying next constructor."); LOG.d(TAG, "Illegal arguments; trying next constructor.");
@ -224,7 +268,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
} }
// If all else fails, return a default WebView // If all else fails, return a default WebView
return (CordovaWebView) new AndroidWebView(CordovaActivity.this); return (CordovaWebView) new AndroidWebView(this);
} }
/** /**
@ -237,7 +281,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
* @param webView the default constructed web view object * @param webView the default constructed web view object
*/ */
protected CordovaWebViewClient makeWebViewClient(CordovaWebView webView) { protected CordovaWebViewClient makeWebViewClient(CordovaWebView webView) {
return webView.makeWebViewClient(); return webView.makeWebViewClient(this);
} }
/** /**
@ -250,77 +294,44 @@ public class CordovaActivity extends Activity implements CordovaInterface {
* @param webView the default constructed web view object * @param webView the default constructed web view object
*/ */
protected CordovaChromeClient makeChromeClient(CordovaWebView webView) { protected CordovaChromeClient makeChromeClient(CordovaWebView webView) {
return webView.makeWebChromeClient(); return webView.makeWebChromeClient(this);
} }
/** @Deprecated // No need to call init() anymore.
* Create and initialize web container with default web view objects.
*/
public void init() { public void init() {
CordovaWebView webView = makeWebView(); this.init(appView, null, null);
this.init(webView, makeWebViewClient(webView), makeChromeClient(webView));
} }
/**
* Initialize web container with web view objects.
*
* @param webView
* @param webViewClient
* @param webChromeClient
*/
@SuppressLint("NewApi") @SuppressLint("NewApi")
@Deprecated // No need to call init() anymore.
public void init(CordovaWebView webView, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient) { public void init(CordovaWebView webView, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient) {
LOG.d(TAG, "CordovaActivity.init()"); LOG.d(TAG, "CordovaActivity.init()");
// Set up web container appView = webView;
this.appView = webView;
this.appView.setId(100);
this.appView.setWebViewClient(webViewClient); if (webViewClient != null) {
this.appView.setWebChromeClient(webChromeClient); this.appView.setWebViewClient(webViewClient);
}
this.appView.setLayoutParams(new LinearLayout.LayoutParams( if (webChromeClient != null) {
ViewGroup.LayoutParams.MATCH_PARENT, this.appView.setWebChromeClient(webChromeClient);
ViewGroup.LayoutParams.MATCH_PARENT,
1.0F));
if (this.getBooleanProperty("DisallowOverscroll", false)) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
//Note: We're using the parent class, because all we know is that this will be a view
this.appView.setOverScrollMode(View.OVER_SCROLL_NEVER);
}
} }
// Add web view but make it invisible while loading URL
this.appView.setVisibility(View.INVISIBLE);
this.root.addView((View) this.appView.getView());
setContentView(this.root);
} }
/** /**
* Load the url into the webview. * Load the url into the webview.
*/ */
public void loadUrl(String url) { public void loadUrl(String url) {
this.splashscreenTime = preferences.getInteger("SplashScreenDelay", this.splashscreenTime);
// Init web view if not already done String splash = preferences.getString("SplashScreen", null);
if (this.appView == null) { if(this.splashscreenTime > 0 && splash != null)
this.init();
}
this.splashscreenTime = this.getIntegerProperty("SplashScreenDelay", this.splashscreenTime);
if(this.splashscreenTime > 0)
{ {
this.splashscreen = this.getIntegerProperty("SplashScreen", 0); this.splashscreen = getResources().getIdentifier(splash, "drawable", getClass().getPackage().getName());;
if(this.splashscreen != 0) if(this.splashscreen != 0)
{ {
this.showSplashScreen(this.splashscreenTime); this.showSplashScreen(this.splashscreenTime);
} }
} }
// Set backgroundColor
this.backgroundColor = this.getIntegerProperty("BackgroundColor", Color.BLACK);
this.root.setBackgroundColor(this.backgroundColor);
// If keepRunning // If keepRunning
this.keepRunning = this.getBooleanProperty("KeepRunning", true); this.keepRunning = this.getBooleanProperty("KeepRunning", true);
@ -391,16 +402,15 @@ public class CordovaActivity extends Activity implements CordovaInterface {
/** /**
* Clear the resource cache. * Clear the resource cache.
*/ */
@Deprecated // Call method on appView directly.
public void clearCache() { public void clearCache() {
if (this.appView == null) {
this.init();
}
this.appView.clearCache(true); this.appView.clearCache(true);
} }
/** /**
* Clear web history in this web view. * Clear web history in this web view.
*/ */
@Deprecated // Call method on appView directly.
public void clearHistory() { public void clearHistory() {
this.appView.clearHistory(); this.appView.clearHistory();
} }
@ -410,6 +420,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
* *
* @return true if we went back, false if we are already at top * @return true if we went back, false if we are already at top
*/ */
@Deprecated // Call method on appView directly.
public boolean backHistory() { public boolean backHistory() {
if (this.appView != null) { if (this.appView != null) {
return appView.backHistory(); return appView.backHistory();
@ -419,103 +430,34 @@ public class CordovaActivity extends Activity implements CordovaInterface {
/** /**
* Get boolean property for activity. * Get boolean property for activity.
*
* @param name
* @param defaultValue
* @return the boolean value of the named property
*/ */
@Deprecated // Call method on preferences directly.
public boolean getBooleanProperty(String name, boolean defaultValue) { public boolean getBooleanProperty(String name, boolean defaultValue) {
Bundle bundle = this.getIntent().getExtras(); return preferences.getBoolean(name, defaultValue);
if (bundle == null) {
return defaultValue;
}
name = name.toLowerCase(Locale.getDefault());
Boolean p;
try {
p = (Boolean) bundle.get(name);
} catch (ClassCastException e) {
String s = bundle.get(name).toString();
if ("true".equals(s)) {
p = true;
}
else {
p = false;
}
}
if (p == null) {
return defaultValue;
}
return p.booleanValue();
} }
/** /**
* Get int property for activity. * Get int property for activity.
*
* @param name
* @param defaultValue
* @return the int value for the named property
*/ */
@Deprecated // Call method on preferences directly.
public int getIntegerProperty(String name, int defaultValue) { public int getIntegerProperty(String name, int defaultValue) {
Bundle bundle = this.getIntent().getExtras(); return preferences.getInteger(name, defaultValue);
if (bundle == null) {
return defaultValue;
}
name = name.toLowerCase(Locale.getDefault());
Integer p;
try {
p = (Integer) bundle.get(name);
} catch (ClassCastException e) {
p = Integer.parseInt(bundle.get(name).toString());
}
if (p == null) {
return defaultValue;
}
return p.intValue();
} }
/** /**
* Get string property for activity. * Get string property for activity.
*
* @param name
* @param defaultValue
* @return the String value for the named property
*/ */
@Deprecated // Call method on preferences directly.
public String getStringProperty(String name, String defaultValue) { public String getStringProperty(String name, String defaultValue) {
Bundle bundle = this.getIntent().getExtras(); return preferences.getString(name, defaultValue);
if (bundle == null) {
return defaultValue;
}
name = name.toLowerCase(Locale.getDefault());
String p = bundle.getString(name);
if (p == null) {
return defaultValue;
}
return p;
} }
/** /**
* Get double property for activity. * Get double property for activity.
*
* @param name
* @param defaultValue
* @return the double value for the named property
*/ */
@Deprecated // Call method on preferences directly.
public double getDoubleProperty(String name, double defaultValue) { public double getDoubleProperty(String name, double defaultValue) {
Bundle bundle = this.getIntent().getExtras(); return preferences.getDouble(name, defaultValue);
if (bundle == null) {
return defaultValue;
}
name = name.toLowerCase(Locale.getDefault());
Double p;
try {
p = (Double) bundle.get(name);
} catch (ClassCastException e) {
p = Double.parseDouble(bundle.get(name).toString());
}
if (p == null) {
return defaultValue;
}
return p.doubleValue();
} }
/** /**
@ -562,8 +504,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
LOG.d(TAG, "Resuming the App"); LOG.d(TAG, "Resuming the App");
//Reload the configuration
Config.init(this);
if (this.activityState == ACTIVITY_STARTING) { if (this.activityState == ACTIVITY_STARTING) {
this.activityState = ACTIVITY_RUNNING; this.activityState = ACTIVITY_RUNNING;
@ -622,6 +562,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
* @param statement * @param statement
* *
*/ */
@Deprecated // Call method on appView directly.
public void sendJavascript(String statement) { public void sendJavascript(String statement) {
if (this.appView != null) { if (this.appView != null) {
this.appView.addJavascript(statement); this.appView.addJavascript(statement);
@ -846,6 +787,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
* @param clearHistory Clear the history stack, so new page becomes top of history * @param clearHistory Clear the history stack, so new page becomes top of history
* @param params Parameters for new app * @param params Parameters for new app
*/ */
@Deprecated // Call method on appView directly.
public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap<String, Object> params) { public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap<String, Object> params) {
if (this.appView != null) { if (this.appView != null) {
appView.showWebPage(url, openExternal, clearHistory, params); appView.showWebPage(url, openExternal, clearHistory, params);

View File

@ -48,7 +48,7 @@ public class CordovaPreferences {
name = name.toLowerCase(Locale.ENGLISH); name = name.toLowerCase(Locale.ENGLISH);
String value = prefs.get(name); String value = prefs.get(name);
if (value != null) { if (value != null) {
return "true".equals(value); return Boolean.parseBoolean(value);
} else if (preferencesBundleExtras != null) { } else if (preferencesBundleExtras != null) {
Object bundleValue = preferencesBundleExtras.get(name); Object bundleValue = preferencesBundleExtras.get(name);
if (bundleValue instanceof String) { if (bundleValue instanceof String) {
@ -64,7 +64,8 @@ public class CordovaPreferences {
name = name.toLowerCase(Locale.ENGLISH); name = name.toLowerCase(Locale.ENGLISH);
String value = prefs.get(name); String value = prefs.get(name);
if (value != null) { if (value != null) {
return Integer.valueOf(value); // Use Integer.decode() can't handle it if the highest bit is set.
return (int)(long)Long.decode(value);
} else if (preferencesBundleExtras != null) { } else if (preferencesBundleExtras != null) {
Object bundleValue = preferencesBundleExtras.get(name); Object bundleValue = preferencesBundleExtras.get(name);
if (bundleValue instanceof String) { if (bundleValue instanceof String) {
@ -123,30 +124,30 @@ public class CordovaPreferences {
action.getIntent().putExtra(name, resource); action.getIntent().putExtra(name, resource);
} }
else if(name.equals("backgroundcolor")) { else if(name.equals("backgroundcolor")) {
int asInt = Integer.valueOf(value); int asInt = (int)(long)Long.decode(value);
action.getIntent().putExtra(name, asInt); action.getIntent().putExtra(name, asInt);
} }
else if(name.equals("loadurltimeoutvalue")) { else if(name.equals("loadurltimeoutvalue")) {
int asInt = Integer.valueOf(value); int asInt = Integer.decode(value);
action.getIntent().putExtra(name, asInt); action.getIntent().putExtra(name, asInt);
} }
else if(name.equals("splashscreendelay")) { else if(name.equals("splashscreendelay")) {
int asInt = Integer.valueOf(value); int asInt = Integer.decode(value);
action.getIntent().putExtra(name, asInt); action.getIntent().putExtra(name, asInt);
} }
else if(name.equals("keeprunning")) else if(name.equals("keeprunning"))
{ {
boolean asBool = "true".equals(value); boolean asBool = Boolean.parseBoolean(value);
action.getIntent().putExtra(name, asBool); action.getIntent().putExtra(name, asBool);
} }
else if(name.equals("inappbrowserstorageenabled")) else if(name.equals("inappbrowserstorageenabled"))
{ {
boolean asBool = "true".equals(value); boolean asBool = Boolean.parseBoolean(value);
action.getIntent().putExtra(name, asBool); action.getIntent().putExtra(name, asBool);
} }
else if(name.equals("disallowoverscroll")) else if(name.equals("disallowoverscroll"))
{ {
boolean asBool = "true".equals(value); boolean asBool = Boolean.parseBoolean(value);
action.getIntent().putExtra(name, asBool); action.getIntent().putExtra(name, asBool);
} }
else else
@ -154,5 +155,9 @@ public class CordovaPreferences {
action.getIntent().putExtra(name, value); action.getIntent().putExtra(name, value);
} }
} }
// In the normal case, the intent extras are null until the first call to putExtra().
if (preferencesBundleExtras == null) {
preferencesBundleExtras = action.getIntent().getExtras();
}
} }
} }

View File

@ -1,12 +1,10 @@
package org.apache.cordova; package org.apache.cordova;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import org.json.JSONException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.webkit.WebChromeClient.CustomViewCallback; import android.webkit.WebChromeClient.CustomViewCallback;
import android.widget.LinearLayout.LayoutParams; import android.widget.LinearLayout.LayoutParams;
@ -14,12 +12,14 @@ import android.widget.LinearLayout.LayoutParams;
public interface CordovaWebView { public interface CordovaWebView {
public static final String CORDOVA_VERSION = "4.0.0-dev"; public static final String CORDOVA_VERSION = "4.0.0-dev";
void init(CordovaInterface cordova, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient, List<PluginEntry> pluginEntries);
View getView(); View getView();
CordovaWebViewClient makeWebViewClient(); CordovaWebViewClient makeWebViewClient(CordovaInterface cordova);
CordovaChromeClient makeWebChromeClient();
CordovaChromeClient makeWebChromeClient(CordovaInterface cordova);
void setWebViewClient(CordovaWebViewClient webViewClient); void setWebViewClient(CordovaWebViewClient webViewClient);
void setWebChromeClient(CordovaChromeClient webChromeClient); void setWebChromeClient(CordovaChromeClient webChromeClient);
@ -132,4 +132,5 @@ public interface CordovaWebView {
// Required for test // Required for test
String getUrl(); String getUrl();
boolean isPaused(); boolean isPaused();
} }

View File

@ -35,12 +35,7 @@ import android.webkit.WebView;
public class IceCreamCordovaWebViewClient extends AndroidWebViewClient implements CordovaWebViewClient{ public class IceCreamCordovaWebViewClient extends AndroidWebViewClient implements CordovaWebViewClient{
private static final String TAG = "IceCreamCordovaWebViewClient"; private static final String TAG = "IceCreamCordovaWebViewClient";
private CordovaUriHelper helper;
public IceCreamCordovaWebViewClient(CordovaInterface cordova) {
super(cordova);
}
public IceCreamCordovaWebViewClient(CordovaInterface cordova, AndroidWebView view) { public IceCreamCordovaWebViewClient(CordovaInterface cordova, AndroidWebView view) {
super(cordova, view); super(cordova, view);
} }

View File

@ -18,12 +18,12 @@
*/ */
package org.apache.cordova; package org.apache.cordova;
import java.util.List;
import org.apache.cordova.CordovaWebView; import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaInterface; import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin; import org.apache.cordova.CordovaPlugin;
//import android.content.Context;
//import android.webkit.WebView;
/** /**
* This class represents a service entry object. * This class represents a service entry object.
@ -52,30 +52,36 @@ public class PluginEntry {
*/ */
public boolean onload = false; public boolean onload = false;
private List<String> urlFilters;
/**
* @param service The name of the service
* @param plugin The plugin associated with this entry
*/
public PluginEntry(String service, CordovaPlugin plugin) {
this(service, plugin.getClass().getName(), true, null);
this.plugin = plugin;
}
/** /**
* Constructor
*
* @param service The name of the service * @param service The name of the service
* @param pluginClass The plugin class name * @param pluginClass The plugin class name
* @param onload Create plugin object when HTML page is loaded * @param onload Create plugin object when HTML page is loaded
*/ */
public PluginEntry(String service, String pluginClass, boolean onload) { public PluginEntry(String service, String pluginClass, boolean onload) {
this(service, pluginClass, onload, null);
}
public PluginEntry(String service, String pluginClass, boolean onload, List<String> urlFilters) {
this.service = service; this.service = service;
this.pluginClass = pluginClass; this.pluginClass = pluginClass;
this.onload = onload; this.onload = onload;
this.urlFilters = urlFilters;
} }
/** public List<String> getUrlFilters() {
* Alternate constructor return urlFilters;
*
* @param service The name of the service
* @param plugin The plugin associated with this entry
*/
public PluginEntry(String service, CordovaPlugin plugin) {
this.service = service;
this.plugin = plugin;
this.pluginClass = plugin.getClass().getName();
this.onload = false;
} }
/** /**
@ -89,8 +95,7 @@ public class PluginEntry {
return this.plugin; return this.plugin;
} }
try { try {
@SuppressWarnings("rawtypes") Class<?> c = getClassByName(this.pluginClass);
Class c = getClassByName(this.pluginClass);
if (isCordovaPlugin(c)) { if (isCordovaPlugin(c)) {
this.plugin = (CordovaPlugin) c.newInstance(); this.plugin = (CordovaPlugin) c.newInstance();
this.plugin.initialize(ctx, webView); this.plugin.initialize(ctx, webView);
@ -110,9 +115,8 @@ public class PluginEntry {
* @return a reference to the named class * @return a reference to the named class
* @throws ClassNotFoundException * @throws ClassNotFoundException
*/ */
@SuppressWarnings("rawtypes") private Class<?> getClassByName(final String clazz) throws ClassNotFoundException {
private Class getClassByName(final String clazz) throws ClassNotFoundException { Class<?> c = null;
Class c = null;
if ((clazz != null) && !("".equals(clazz))) { if ((clazz != null) && !("".equals(clazz))) {
c = Class.forName(clazz); c = Class.forName(clazz);
} }
@ -122,10 +126,9 @@ public class PluginEntry {
/** /**
* Returns whether the given class extends CordovaPlugin. * Returns whether the given class extends CordovaPlugin.
*/ */
@SuppressWarnings("rawtypes") private boolean isCordovaPlugin(Class<?> c) {
private boolean isCordovaPlugin(Class c) {
if (c != null) { if (c != null) {
return org.apache.cordova.CordovaPlugin.class.isAssignableFrom(c); return CordovaPlugin.class.isAssignableFrom(c);
} }
return false; return false;
} }

View File

@ -19,7 +19,6 @@
package org.apache.cordova; package org.apache.cordova;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -54,13 +53,28 @@ public class PluginManager {
// Stores mapping of Plugin Name -> <url-filter> values. // Stores mapping of Plugin Name -> <url-filter> values.
// Using <url-filter> is deprecated. // Using <url-filter> is deprecated.
protected HashMap<String, List<String>> urlMap; protected HashMap<String, List<String>> urlMap = new HashMap<String, List<String>>();
private Set<String> pluginIdWhitelist; private Set<String> pluginIdWhitelist;
public PluginManager(CordovaWebView app, CordovaInterface ctx) { PluginManager(CordovaWebView cordovaWebView, CordovaInterface cordova, List<PluginEntry> pluginEntries) {
this.ctx = ctx; this.ctx = cordova;
this.app = app; this.app = cordovaWebView;
if (pluginEntries == null) {
ConfigXmlParser parser = new ConfigXmlParser();
parser.parse(ctx.getActivity());
pluginEntries = parser.getPluginEntries();
}
setPluginEntries(pluginEntries);
}
public void setPluginEntries(List<PluginEntry> pluginEntries) {
this.onPause(false);
this.onDestroy();
this.clearPluginObjects();
for (PluginEntry entry : pluginEntries) {
addService(entry);
}
} }
public void setPluginIdWhitelist(Set<String> pluginIdWhitelist) { public void setPluginIdWhitelist(Set<String> pluginIdWhitelist) {
@ -72,33 +86,14 @@ public class PluginManager {
*/ */
public void init() { public void init() {
LOG.d(TAG, "init()"); LOG.d(TAG, "init()");
this.onPause(false);
// If first time, then load plugins from config.xml file this.onDestroy();
if (urlMap == null) { this.clearPluginObjects();
this.loadPlugins();
}
// Stop plugins on current HTML page and discard plugin objects
else {
this.onPause(false);
this.onDestroy();
this.clearPluginObjects();
}
// Start up all plugins that have onload specified
this.startupPlugins(); this.startupPlugins();
} }
/** @Deprecated
* Load plugins from res/xml/config.xml
*/
public void loadPlugins() { public void loadPlugins() {
ConfigXmlParser parser = new ConfigXmlParser();
parser.parse(ctx.getActivity());
for (PluginEntry entry : parser.getPluginEntries()) {
addService(entry);
}
urlMap = parser.getPluginUrlMap();
} }
/** /**
@ -219,6 +214,10 @@ public class PluginManager {
*/ */
public void addService(PluginEntry entry) { public void addService(PluginEntry entry) {
this.entries.put(entry.service, entry); this.entries.put(entry.service, entry);
List<String> urlFilters = entry.getUrlFilters();
if (urlFilters != null) {
urlMap.put(entry.service, urlFilters);
}
} }
/** /**
@ -324,11 +323,9 @@ public class PluginManager {
* Called when the app navigates or refreshes. * Called when the app navigates or refreshes.
*/ */
public void onReset() { public void onReset() {
Iterator<PluginEntry> it = this.entries.values().iterator(); for (PluginEntry entry : this.entries.values()) {
while (it.hasNext()) { if (entry.plugin != null) {
CordovaPlugin plugin = it.next().plugin; entry.plugin.onReset();
if (plugin != null) {
plugin.onReset();
} }
} }
} }