You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ag...@apache.org on 2014/07/07 22:24:58 UTC

[6/9] android commit: Refactor: Use ConfigXmlParser in activity. Adds CordovaWebView.init()

Refactor: Use ConfigXmlParser in activity. Adds CordovaWebView.init()

This does subtly change the API surface due to CordovaWebView.init(),
but only minimally, and is backwards compatibly with the default
generated projects from prior versions.


Project: http://git-wip-us.apache.org/repos/asf/cordova-android/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-android/commit/705991e5
Tree: http://git-wip-us.apache.org/repos/asf/cordova-android/tree/705991e5
Diff: http://git-wip-us.apache.org/repos/asf/cordova-android/diff/705991e5

Branch: refs/heads/4.0.x
Commit: 705991e5b037743e632934b3c6ee98976e18d3f8
Parents: b636874
Author: Andrew Grieve <ag...@chromium.org>
Authored: Fri Jul 4 16:32:09 2014 -0400
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Fri Jul 4 16:32:09 2014 -0400

----------------------------------------------------------------------
 bin/templates/project/Activity.java             |   7 +-
 framework/src/org/apache/cordova/Config.java    |   2 +-
 .../src/org/apache/cordova/CordovaActivity.java | 229 +++++++------------
 .../org/apache/cordova/CordovaChromeClient.java |  18 +-
 .../src/org/apache/cordova/CordovaWebView.java  | 187 +++++----------
 .../apache/cordova/CordovaWebViewClient.java    |   7 +-
 .../src/org/apache/cordova/PluginManager.java   |  55 ++---
 7 files changed, 176 insertions(+), 329 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/705991e5/bin/templates/project/Activity.java
----------------------------------------------------------------------
diff --git a/bin/templates/project/Activity.java b/bin/templates/project/Activity.java
index a515ab0..1bd9e1c 100644
--- a/bin/templates/project/Activity.java
+++ b/bin/templates/project/Activity.java
@@ -22,16 +22,13 @@ package __ID__;
 import android.os.Bundle;
 import org.apache.cordova.*;
 
-public class __ACTIVITY__ extends CordovaActivity 
+public class __ACTIVITY__ extends CordovaActivity
 {
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
-        super.init();
         // Set by <content src="index.html" /> in config.xml
-        super.loadUrl(Config.getStartUrl());
-        //super.loadUrl("file:///android_asset/www/index.html");
+        loadUrl(launchUrl);
     }
 }
-

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/705991e5/framework/src/org/apache/cordova/Config.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/Config.java b/framework/src/org/apache/cordova/Config.java
index 7865e00..dfb039d 100644
--- a/framework/src/org/apache/cordova/Config.java
+++ b/framework/src/org/apache/cordova/Config.java
@@ -25,7 +25,7 @@ import android.util.Log;
 public class Config {
     private static final String TAG = "Config";
 
-    private static ConfigXmlParser parser;
+    static ConfigXmlParser parser;
 
     private Config() {
     }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/705991e5/framework/src/org/apache/cordova/CordovaActivity.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/CordovaActivity.java b/framework/src/org/apache/cordova/CordovaActivity.java
index b1110e1..a3b6314 100755
--- a/framework/src/org/apache/cordova/CordovaActivity.java
+++ b/framework/src/org/apache/cordova/CordovaActivity.java
@@ -18,8 +18,8 @@
 */
 package org.apache.cordova;
 
+import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Locale;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -72,9 +72,8 @@ import android.widget.LinearLayout;
  *       &#64;Override
  *       public void onCreate(Bundle savedInstanceState) {
  *         super.onCreate(savedInstanceState);
- *         super.init();
  *         // Load your application
- *         super.loadUrl(Config.getStartUrl());
+ *         loadUrl(launchUrl);
  *       }
  *     }
  * </pre>
@@ -110,10 +109,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
     protected CordovaPlugin activityResultCallback = null;
     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.
      */
@@ -133,6 +128,12 @@ public class CordovaActivity extends Activity implements CordovaInterface {
 
     private String initCallbackClass;
 
+    // Read from config.xml:
+    protected CordovaPreferences preferences;
+    protected Whitelist whitelist;
+    protected String launchUrl;
+    protected ArrayList<PluginEntry> pluginEntries;
+
     /**
     * Sets the authentication token.
     *
@@ -194,10 +195,8 @@ public class CordovaActivity extends Activity implements CordovaInterface {
     /**
      * Called when the activity is first created.
      */
-    @SuppressWarnings("deprecation")
     @Override
     public void onCreate(Bundle savedInstanceState) {
-        Config.init(this);
         LOG.i(TAG, "Apache Cordova native platform version " + CordovaWebView.CORDOVA_VERSION + " is starting");
         LOG.d(TAG, "CordovaActivity.onCreate()");
         super.onCreate(savedInstanceState);
@@ -207,17 +206,19 @@ public class CordovaActivity extends Activity implements CordovaInterface {
             initCallbackClass = savedInstanceState.getString("callbackClass");
         }
         
-        if(!this.getBooleanProperty("ShowTitle", false))
+        loadConfig();
+
+        if(!preferences.getBoolean("ShowTitle", false))
         {
             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.");
             getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                     WindowManager.LayoutParams.FLAG_FULLSCREEN);
-        } else if (this.getBooleanProperty("Fullscreen", false)) {
+        } else if (preferences.getBoolean("Fullscreen", false)) {
             getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                     WindowManager.LayoutParams.FLAG_FULLSCREEN);
         } else {
@@ -225,6 +226,35 @@ public class CordovaActivity extends Activity implements CordovaInterface {
                     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!
         Display display = getWindowManager().getDefaultDisplay();
         int width = display.getWidth();
@@ -232,12 +262,23 @@ public class CordovaActivity extends Activity implements CordovaInterface {
 
         root = new LinearLayoutSoftKeyboardDetect(this, width, height);
         root.setOrientation(LinearLayout.VERTICAL);
-        root.setBackgroundColor(this.backgroundColor);
         root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT, 0.0F));
 
-        // Setup the hardware volume controls to handle volume control
-        setVolumeControlStream(AudioManager.STREAM_MUSIC);
+        appView.setId(100);
+        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);
     }
 
     /**
@@ -266,11 +307,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
      * @param webView the default constructed web view object
      */
     protected CordovaWebViewClient makeWebViewClient(CordovaWebView webView) {
-        if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
-            return new CordovaWebViewClient(this, webView);
-        } else {
-            return new IceCreamCordovaWebViewClient(this, webView);
-        }
+        return webView.makeWebViewClient(this);
     }
 
     /**
@@ -282,78 +319,46 @@ public class CordovaActivity extends Activity implements CordovaInterface {
      * @param webView the default constructed web view object
      */
     protected CordovaChromeClient makeChromeClient(CordovaWebView webView) {
-        return new CordovaChromeClient(this, webView);
+        return webView.makeChromeClient(this);
     }
 
-    /**
-     * Create and initialize web container with default web view objects.
-     */
+    @Deprecated // No need to call init() anymore.
     public void init() {
-        CordovaWebView webView = makeWebView();
-        this.init(webView, makeWebViewClient(webView), makeChromeClient(webView));
+        this.init(appView, null, null);
     }
 
-    /**
-     * Initialize web container with web view objects.
-     *
-     * @param webView
-     * @param webViewClient
-     * @param webChromeClient
-     */
     @SuppressLint("NewApi")
+    @Deprecated // No need to call init() anymore.
     public void init(CordovaWebView webView, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient) {
         LOG.d(TAG, "CordovaActivity.init()");
 
-        // Set up web container
-        this.appView = webView;
-        this.appView.setId(100);
-
-        this.appView.setWebViewClient(webViewClient);
-        this.appView.setWebChromeClient(webChromeClient);
-        webViewClient.setWebView(this.appView);
-        webChromeClient.setWebView(this.appView);
-
-        this.appView.setLayoutParams(new LinearLayout.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                1.0F));
+        appView = webView;
 
-        if (this.getBooleanProperty("DisallowOverscroll", false)) {
-            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
-                this.appView.setOverScrollMode(CordovaWebView.OVER_SCROLL_NEVER);
-            }
+        if (webViewClient != null) {
+            this.appView.setWebViewClient(webViewClient);
+            webViewClient.setWebView(this.appView);
+        }
+        if (webChromeClient != null) {
+            this.appView.setWebChromeClient(webChromeClient);
+            webChromeClient.setWebView(this.appView);
         }
-
-        // Add web view but make it invisible while loading URL
-        this.appView.setVisibility(View.INVISIBLE);
-        this.root.addView(this.appView);
-        setContentView(this.root);
     }
 
     /**
      * Load the url into the webview.
      */
     public void loadUrl(String url) {
-
-        // Init web view if not already done
-        if (this.appView == null) {
-            this.init();
-        }
-
-        this.splashscreenTime = this.getIntegerProperty("SplashScreenDelay", this.splashscreenTime);
-        if(this.splashscreenTime > 0)
+        this.splashscreenTime = preferences.getInteger("SplashScreenDelay", this.splashscreenTime);
+        String splash = preferences.getString("SplashScreen", null);
+        if(this.splashscreenTime > 0 && splash != null)
         {
-            this.splashscreen = this.getIntegerProperty("SplashScreen", 0);
+            this.splashscreen = getResources().getIdentifier(splash, "drawable", getClass().getPackage().getName());;
             if(this.splashscreen != 0)
             {
                 this.showSplashScreen(this.splashscreenTime);
             }
         }
         
-        // Set backgroundColor
-        this.backgroundColor = this.getIntegerProperty("BackgroundColor", Color.BLACK);
-        this.root.setBackgroundColor(this.backgroundColor);
-
         // If keepRunning
         this.keepRunning = this.getBooleanProperty("KeepRunning", true);
 
@@ -430,9 +435,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
      */
     @Deprecated // Call method on appView directly.
     public void clearCache() {
-        if (this.appView == null) {
-            this.init();
-        }
         this.appView.clearCache(true);
     }
 
@@ -459,103 +461,34 @@ public class CordovaActivity extends Activity implements CordovaInterface {
 
     /**
      * 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) {
-        Bundle bundle = this.getIntent().getExtras();
-        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();
+        return preferences.getBoolean(name, defaultValue);
     }
 
     /**
      * 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) {
-        Bundle bundle = this.getIntent().getExtras();
-        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();
+        return preferences.getInteger(name, defaultValue);
     }
 
     /**
      * 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) {
-        Bundle bundle = this.getIntent().getExtras();
-        if (bundle == null) {
-            return defaultValue;
-        }
-        name = name.toLowerCase(Locale.getDefault());
-        String p = bundle.getString(name);
-        if (p == null) {
-            return defaultValue;
-        }
-        return p;
+        return preferences.getString(name, defaultValue);
     }
 
     /**
      * 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) {
-        Bundle bundle = this.getIntent().getExtras();
-        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();
+        return preferences.getDouble(name, defaultValue);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/705991e5/framework/src/org/apache/cordova/CordovaChromeClient.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/CordovaChromeClient.java b/framework/src/org/apache/cordova/CordovaChromeClient.java
index f2c3350..0337098 100755
--- a/framework/src/org/apache/cordova/CordovaChromeClient.java
+++ b/framework/src/org/apache/cordova/CordovaChromeClient.java
@@ -72,31 +72,17 @@ public class CordovaChromeClient extends WebChromeClient {
     // File Chooser
     public ValueCallback<Uri> mUploadMessage;
     
-    /**
-     * Constructor.
-     *
-     * @param cordova
-     */
+    @Deprecated
     public CordovaChromeClient(CordovaInterface cordova) {
         this.cordova = cordova;
     }
 
-    /**
-     * Constructor.
-     * 
-     * @param ctx
-     * @param app
-     */
     public CordovaChromeClient(CordovaInterface ctx, CordovaWebView app) {
         this.cordova = ctx;
         this.appView = app;
     }
 
-    /**
-     * Constructor.
-     * 
-     * @param view
-     */
+    @Deprecated
     public void setWebView(CordovaWebView view) {
         this.appView = view;
     }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/705991e5/framework/src/org/apache/cordova/CordovaWebView.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/CordovaWebView.java b/framework/src/org/apache/cordova/CordovaWebView.java
index 9401e03..8d0b4a9 100755
--- a/framework/src/org/apache/cordova/CordovaWebView.java
+++ b/framework/src/org/apache/cordova/CordovaWebView.java
@@ -21,9 +21,12 @@ package org.apache.cordova;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 
 import org.apache.cordova.Config;
 import org.apache.cordova.CordovaInterface;
@@ -122,114 +125,51 @@ public class CordovaWebView extends WebView {
             ViewGroup.LayoutParams.MATCH_PARENT,
             Gravity.CENTER);
     
-    /**
-     * Constructor.
-     *
-     * @param context
-     */
     public CordovaWebView(Context context) {
-        super(context);
-        if (CordovaInterface.class.isInstance(context))
-        {
-            this.cordova = (CordovaInterface) context;
-        }
-        else
-        {
-            Log.d(TAG, "Your activity must implement CordovaInterface to work");
-        }
-        this.setup();
+        this(context, null);
     }
 
-    /**
-     * Constructor.
-     *
-     * @param context
-     * @param attrs
-     */
     public CordovaWebView(Context context, AttributeSet 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.setWebChromeClient(new CordovaChromeClient(this.cordova, this));
-        this.initWebViewClient(this.cordova);
-        this.setup();
     }
 
-    /**
-     * Constructor.
-     *
-     * @param context
-     * @param attrs
-     * @param defStyle
-     *
-     */
+    @Deprecated
     public CordovaWebView(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.setWebChromeClient(new CordovaChromeClient(this.cordova, this));
-        this.setup();
     }
 
-    /**
-     * Constructor.
-     *
-     * @param context
-     * @param attrs
-     * @param defStyle
-     * @param privateBrowsing
-     */
     @TargetApi(11)
+    @Deprecated
     public CordovaWebView(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.setWebChromeClient(new CordovaChromeClient(this.cordova));
-        this.initWebViewClient(this.cordova);
-        this.setup();
     }
 
-    /**
-     * set the WebViewClient, but provide special case handling for IceCreamSandwich.
-     */
-    private void initWebViewClient(CordovaInterface cordova) {
-        if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB ||
-                android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.JELLY_BEAN_MR1)
-        {
-            this.setWebViewClient(new CordovaWebViewClient(this.cordova, this));
-        }
-        else
-        {
-            this.setWebViewClient(new IceCreamCordovaWebViewClient(this.cordova, this));
+    // Use two-phase init so that the control will work with XML layouts.
+    public void init(CordovaInterface cordova, CordovaWebViewClient webViewClient, CordovaChromeClient chromeClient, List<PluginEntry> pluginEntries) {
+        if (this.cordova != null) {
+            throw new IllegalStateException();
         }
+        this.cordova = cordova;
+        this.viewClient = webViewClient;
+        this.chromeClient = chromeClient;
+        super.setWebChromeClient(chromeClient);
+        super.setWebViewClient(webViewClient);
+
+        pluginManager = new PluginManager(this, this.cordova, pluginEntries);
+        jsMessageQueue = new NativeToJsMessageQueue(this, cordova);
+        exposedJsApi = new ExposedJsApi(pluginManager, jsMessageQueue);
+        resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
+
+        initWebViewSettings();
+        exposeJsInterface();
     }
 
-    /**
-     * Initialize webview.
-     */
+    @SuppressLint("SetJavaScriptEnabled")
     @SuppressWarnings("deprecation")
-    @SuppressLint("NewApi")
-    private void setup() {
+    private void initWebViewSettings() {
         this.setInitialScale(0);
         this.setVerticalScrollBarEnabled(false);
+        // TODO: The Activity is the one that should call requestFocus().
         if (shouldRequestFocusOnInit()) {
 			this.requestFocusFromTouch();
 		}
@@ -270,31 +210,17 @@ public class CordovaWebView extends WebView {
             Level16Apis.enableUniversalAccess(settings);
         // Enable database
         // 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.setDatabasePath(databasePath);
         
         
         //Determine whether we're in debug or release mode, and turn on Debugging!
-        try {
-            final String packageName = this.cordova.getActivity().getPackageName();
-            final PackageManager pm = this.cordova.getActivity().getPackageManager();
-            ApplicationInfo appInfo;
-            
-            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();
-        }  
+        ApplicationInfo appInfo = getContext().getApplicationContext().getApplicationInfo();
+        if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0 &&
+            android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
+            enableRemoteDebugging();
+        }
         
         settings.setGeolocationDatabasePath(databasePath);
 
@@ -307,13 +233,12 @@ public class CordovaWebView extends WebView {
         // Enable AppCache
         // Fix for CB-2282
         settings.setAppCacheMaxSize(5 * 1048576);
-        String pathToCache = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
-        settings.setAppCachePath(pathToCache);
+        settings.setAppCachePath(databasePath);
         settings.setAppCacheEnabled(true);
         
         // Fix for CB-1405
         // Google issue 4641
-        this.updateUserAgentString();
+        settings.getUserAgentString();
         
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
@@ -321,18 +246,33 @@ public class CordovaWebView extends WebView {
             this.receiver = new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
-                    updateUserAgentString();
+                    getSettings().getUserAgentString();
                 }
             };
-            this.cordova.getActivity().registerReceiver(this.receiver, intentFilter);
+            getContext().registerReceiver(this.receiver, intentFilter);
         }
         // end CB-1405
+    }
 
-        pluginManager = new PluginManager(this, this.cordova);
-        jsMessageQueue = new NativeToJsMessageQueue(this, cordova);
-        exposedJsApi = new ExposedJsApi(pluginManager, jsMessageQueue);
-        resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
-        exposeJsInterface();
+    @TargetApi(Build.VERSION_CODES.KITKAT)
+    private void enableRemoteDebugging() {
+        try {
+            WebView.setWebContentsDebuggingEnabled(true);
+        } catch (IllegalArgumentException e) {
+            Log.d(TAG, "You have one job! To turn on Remote Web Debugging! YOU HAVE FAILED! ");
+            e.printStackTrace();
+        }
+    }
+
+    public CordovaChromeClient makeChromeClient(CordovaInterface cordova) {
+        return new CordovaChromeClient(cordova, this);
+    }
+
+    public CordovaWebViewClient makeWebViewClient(CordovaInterface cordova) {
+        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+            return new CordovaWebViewClient(cordova, this);
+        }
+        return new IceCreamCordovaWebViewClient(cordova, this);
     }
 
 	/**
@@ -345,13 +285,8 @@ public class CordovaWebView extends WebView {
 		return true;
 	}
 
-	private void updateUserAgentString() {
-        this.getSettings().getUserAgentString();
-    }
-
     private void exposeJsInterface() {
-        int SDK_INT = Build.VERSION.SDK_INT;
-        if ((SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)) {
+        if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)) {
             Log.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old.");
             // 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
@@ -363,9 +298,8 @@ public class CordovaWebView extends WebView {
 
     /**
      * Set the WebViewClient.
-     *
-     * @param client
      */
+    @Deprecated // Set this in init() instead.
     public void setWebViewClient(CordovaWebViewClient client) {
         this.viewClient = client;
         super.setWebViewClient(client);
@@ -373,9 +307,8 @@ public class CordovaWebView extends WebView {
 
     /**
      * Set the WebChromeClient.
-     *
-     * @param client
      */
+    @Deprecated // Set this in init() instead.
     public void setWebChromeClient(CordovaChromeClient client) {
         this.chromeClient = client;
         super.setWebChromeClient(client);
@@ -849,7 +782,7 @@ public class CordovaWebView extends WebView {
         // unregister the receiver
         if (this.receiver != null) {
             try {
-                this.cordova.getActivity().unregisterReceiver(this.receiver);
+                getContext().unregisterReceiver(this.receiver);
             } catch (Exception e) {
                 Log.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e);
             }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/705991e5/framework/src/org/apache/cordova/CordovaWebViewClient.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/CordovaWebViewClient.java b/framework/src/org/apache/cordova/CordovaWebViewClient.java
index 9e276d7..65d8ff6 100755
--- a/framework/src/org/apache/cordova/CordovaWebViewClient.java
+++ b/framework/src/org/apache/cordova/CordovaWebViewClient.java
@@ -64,11 +64,7 @@ public class CordovaWebViewClient extends WebViewClient {
     /** The authorization tokens. */
     private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
 
-    /**
-     * Constructor.
-     *
-     * @param cordova
-     */
+    @Deprecated
     public CordovaWebViewClient(CordovaInterface cordova) {
         this.cordova = cordova;
     }
@@ -90,6 +86,7 @@ public class CordovaWebViewClient extends WebViewClient {
      *
      * @param view
      */
+    @Deprecated
     public void setWebView(CordovaWebView view) {
         this.appView = view;
         helper = new CordovaUriHelper(cordova, view);

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/705991e5/framework/src/org/apache/cordova/PluginManager.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/PluginManager.java b/framework/src/org/apache/cordova/PluginManager.java
index 410cc6e..4bd4754 100755
--- a/framework/src/org/apache/cordova/PluginManager.java
+++ b/framework/src/org/apache/cordova/PluginManager.java
@@ -52,11 +52,31 @@ public class PluginManager {
 
     // Stores mapping of Plugin Name -> <url-filter> values.
     // Using <url-filter> is deprecated.
-    protected HashMap<String, List<String>> urlMap;
+    protected HashMap<String, List<String>> urlMap = new HashMap<String, List<String>>();
 
-    public PluginManager(CordovaWebView app, CordovaInterface ctx) {
-        this.ctx = ctx;
-        this.app = app;
+    @Deprecated
+    PluginManager(CordovaWebView cordovaWebView, CordovaInterface cordova) {
+        this(cordovaWebView, cordova, null);
+    }
+
+    PluginManager(CordovaWebView cordovaWebView, CordovaInterface cordova, List<PluginEntry> pluginEntries) {
+        this.ctx = cordova;
+        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);
+        }
     }
 
     /**
@@ -64,33 +84,14 @@ public class PluginManager {
      */
     public void init() {
         LOG.d(TAG, "init()");
-
-        // If first time, then load plugins from config.xml file
-        if (urlMap == null) {
-            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.onPause(false);
+        this.onDestroy();
+        this.clearPluginObjects();
         this.startupPlugins();
     }
 
-    /**
-     * Load plugins from res/xml/config.xml
-     */
+    @Deprecated
     public void loadPlugins() {
-        ConfigXmlParser parser = new ConfigXmlParser();
-        parser.parse(ctx.getActivity());
-        urlMap = new HashMap<String, List<String>>();
-        for (PluginEntry entry : parser.getPluginEntries()) {
-            addService(entry);
-        }
     }
 
     /**