You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ia...@apache.org on 2014/04/30 21:52:59 UTC

[01/12] android commit: Removing the deprecated setAttribute methods to clean up the codebase

Repository: cordova-android
Updated Branches:
  refs/heads/pluggable_webview [created] df05f3a3c


Removing the deprecated setAttribute methods to clean up the codebase


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

Branch: refs/heads/pluggable_webview
Commit: 25c8b2fabb3fbc348efd15d5450aa862b68ec182
Parents: e6adbb0
Author: Joe Bowser <bo...@apache.org>
Authored: Tue Mar 4 15:02:30 2014 -0800
Committer: Ian Clelland <ic...@chromium.org>
Committed: Tue Apr 29 22:44:05 2014 -0400

----------------------------------------------------------------------
 .../src/org/apache/cordova/CordovaActivity.java | 60 --------------------
 1 file changed, 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/25c8b2fa/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 9f8b020..7d81825 100755
--- a/framework/src/org/apache/cordova/CordovaActivity.java
+++ b/framework/src/org/apache/cordova/CordovaActivity.java
@@ -605,66 +605,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
         return p.doubleValue();
     }
 
-    /**
-     * Set boolean property on activity.
-     * This method has been deprecated in 3.0 and will be removed at a future
-     * time. Please use config.xml instead.
-     *
-     * @param name
-     * @param value
-     * @deprecated
-     */
-    @Deprecated
-    public void setBooleanProperty(String name, boolean value) {
-        Log.d(TAG, "Setting boolean properties in CordovaActivity will be deprecated in 3.0 on July 2013, please use config.xml");
-        this.getIntent().putExtra(name.toLowerCase(), value);
-    }
-
-    /**
-     * Set int property on activity.
-     * This method has been deprecated in 3.0 and will be removed at a future
-     * time. Please use config.xml instead.
-     *
-     * @param name
-     * @param value
-     * @deprecated
-     */
-    @Deprecated
-    public void setIntegerProperty(String name, int value) {
-        Log.d(TAG, "Setting integer properties in CordovaActivity will be deprecated in 3.0 on July 2013, please use config.xml");
-        this.getIntent().putExtra(name.toLowerCase(), value);
-    }
-
-    /**
-     * Set string property on activity.
-     * This method has been deprecated in 3.0 and will be removed at a future
-     * time. Please use config.xml instead.
-     *
-     * @param name
-     * @param value
-     * @deprecated
-     */
-    @Deprecated
-    public void setStringProperty(String name, String value) {
-        Log.d(TAG, "Setting string properties in CordovaActivity will be deprecated in 3.0 on July 2013, please use config.xml");
-        this.getIntent().putExtra(name.toLowerCase(), value);
-    }
-
-    /**
-     * Set double property on activity.
-     * This method has been deprecated in 3.0 and will be removed at a future
-     * time. Please use config.xml instead.
-     *
-     * @param name
-     * @param value
-     * @deprecated
-     */
-    @Deprecated
-    public void setDoubleProperty(String name, double value) {
-        Log.d(TAG, "Setting double properties in CordovaActivity will be deprecated in 3.0 on July 2013, please use config.xml");
-        this.getIntent().putExtra(name.toLowerCase(), value);
-    }
-
     @Override
     /**
      * Called when the system is about to start resuming a previous activity.


[05/12] Hurray! It runs! Now that we have the default WebView working, it's time to make things a little more pluggable.

Posted by ia...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/19f76d34/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
old mode 100755
new mode 100644
index 54c8948..847a466
--- a/framework/src/org/apache/cordova/CordovaChromeClient.java
+++ b/framework/src/org/apache/cordova/CordovaChromeClient.java
@@ -18,376 +18,15 @@
 */
 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;
-import android.content.DialogInterface;
-import android.content.Intent;
 import android.net.Uri;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.webkit.ConsoleMessage;
-import android.webkit.JsPromptResult;
-import android.webkit.JsResult;
 import android.webkit.ValueCallback;
-import android.webkit.WebChromeClient;
-import android.webkit.WebStorage;
-import android.webkit.WebView;
-import android.webkit.GeolocationPermissions.Callback;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-
-/**
- * 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,
- * such as onCreateWindow(), onConsoleMessage(), onProgressChanged(), etc. Related
- * to but different than CordovaWebViewClient.
- *
- * @see <a href="http://developer.android.com/reference/android/webkit/WebChromeClient.html">WebChromeClient</a>
- * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
- * @see CordovaWebViewClient
- * @see CordovaWebView
- */
-public class CordovaChromeClient extends WebChromeClient {
-
-    public static final int FILECHOOSER_RESULTCODE = 5173;
-    private static final String LOG_TAG = "CordovaChromeClient";
-    private String TAG = "CordovaLog";
-    private long MAX_QUOTA = 100 * 1024 * 1024;
-    protected CordovaInterface cordova;
-    protected CordovaWebView appView;
-
-    // the video progress view
-    private View mVideoProgressView;
-    
-    // File Chooser
-    public ValueCallback<Uri> mUploadMessage;
-    
-    /**
-     * Constructor.
-     *
-     * @param cordova
-     */
-    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
-     */
-    public void setWebView(CordovaWebView view) {
-        this.appView = view;
-    }
-
-    /**
-     * Tell the client to display a javascript alert dialog.
-     *
-     * @param view
-     * @param url
-     * @param message
-     * @param result
-     */
-    @Override
-    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
-        AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
-        dlg.setMessage(message);
-        dlg.setTitle("Alert");
-        //Don't let alerts break the back button
-        dlg.setCancelable(true);
-        dlg.setPositiveButton(android.R.string.ok,
-                new AlertDialog.OnClickListener() {
-                    public void onClick(DialogInterface dialog, int which) {
-                        result.confirm();
-                    }
-                });
-        dlg.setOnCancelListener(
-                new DialogInterface.OnCancelListener() {
-                    public void onCancel(DialogInterface dialog) {
-                        result.cancel();
-                    }
-                });
-        dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
-            //DO NOTHING
-            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
-                if (keyCode == KeyEvent.KEYCODE_BACK)
-                {
-                    result.confirm();
-                    return false;
-                }
-                else
-                    return true;
-            }
-        });
-        dlg.show();
-        return true;
-    }
-
-    /**
-     * Tell the client to display a confirm dialog to the user.
-     *
-     * @param view
-     * @param url
-     * @param message
-     * @param result
-     */
-    @Override
-    public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
-        AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
-        dlg.setMessage(message);
-        dlg.setTitle("Confirm");
-        dlg.setCancelable(true);
-        dlg.setPositiveButton(android.R.string.ok,
-                new DialogInterface.OnClickListener() {
-                    public void onClick(DialogInterface dialog, int which) {
-                        result.confirm();
-                    }
-                });
-        dlg.setNegativeButton(android.R.string.cancel,
-                new DialogInterface.OnClickListener() {
-                    public void onClick(DialogInterface dialog, int which) {
-                        result.cancel();
-                    }
-                });
-        dlg.setOnCancelListener(
-                new DialogInterface.OnCancelListener() {
-                    public void onCancel(DialogInterface dialog) {
-                        result.cancel();
-                    }
-                });
-        dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
-            //DO NOTHING
-            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
-                if (keyCode == KeyEvent.KEYCODE_BACK)
-                {
-                    result.cancel();
-                    return false;
-                }
-                else
-                    return true;
-            }
-        });
-        dlg.show();
-        return true;
-    }
-
-    /**
-     * Tell the client to display a prompt dialog to the user.
-     * If the client returns true, WebView will assume that the client will
-     * handle the prompt dialog and call the appropriate JsPromptResult method.
-     *
-     * Since we are hacking prompts for our own purposes, we should not be using them for
-     * this purpose, perhaps we should hack console.log to do this instead!
-     *
-     * @param view
-     * @param url
-     * @param message
-     * @param defaultValue
-     * @param result
-     */
-    @Override
-    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
-
-        // Security check to make sure any requests are coming from the page initially
-        // loaded in webview and not another loaded in an iframe.
-        boolean reqOk = false;
-        if (url.startsWith("file://") || Config.isUrlWhiteListed(url)) {
-            reqOk = true;
-        }
-
-        // Calling PluginManager.exec() to call a native service using 
-        // prompt(this.stringify(args), "gap:"+this.stringify([service, action, callbackId, true]));
-        if (reqOk && defaultValue != null && defaultValue.length() > 3 && defaultValue.substring(0, 4).equals("gap:")) {
-            JSONArray array;
-            try {
-                array = new JSONArray(defaultValue.substring(4));
-                String service = array.getString(0);
-                String action = array.getString(1);
-                String callbackId = array.getString(2);
-                String r = this.appView.exposedJsApi.exec(service, action, callbackId, message);
-                result.confirm(r == null ? "" : r);
-            } catch (JSONException e) {
-                e.printStackTrace();
-                return false;
-            }
-        }
-
-        // Sets the native->JS bridge mode. 
-        else if (reqOk && defaultValue != null && defaultValue.equals("gap_bridge_mode:")) {
-        	try {
-                this.appView.exposedJsApi.setNativeToJsBridgeMode(Integer.parseInt(message));
-                result.confirm("");
-        	} catch (NumberFormatException e){
-                result.confirm("");
-                e.printStackTrace();
-        	}
-        }
-
-        // Polling for JavaScript messages 
-        else if (reqOk && defaultValue != null && defaultValue.equals("gap_poll:")) {
-            String r = this.appView.exposedJsApi.retrieveJsMessages("1".equals(message));
-            result.confirm(r == null ? "" : r);
-        }
-
-        // Do NO-OP so older code doesn't display dialog
-        else if (defaultValue != null && defaultValue.equals("gap_init:")) {
-            result.confirm("OK");
-        }
-
-        // Show dialog
-        else {
-            final JsPromptResult res = result;
-            AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
-            dlg.setMessage(message);
-            final EditText input = new EditText(this.cordova.getActivity());
-            if (defaultValue != null) {
-                input.setText(defaultValue);
-            }
-            dlg.setView(input);
-            dlg.setCancelable(false);
-            dlg.setPositiveButton(android.R.string.ok,
-                    new DialogInterface.OnClickListener() {
-                        public void onClick(DialogInterface dialog, int which) {
-                            String usertext = input.getText().toString();
-                            res.confirm(usertext);
-                        }
-                    });
-            dlg.setNegativeButton(android.R.string.cancel,
-                    new DialogInterface.OnClickListener() {
-                        public void onClick(DialogInterface dialog, int which) {
-                            res.cancel();
-                        }
-                    });
-            dlg.show();
-        }
-        return true;
-    }
-
-    /**
-     * Handle database quota exceeded notification.
-     */
-    @Override
-    public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
-            long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
-    {
-        LOG.d(TAG, "onExceededDatabaseQuota estimatedSize: %d  currentQuota: %d  totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
-        quotaUpdater.updateQuota(MAX_QUOTA);
-    }
-
-    // console.log in api level 7: http://developer.android.com/guide/developing/debug-tasks.html
-    // Expect this to not compile in a future Android release!
-    @SuppressWarnings("deprecation")
-    @Override
-    public void onConsoleMessage(String message, int lineNumber, String sourceID)
-    {
-        //This is only for Android 2.1
-        if(android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.ECLAIR_MR1)
-        {
-            LOG.d(TAG, "%s: Line %d : %s", sourceID, lineNumber, message);
-            super.onConsoleMessage(message, lineNumber, sourceID);
-        }
-    }
 
-    @TargetApi(8)
-    @Override
-    public boolean onConsoleMessage(ConsoleMessage consoleMessage)
-    {
-        if (consoleMessage.message() != null)
-            LOG.d(TAG, "%s: Line %d : %s" , consoleMessage.sourceId() , consoleMessage.lineNumber(), consoleMessage.message());
-         return super.onConsoleMessage(consoleMessage);
-    }
+public interface CordovaChromeClient {
 
-    @Override
-    /**
-     * Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin.
-     *
-     * @param origin
-     * @param callback
-     */
-    public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
-        super.onGeolocationPermissionsShowPrompt(origin, callback);
-        callback.invoke(origin, true, false);
-    }
-    
-    // API level 7 is required for this, see if we could lower this using something else
-    @Override
-    public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
-        this.appView.showCustomView(view, callback);
-    }
+    int FILECHOOSER_RESULTCODE = 0;
 
-	@Override
-	public void onHideCustomView() {
-    	this.appView.hideCustomView();
-	}
-    
-    @Override
-    /**
-     * Ask the host application for a custom progress view to show while
-     * a <video> is loading.
-     * @return View The progress view.
-     */
-    public View getVideoLoadingProgressView() {
+    void setWebView(CordovaWebView appView);
 
-	    if (mVideoProgressView == null) {	        
-	    	// Create a new Loading view programmatically.
-	    	
-	    	// create the linear layout
-	    	LinearLayout layout = new LinearLayout(this.appView.getContext());
-	        layout.setOrientation(LinearLayout.VERTICAL);
-	        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
-	        layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
-	        layout.setLayoutParams(layoutParams);
-	        // the proress bar
-	        ProgressBar bar = new ProgressBar(this.appView.getContext());
-	        LinearLayout.LayoutParams barLayoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
-	        barLayoutParams.gravity = Gravity.CENTER;
-	        bar.setLayoutParams(barLayoutParams);   
-	        layout.addView(bar);
-	        
-	        mVideoProgressView = layout;
-	    }
-    return mVideoProgressView; 
-    }
-    
-    public void openFileChooser(ValueCallback<Uri> uploadMsg) {
-        this.openFileChooser(uploadMsg, "*/*");
-    }
+    ValueCallback<Uri> getValueCallback();
 
-    public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) {
-        this.openFileChooser(uploadMsg, acceptType, null);
-    }
-    
-    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)
-    {
-        mUploadMessage = uploadMsg;
-        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
-        i.addCategory(Intent.CATEGORY_OPENABLE);
-        i.setType("*/*");
-        this.cordova.getActivity().startActivityForResult(Intent.createChooser(i, "File Browser"),
-                FILECHOOSER_RESULTCODE);
-    }
-    
-    public ValueCallback<Uri> getValueCallback() {
-        return this.mUploadMessage;
-    }
 }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/19f76d34/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
old mode 100755
new mode 100644
index b0e3d43..737ee3a
--- a/framework/src/org/apache/cordova/CordovaWebView.java
+++ b/framework/src/org/apache/cordova/CordovaWebView.java
@@ -1,1007 +1,110 @@
-/*
-       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 java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Locale;
 
-import org.apache.cordova.Config;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.LOG;
-import org.apache.cordova.PluginManager;
-import org.apache.cordova.PluginResult;
+import org.json.JSONException;
 
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
-import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.inputmethod.InputMethodManager;
-import android.webkit.WebBackForwardList;
-import android.webkit.WebHistoryItem;
-import android.webkit.WebChromeClient;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.webkit.WebSettings.LayoutAlgorithm;
-import android.widget.FrameLayout;
+import android.webkit.WebChromeClient.CustomViewCallback;
+import android.widget.LinearLayout.LayoutParams;
 
-/*
- * This class is our web view.
- *
- * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
- * @see <a href="http://developer.android.com/reference/android/webkit/WebView.html">WebView</a>
- */
-public class CordovaWebView extends WebView {
+public interface CordovaWebView {
 
-    public static final String TAG = "CordovaWebView";
-    public static final String CORDOVA_VERSION = "3.5.0-dev";
+    String OVER_SCROLL_NEVER = null;
+    Object pluginManager = null;
+    Object jsMessageQueue = null;
 
-    private ArrayList<Integer> keyDownCodes = new ArrayList<Integer>();
-    private ArrayList<Integer> keyUpCodes = new ArrayList<Integer>();
+    void setWebViewClient(CordovaWebViewClient webViewClient);
 
-    public PluginManager pluginManager;
-    private boolean paused;
+    void setWebChromeClient(CordovaChromeClient webChromeClient);
 
-    private BroadcastReceiver receiver;
+    void setId(int i);
 
+    void setLayoutParams(LayoutParams layoutParams);
 
-    /** Activities and other important classes **/
-    private CordovaInterface cordova;
-    CordovaWebViewClient viewClient;
-    @SuppressWarnings("unused")
-    private CordovaChromeClient chromeClient;
+    void setVisibility(int invisible);
 
-    private String url;
+    Object getParent();
 
-    // Flag to track that a loadUrl timeout occurred
-    int loadUrlTimeout = 0;
+    void loadUrl(String url, int splashscreenTime);
 
-    private boolean bound;
+    void loadUrl(String url);
 
-    private boolean handleButton = false;
-    
-    private long lastMenuEventTime = 0;
+    boolean canGoBack();
 
-    NativeToJsMessageQueue jsMessageQueue;
-    ExposedJsApi exposedJsApi;
+    void clearCache(boolean b);
 
-    /** custom view created by the browser (a video player for example) */
-    private View mCustomView;
-    private WebChromeClient.CustomViewCallback mCustomViewCallback;
+    void clearHistory();
 
-    private ActivityResult mResult = null;
+    boolean backHistory();
 
-    private CordovaResourceApi resourceApi;
+    void handlePause(boolean keepRunning);
 
-    class ActivityResult {
-        
-        int request;
-        int result;
-        Intent incoming;
-        
-        public ActivityResult(int req, int res, Intent intent) {
-            request = req;
-            result = res;
-            incoming = intent;
-        }
+    void onNewIntent(Intent intent);
 
-        
-    }
-    
-    static final FrameLayout.LayoutParams COVER_SCREEN_GRAVITY_CENTER =
-            new FrameLayout.LayoutParams(
-            ViewGroup.LayoutParams.MATCH_PARENT,
-            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.loadConfiguration();
-        this.setup();
-    }
-
-    /**
-     * 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.loadConfiguration();
-        this.setup();
-    }
-
-    /**
-     * Constructor.
-     *
-     * @param context
-     * @param attrs
-     * @param defStyle
-     *
-     */
-    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.loadConfiguration();
-        this.setup();
-    }
-
-    /**
-     * Constructor.
-     *
-     * @param context
-     * @param attrs
-     * @param defStyle
-     * @param privateBrowsing
-     */
-    @TargetApi(11)
-    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.loadConfiguration();
-        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));
-        }
-    }
-
-    /**
-     * Initialize webview.
-     */
-    @SuppressWarnings("deprecation")
-    @SuppressLint("NewApi")
-    private void setup() {
-        this.setInitialScale(0);
-        this.setVerticalScrollBarEnabled(false);
-        if (shouldRequestFocusOnInit()) {
-			this.requestFocusFromTouch();
-		}
-		// Enable JavaScript
-        WebSettings settings = this.getSettings();
-        settings.setJavaScriptEnabled(true);
-        settings.setJavaScriptCanOpenWindowsAutomatically(true);
-        settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
-        
-        // Set the nav dump for HTC 2.x devices (disabling for ICS, deprecated entirely for Jellybean 4.2)
-        try {
-            Method gingerbread_getMethod =  WebSettings.class.getMethod("setNavDump", new Class[] { boolean.class });
-            
-            String manufacturer = android.os.Build.MANUFACTURER;
-            Log.d(TAG, "CordovaWebView is running on device made by: " + manufacturer);
-            if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB &&
-                    android.os.Build.MANUFACTURER.contains("HTC"))
-            {
-                gingerbread_getMethod.invoke(settings, true);
-            }
-        } catch (NoSuchMethodException e) {
-            Log.d(TAG, "We are on a modern version of Android, we will deprecate HTC 2.3 devices in 2.8");
-        } catch (IllegalArgumentException e) {
-            Log.d(TAG, "Doing the NavDump failed with bad arguments");
-        } catch (IllegalAccessException e) {
-            Log.d(TAG, "This should never happen: IllegalAccessException means this isn't Android anymore");
-        } catch (InvocationTargetException e) {
-            Log.d(TAG, "This should never happen: InvocationTargetException means this isn't Android anymore.");
-        }
-
-        //We don't save any form data in the application
-        settings.setSaveFormData(false);
-        settings.setSavePassword(false);
-        
-        // Jellybean rightfully tried to lock this down. Too bad they didn't give us a whitelist
-        // while we do this
-        if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
-            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();
-        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();
-        }  
-        
-        settings.setGeolocationDatabasePath(databasePath);
-
-        // Enable DOM storage
-        settings.setDomStorageEnabled(true);
-
-        // Enable built-in geolocation
-        settings.setGeolocationEnabled(true);
-        
-        // 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.setAppCacheEnabled(true);
-        
-        // Fix for CB-1405
-        // Google issue 4641
-        this.updateUserAgentString();
-        
-        IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
-        if (this.receiver == null) {
-            this.receiver = new BroadcastReceiver() {
-                @Override
-                public void onReceive(Context context, Intent intent) {
-                    updateUserAgentString();
-                }
-            };
-            this.cordova.getActivity().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();
-    }
-
-	/**
-	 * Override this method to decide whether or not you need to request the
-	 * focus when your application start
-	 * 
-	 * @return true unless this method is overriden to return a different value
-	 */
-    protected boolean shouldRequestFocusOnInit() {
-		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)) {
-            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
-            // use the prompt bridge instead.
-            return;            
-        } 
-        this.addJavascriptInterface(exposedJsApi, "_cordovaNative");
-    }
-
-    /**
-     * Set the WebViewClient.
-     *
-     * @param client
-     */
-    public void setWebViewClient(CordovaWebViewClient client) {
-        this.viewClient = client;
-        super.setWebViewClient(client);
-    }
-
-    /**
-     * Set the WebChromeClient.
-     *
-     * @param client
-     */
-    public void setWebChromeClient(CordovaChromeClient client) {
-        this.chromeClient = client;
-        super.setWebChromeClient(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 {
-
-            String initUrl = this.getProperty("url", null);
-
-            // If first page of app, then set URL to load to be the one passed in
-            if (initUrl == null) {
-                this.loadUrlIntoView(url);
-            }
-            // Otherwise use the URL specified in the activity's extras bundle
-            else {
-                this.loadUrlIntoView(initUrl);
-            }
-        }
-    }
-
-    /**
-     * 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 loadUrl(final String url, int time) {
-        String initUrl = this.getProperty("url", null);
-
-        // If first page of app, then set URL to load to be the one passed in
-        if (initUrl == null) {
-            this.loadUrlIntoView(url, time);
-        }
-        // Otherwise use the URL specified in the activity's extras bundle
-        else {
-            this.loadUrlIntoView(initUrl);
-        }
-    }
-
-    public void loadUrlIntoView(final String url) {
-        loadUrlIntoView(url, true);
-    }
-
-    /**
-     * Load the url into the webview.
-     *
-     * @param url
-     */
-    public void loadUrlIntoView(final String url, boolean recreatePlugins) {
-        LOG.d(TAG, ">>> loadUrl(" + url + ")");
-
-        if (recreatePlugins) {
-            this.url = url;
-            this.pluginManager.init();
-        }
-
-        // Create a timeout timer for loadUrl
-        final CordovaWebView me = this;
-        final int currentLoadUrlTimeout = me.loadUrlTimeout;
-        final int loadUrlTimeoutValue = Integer.parseInt(this.getProperty("LoadUrlTimeoutValue", "20000"));
-
-        // Timeout error method
-        final Runnable loadError = new Runnable() {
-            public void run() {
-                me.stopLoading();
-                LOG.e(TAG, "CordovaWebView: TIMEOUT ERROR!");
-                if (viewClient != null) {
-                    viewClient.onReceivedError(me, -6, "The connection to the server was unsuccessful.", url);
-                }
-            }
-        };
-
-        // Timeout timer method
-        final Runnable timeoutCheck = new Runnable() {
-            public void run() {
-                try {
-                    synchronized (this) {
-                        wait(loadUrlTimeoutValue);
-                    }
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
-                }
-
-                // If timeout, then stop loading and handle error
-                if (me.loadUrlTimeout == currentLoadUrlTimeout) {
-                    me.cordova.getActivity().runOnUiThread(loadError);
-                }
-            }
-        };
-
-        // Load url
-        this.cordova.getActivity().runOnUiThread(new Runnable() {
-            public void run() {
-                cordova.getThreadPool().execute(timeoutCheck);
-                me.loadUrlNow(url);
-            }
-        });
-    }
-
-    /**
-     * Load URL in webview.
-     *
-     * @param url
-     */
-    void loadUrlNow(String url) {
-        if (LOG.isLoggable(LOG.DEBUG) && !url.startsWith("javascript:")) {
-            LOG.d(TAG, ">>> loadUrlNow()");
-        }
-        if (url.startsWith("file://") || url.startsWith("javascript:") || Config.isUrlWhiteListed(url)) {
-            super.loadUrl(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
-     */
-    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;
-        super.stopLoading();
-    }
-    
-    public void onScrollChanged(int l, int t, int oldl, int oldt)
-    {
-        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);
-    }
-    
-    /**
-     * Send JavaScript statement back to JavaScript.
-     * (This is a convenience method)
-     *
-     * @param statement
-     */
-    public void sendJavascript(String statement) {
-        this.jsMessageQueue.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);
-    }
-
-    /**
-     * 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)
-     *
-     * @return true if we went back, false if we are already at top
-     */
-    public boolean backHistory() {
-
-        // Check webview first to see if there is a history
-        // This is needed to support curPage#diffLink, since they are added to appView's history, but not our history url array (JQMobile behavior)
-        if (super.canGoBack()) {
-            printBackForwardList();
-            super.goBack();
-            
-            return true;
-        }
-        return false;
-    }
-
-
-    /**
-     * Load the specified URL in the Cordova webview or a new browser instance.
-     *
-     * NOTE: If openExternal is false, only URLs listed in whitelist can be loaded.
-     *
-     * @param url           The url to load.
-     * @param openExternal  Load url in browser instead of Cordova webview.
-     * @param clearHistory  Clear the history stack, so new page becomes top of history
-     * @param params        Parameters for new app
-     */
-    public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap<String, Object> params) {
-        LOG.d(TAG, "showWebPage(%s, %b, %b, HashMap", url, openExternal, clearHistory);
-
-        // If clearing history
-        if (clearHistory) {
-            this.clearHistory();
-        }
-
-        // If loading into our webview
-        if (!openExternal) {
-
-            // Make sure url is in whitelist
-            if (url.startsWith("file://") || Config.isUrlWhiteListed(url)) {
-                // TODO: What about params?
-                // Load new URL
-                this.loadUrl(url);
-                return;
-            }
-            // Load in default viewer if not
-            LOG.w(TAG, "showWebPage: Cannot load URL into webview since it is not in white list.  Loading into browser instead. (URL=" + url + ")");
-        }
-        try {
-            // Omitting the MIME type for file: URLs causes "No Activity found to handle Intent".
-            // Adding the MIME type to http: URLs causes them to not be handled by the downloader.
-            Intent intent = new Intent(Intent.ACTION_VIEW);
-            Uri uri = Uri.parse(url);
-            if ("file".equals(uri.getScheme())) {
-                intent.setDataAndType(uri, resourceApi.getMimeType(uri));
-            } else {
-                intent.setData(uri);
-            }
-            cordova.getActivity().startActivity(intent);
-        } catch (android.content.ActivityNotFoundException e) {
-            LOG.e(TAG, "Error loading url " + url, e);
-        }
-    }
-
-    /**
-     * 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.
-     *
-     * @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
-     */
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event)
-    {
-        if(keyDownCodes.contains(keyCode))
-        {
-            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
-                    // only override default behavior is event bound
-                    LOG.d(TAG, "Down Key Hit");
-                    this.loadUrl("javascript:cordova.fireDocumentEvent('volumedownbutton');");
-                    return true;
-            }
-            // If volumeup key
-            else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
-                    LOG.d(TAG, "Up Key Hit");
-                    this.loadUrl("javascript:cordova.fireDocumentEvent('volumeupbutton');");
-                    return true;
-            }
-            else
-            {
-                return super.onKeyDown(keyCode, event);
-            }
-        }
-        else if(keyCode == KeyEvent.KEYCODE_BACK)
-        {
-            return !(this.startOfHistory()) || this.bound;
-        }
-        else if(keyCode == KeyEvent.KEYCODE_MENU)
-        {
-            //How did we get here?  Is there a childView?
-            View childView = this.getFocusedChild();
-            if(childView != null)
-            {
-                //Make sure we close the keyboard if it's present
-                InputMethodManager imm = (InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
-                imm.hideSoftInputFromWindow(childView.getWindowToken(), 0);
-                cordova.getActivity().openOptionsMenu();
-                return true;
-            } else {
-                return super.onKeyDown(keyCode, event);
-            }
-        }
-        
-        return super.onKeyDown(keyCode, event);
-    }
-    
+    void handleResume(boolean keepRunning, boolean activityResultKeepRunning);
 
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event)
-    {
-        // If back key
-        if (keyCode == KeyEvent.KEYCODE_BACK) {
-            // A custom view is currently displayed  (e.g. playing a video)
-            if(mCustomView != null) {
-                this.hideCustomView();
-            } else {
-                // The webview is currently displayed
-                // If back key is bound, then send event to JavaScript
-                if (this.bound) {
-                    this.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');");
-                    return true;
-                } else {
-                    // If not bound
-                    // Go to previous page in webview if it is possible to go back
-                    if (this.backHistory()) {
-                        return true;
-                    }
-                    // If not, then invoke default behavior
-                    else {
-                        //this.activityState = ACTIVITY_EXITING;
-                    	//return false;
-                    	// If they hit back button when app is initializing, app should exit instead of hang until initialization (CB2-458)
-                    	this.cordova.getActivity().finish();
-                    }
-                }
-            }
-        }
-        // Legacy
-        else if (keyCode == KeyEvent.KEYCODE_MENU) {
-            if (this.lastMenuEventTime < event.getEventTime()) {
-                this.loadUrl("javascript:cordova.fireDocumentEvent('menubutton');");
-            }
-            this.lastMenuEventTime = event.getEventTime();
-            return super.onKeyUp(keyCode, event);
-        }
-        // If search key
-        else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
-            this.loadUrl("javascript:cordova.fireDocumentEvent('searchbutton');");
-            return true;
-        }
-        else if(keyUpCodes.contains(keyCode))
-        {
-            //What the hell should this do?
-            return super.onKeyUp(keyCode, event);
-        }
-
-        //Does webkit change this behavior?
-        return super.onKeyUp(keyCode, event);
-    }
+    void handleDestroy();
 
+    void postMessage(String id, Object data);
+
+    void addJavascript(String statement);
     
-    public void bindButton(boolean override)
-    {
-        this.bound = override;
-    }
-
-    public void bindButton(String button, boolean override) {
-        // TODO Auto-generated method stub
-        if (button.compareTo("volumeup")==0) {
-          keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_UP);
-        }
-        else if (button.compareTo("volumedown")==0) {
-          keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_DOWN);
-        }
-      }
-
-    public void bindButton(int keyCode, boolean keyDown, boolean override) {
-       if(keyDown)
-       {
-           keyDownCodes.add(keyCode);
-       }
-       else
-       {
-           keyUpCodes.add(keyCode);
-       }
-    }
-
-    public boolean isBackButtonBound()
-    {
-        return this.bound;
-    }
-    
-    public void handlePause(boolean keepRunning)
-    {
-        LOG.d(TAG, "Handle the pause");
-        // Send pause event to JavaScript
-        this.loadUrl("javascript:try{cordova.fireDocumentEvent('pause');}catch(e){console.log('exception firing pause event from native');};");
-
-        // Forward to plugins
-        if (this.pluginManager != null) {
-            this.pluginManager.onPause(keepRunning);
-        }
-
-        // If app doesn't want to run in background
-        if (!keepRunning) {
-            // 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
-        if (this.pluginManager != null) {
-            this.pluginManager.onResume(keepRunning);
-        }
-
-        // Resume JavaScript timers (including setInterval)
-        this.resumeTimers();
-        paused = false;
-    }
-    
-    public void handleDestroy()
-    {
-        // Send destroy event to JavaScript
-        this.loadUrl("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};");
-
-        // Load blank page so that JavaScript onunload is called
-        this.loadUrl("about:blank");
-
-        // Forward to plugins
-        if (this.pluginManager != null) {
-            this.pluginManager.onDestroy();
-        }
-        
-        // unregister the receiver
-        if (this.receiver != null) {
-            try {
-                this.cordova.getActivity().unregisterReceiver(this.receiver);
-            } catch (Exception e) {
-                Log.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e);
-            }
-        }
-    }
-    
-    public void onNewIntent(Intent intent)
-    {
-        //Forward to plugins
-        if (this.pluginManager != null) {
-            this.pluginManager.onNewIntent(intent);
-        }
-    }
-    
-    public boolean isPaused()
-    {
-        return paused;
-    }
-
-    public boolean hadKeyEvent() {
-        return handleButton;
-    }
-
-    // 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)
-    private static class Level16Apis {
-        static void enableUniversalAccess(WebSettings settings) {
-            settings.setAllowUniversalAccessFromFileURLs(true);
-        }
-    }
-    
-    public void printBackForwardList() {
-        WebBackForwardList currentList = this.copyBackForwardList();
-        int currentSize = currentList.getSize();
-        for(int i = 0; i < currentSize; ++i)
-        {
-            WebHistoryItem item = currentList.getItemAtIndex(i);
-            String url = item.getUrl();
-            LOG.d(TAG, "The URL at index: " + Integer.toString(i) + " is " + url );
-        }
-    }
-    
-    
-    //Can Go Back is BROKEN!
-    public boolean startOfHistory()
-    {
-        WebBackForwardList currentList = this.copyBackForwardList();
-        WebHistoryItem item = currentList.getItemAtIndex(0);
-        if( item!=null){	// Null-fence in case they haven't called loadUrl yet (CB-2458)
-	        String url = item.getUrl();
-	        String currentUrl = this.getUrl();
-	        LOG.d(TAG, "The current URL is: " + currentUrl);
-	        LOG.d(TAG, "The URL at item 0 is: " + url);
-	        return currentUrl.equals(url);
-        }
-        return false;
-    }
-
-    public void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
-        // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
-        Log.d(TAG, "showing Custom View");
-        // if a view already exists then immediately terminate the new one
-        if (mCustomView != null) {
-            callback.onCustomViewHidden();
-            return;
-        }
-        
-        // Store the view and its callback for later (to kill it properly)
-        mCustomView = view;
-        mCustomViewCallback = callback;
-        
-        // Add the custom view to its container.
-        ViewGroup parent = (ViewGroup) this.getParent();
-        parent.addView(view, COVER_SCREEN_GRAVITY_CENTER);
-        
-        // Hide the content view.
-        this.setVisibility(View.GONE);
-        
-        // Finally show the custom view container.
-        parent.setVisibility(View.VISIBLE);
-        parent.bringToFront();
-    }
-
-    public void hideCustomView() {
-        // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
-        Log.d(TAG, "Hiding Custom View");
-        if (mCustomView == null) return;
-
-        // Hide the custom view.
-        mCustomView.setVisibility(View.GONE);
-        
-        // Remove the custom view from its container.
-        ViewGroup parent = (ViewGroup) this.getParent();
-        parent.removeView(mCustomView);
-        mCustomView = null;
-        mCustomViewCallback.onCustomViewHidden();
-        
-        // Show the content view.
-        this.setVisibility(View.VISIBLE);
-    }
-    
-    /**
-     * if the video overlay is showing then we need to know 
-     * as it effects back button handling
-     * 
-     * @return true if custom view is showing
-     */
-    public boolean isCustomViewShowing() {
-        return mCustomView != null;
-    }
-    
-    public WebBackForwardList restoreState(Bundle savedInstanceState)
-    {
-        WebBackForwardList myList = super.restoreState(savedInstanceState);
-        Log.d(TAG, "WebView restoration crew now restoring!");
-        //Initialize the plugin manager once more
-        this.pluginManager.init();
-        return myList;
-    }
-
-    public void storeResult(int requestCode, int resultCode, Intent intent) {
-        mResult = new ActivityResult(requestCode, resultCode, intent);
-    }
-    
-    public CordovaResourceApi getResourceApi() {
-        return resourceApi;
-    }
+    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();
+
+    boolean onKeyUp(int keyCode, KeyEvent event);
+
+    boolean onKeyDown(int keyCode, KeyEvent event);
+
+    String exec(String service, String action, String callbackId, String message) throws JSONException;
+
+    void setNativeToJsBridgeMode(int parseInt);
+
+    String retrieveJsMessages(boolean equals);
+
+    void showCustomView(View view, CustomViewCallback callback);
+
+    void hideCustomView();
+
+    Context getContext();
+
+    boolean onOverrideUrlLoading(String url);
+
+    void resetJsMessageQueue();
+
+    void onReset();
+
+    int getVisibility();
+
+    void incUrlTimeout();
+
+    void setOverScrollMode(int overScrollNever);
+
+    void loadUrlNow(String string);
+
+    void setNetworkAvailable(boolean online);
+
+    CordovaResourceApi getResourceApi();
+
+    void bindButton(boolean override);
+    void bindButton(String button, boolean override);
+
+    boolean isBackButtonBound();
+
+    void sendPluginResult(PluginResult cr, String callbackId);
+
+    PluginManager getPluginManager();
 }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/19f76d34/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
old mode 100755
new mode 100644
index 407c1fb..e914af1
--- a/framework/src/org/apache/cordova/CordovaWebViewClient.java
+++ b/framework/src/org/apache/cordova/CordovaWebViewClient.java
@@ -1,483 +1,9 @@
-/*
-       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 java.io.ByteArrayInputStream;
-import java.util.Hashtable;
-
-import org.apache.cordova.CordovaInterface;
-
-import org.apache.cordova.LOG;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.annotation.TargetApi;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.net.http.SslError;
-import android.util.Log;
-import android.view.View;
-import android.webkit.HttpAuthHandler;
-import android.webkit.SslErrorHandler;
-import android.webkit.WebResourceResponse;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-
-/**
- * This class is the WebViewClient that implements callbacks for our web view.
- * The kind of callbacks that happen here are regarding the rendering of the
- * document instead of the chrome surrounding it, such as onPageStarted(), 
- * shouldOverrideUrlLoading(), etc. Related to but different than
- * CordovaChromeClient.
- *
- * @see <a href="http://developer.android.com/reference/android/webkit/WebViewClient.html">WebViewClient</a>
- * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
- * @see CordovaChromeClient
- * @see CordovaWebView
- */
-public class CordovaWebViewClient extends WebViewClient {
-
-	private static final String TAG = "CordovaWebViewClient";
-	private static final String CORDOVA_EXEC_URL_PREFIX = "http://cdv_exec/";
-    CordovaInterface cordova;
-    CordovaWebView appView;
-    private boolean doClearHistory = false;
-    boolean isCurrentlyLoading;
-
-    /** The authorization tokens. */
-    private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
-
-    /**
-     * Constructor.
-     *
-     * @param cordova
-     */
-    public CordovaWebViewClient(CordovaInterface cordova) {
-        this.cordova = cordova;
-    }
-
-    /**
-     * Constructor.
-     *
-     * @param cordova
-     * @param view
-     */
-    public CordovaWebViewClient(CordovaInterface cordova, CordovaWebView view) {
-        this.cordova = cordova;
-        this.appView = view;
-    }
-
-    /**
-     * Constructor.
-     *
-     * @param view
-     */
-    public void setWebView(CordovaWebView view) {
-        this.appView = view;
-    }
-
-
-    // Parses commands sent by setting the webView's URL to:
-    // cdvbrg:service/action/callbackId#jsonArgs
-	private void handleExecUrl(String url) {
-		int idx1 = CORDOVA_EXEC_URL_PREFIX.length();
-		int idx2 = url.indexOf('#', idx1 + 1);
-		int idx3 = url.indexOf('#', idx2 + 1);
-		int idx4 = url.indexOf('#', idx3 + 1);
-		if (idx1 == -1 || idx2 == -1 || idx3 == -1 || idx4 == -1) {
-			Log.e(TAG, "Could not decode URL command: " + url);
-			return;
-		}
-		String service    = url.substring(idx1, idx2);
-		String action     = url.substring(idx2 + 1, idx3);
-		String callbackId = url.substring(idx3 + 1, idx4);
-		String jsonArgs   = url.substring(idx4 + 1);
-        appView.pluginManager.exec(service, action, callbackId, jsonArgs);
-	}
-
-    /**
-     * Give the host application a chance to take over the control when a new url
-     * is about to be loaded in the current WebView.
-     *
-     * @param view          The WebView that is initiating the callback.
-     * @param url           The url to be loaded.
-     * @return              true to override, false for default behavior
-     */
-	@Override
-    public boolean shouldOverrideUrlLoading(WebView view, String url) {
-    	// Check if it's an exec() bridge command message.
-    	if (NativeToJsMessageQueue.ENABLE_LOCATION_CHANGE_EXEC_MODE && url.startsWith(CORDOVA_EXEC_URL_PREFIX)) {
-    		handleExecUrl(url);
-    	}
-
-        // Give plugins the chance to handle the url
-    	else if ((this.appView.pluginManager != null) && this.appView.pluginManager.onOverrideUrlLoading(url)) {
-        }
-
-        // If dialing phone (tel:5551212)
-        else if (url.startsWith(WebView.SCHEME_TEL)) {
-            try {
-                Intent intent = new Intent(Intent.ACTION_DIAL);
-                intent.setData(Uri.parse(url));
-                this.cordova.getActivity().startActivity(intent);
-            } catch (android.content.ActivityNotFoundException e) {
-                LOG.e(TAG, "Error dialing " + url + ": " + e.toString());
-            }
-        }
-
-        // If displaying map (geo:0,0?q=address)
-        else if (url.startsWith("geo:")) {
-            try {
-                Intent intent = new Intent(Intent.ACTION_VIEW);
-                intent.setData(Uri.parse(url));
-                this.cordova.getActivity().startActivity(intent);
-            } catch (android.content.ActivityNotFoundException e) {
-                LOG.e(TAG, "Error showing map " + url + ": " + e.toString());
-            }
-        }
-
-        // If sending email (mailto:abc@corp.com)
-        else if (url.startsWith(WebView.SCHEME_MAILTO)) {
-            try {
-                Intent intent = new Intent(Intent.ACTION_VIEW);
-                intent.setData(Uri.parse(url));
-                this.cordova.getActivity().startActivity(intent);
-            } catch (android.content.ActivityNotFoundException e) {
-                LOG.e(TAG, "Error sending email " + url + ": " + e.toString());
-            }
-        }
-
-        // If sms:5551212?body=This is the message
-        else if (url.startsWith("sms:")) {
-            try {
-                Intent intent = new Intent(Intent.ACTION_VIEW);
-
-                // Get address
-                String address = null;
-                int parmIndex = url.indexOf('?');
-                if (parmIndex == -1) {
-                    address = url.substring(4);
-                }
-                else {
-                    address = url.substring(4, parmIndex);
-
-                    // If body, then set sms body
-                    Uri uri = Uri.parse(url);
-                    String query = uri.getQuery();
-                    if (query != null) {
-                        if (query.startsWith("body=")) {
-                            intent.putExtra("sms_body", query.substring(5));
-                        }
-                    }
-                }
-                intent.setData(Uri.parse("sms:" + address));
-                intent.putExtra("address", address);
-                intent.setType("vnd.android-dir/mms-sms");
-                this.cordova.getActivity().startActivity(intent);
-            } catch (android.content.ActivityNotFoundException e) {
-                LOG.e(TAG, "Error sending sms " + url + ":" + e.toString());
-            }
-        }
-        
-        //Android Market
-        else if(url.startsWith("market:")) {
-            try {
-                Intent intent = new Intent(Intent.ACTION_VIEW);
-                intent.setData(Uri.parse(url));
-                this.cordova.getActivity().startActivity(intent);
-            } catch (android.content.ActivityNotFoundException e) {
-                LOG.e(TAG, "Error loading Google Play Store: " + url, e);
-            }
-        }
-
-        // All else
-        else {
-
-            // If our app or file:, then load into a new Cordova webview container by starting a new instance of our activity.
-            // Our app continues to run.  When BACK is pressed, our app is redisplayed.
-            if (url.startsWith("file://") || url.startsWith("data:")  || Config.isUrlWhiteListed(url)) {
-                return false;
-            }
-
-            // If not our application, let default viewer handle
-            else {
-                try {
-                    Intent intent = new Intent(Intent.ACTION_VIEW);
-                    intent.setData(Uri.parse(url));
-                    this.cordova.getActivity().startActivity(intent);
-                } catch (android.content.ActivityNotFoundException e) {
-                    LOG.e(TAG, "Error loading url " + url, e);
-                }
-            }
-        }
-        return true;
-    }
-    
-    /**
-     * 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) {
-
-        // Get the authentication token
-        AuthenticationToken token = this.getAuthenticationToken(host, realm);
-        if (token != null) {
-            handler.proceed(token.getUserName(), token.getPassword());
-        }
-        else {
-            // Handle 401 like we'd normally do!
-            super.onReceivedHttpAuthRequest(view, handler, host, realm);
-        }
-    }
-
-    /**
-     * Notify the host application that a page has started loading.
-     * This method is called once for each main frame load so a page with iframes or framesets will call onPageStarted
-     * one time for the main frame. This also means that onPageStarted will not be called when the contents of an
-     * embedded frame changes, i.e. clicking a link whose target is an iframe.
-     *
-     * @param view          The webview initiating the callback.
-     * @param url           The url of the page.
-     */
-    @Override
-    public void onPageStarted(WebView view, String url, Bitmap favicon) {
-        super.onPageStarted(view, url, favicon);
-        isCurrentlyLoading = true;
-        LOG.d(TAG, "onPageStarted(" + url + ")");
-        // Flush stale messages.
-        this.appView.jsMessageQueue.reset();
-
-        // Broadcast message that page has loaded
-        this.appView.postMessage("onPageStarted", url);
-
-        // Notify all plugins of the navigation, so they can clean up if necessary.
-        if (this.appView.pluginManager != null) {
-            this.appView.pluginManager.onReset();
-        }
-    }
-
-    /**
-     * Notify the host application that a page has finished loading.
-     * This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet.
-     *
-     *
-     * @param view          The webview initiating the callback.
-     * @param url           The url of the page.
-     */
-    @Override
-    public void onPageFinished(WebView view, String url) {
-        super.onPageFinished(view, url);
-        // Ignore excessive calls.
-        if (!isCurrentlyLoading) {
-            return;
-        }
-        isCurrentlyLoading = false;
-        LOG.d(TAG, "onPageFinished(" + url + ")");
-
-        /**
-         * Because of a timing issue we need to clear this history in onPageFinished as well as
-         * onPageStarted. However we only want to do this if the doClearHistory boolean is set to
-         * true. You see when you load a url with a # in it which is common in jQuery applications
-         * onPageStared is not called. Clearing the history at that point would break jQuery apps.
-         */
-        if (this.doClearHistory) {
-            view.clearHistory();
-            this.doClearHistory = false;
-        }
-
-        // Clear timeout flag
-        this.appView.loadUrlTimeout++;
-
-        // Broadcast message that page has loaded
-        this.appView.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) {
-            Thread t = new Thread(new Runnable() {
-                public void run() {
-                    try {
-                        Thread.sleep(2000);
-                        cordova.getActivity().runOnUiThread(new Runnable() {
-                            public void run() {
-                                appView.postMessage("spinner", "stop");
-                            }
-                        });
-                    } catch (InterruptedException e) {
-                    }
-                }
-            });
-            t.start();
-        }
-
-        // Shutdown if blank loaded
-        if (url.equals("about:blank")) {
-            appView.postMessage("exit", null);
-        }
-    }
-
-    /**
-     * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
-     * The errorCode parameter corresponds to one of the ERROR_* constants.
-     *
-     * @param view          The WebView that is initiating the callback.
-     * @param errorCode     The error code corresponding to an ERROR_* value.
-     * @param description   A String describing the error.
-     * @param failingUrl    The url that failed to load.
-     */
-    @Override
-    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
-        // Ignore error due to stopLoading().
-        if (!isCurrentlyLoading) {
-            return;
-        }
-        LOG.d(TAG, "CordovaWebViewClient.onReceivedError: Error code=%s Description=%s URL=%s", errorCode, description, failingUrl);
-
-        // Clear timeout flag
-        this.appView.loadUrlTimeout++;
-
-        // Handle error
-        JSONObject data = new JSONObject();
-        try {
-            data.put("errorCode", errorCode);
-            data.put("description", description);
-            data.put("url", failingUrl);
-        } catch (JSONException e) {
-            e.printStackTrace();
-        }
-        this.appView.postMessage("onReceivedError", data);
-    }
-
-    /**
-     * Notify the host application that an SSL error occurred while loading a resource.
-     * The host application must call either handler.cancel() or handler.proceed().
-     * Note that the decision may be retained for use in response to future SSL errors.
-     * The default behavior is to cancel the load.
-     *
-     * @param view          The WebView that is initiating the callback.
-     * @param handler       An SslErrorHandler object that will handle the user's response.
-     * @param error         The SSL error object.
-     */
-    @TargetApi(8)
-    @Override
-    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
-
-        final String packageName = this.cordova.getActivity().getPackageName();
-        final PackageManager pm = this.cordova.getActivity().getPackageManager();
-
-        ApplicationInfo appInfo;
-        try {
-            appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
-            if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
-                // debug = true
-                handler.proceed();
-                return;
-            } else {
-                // debug = false
-                super.onReceivedSslError(view, handler, error);
-            }
-        } catch (NameNotFoundException e) {
-            // When it doubt, lock it out!
-            super.onReceivedSslError(view, handler, error);
-        }
-    }
-
-
-    /**
-     * Sets the authentication token.
-     *
-     * @param authenticationToken
-     * @param host
-     * @param realm
-     */
-    public void setAuthenticationToken(AuthenticationToken authenticationToken, String host, String realm) {
-        if (host == null) {
-            host = "";
-        }
-        if (realm == null) {
-            realm = "";
-        }
-        this.authenticationTokens.put(host.concat(realm), authenticationToken);
-    }
-
-    /**
-     * Removes the authentication token.
-     *
-     * @param host
-     * @param realm
-     *
-     * @return the authentication token or null if did not exist
-     */
-    public AuthenticationToken removeAuthenticationToken(String host, String realm) {
-        return this.authenticationTokens.remove(host.concat(realm));
-    }
-
-    /**
-     * Gets the authentication token.
-     *
-     * In order it tries:
-     * 1- host + realm
-     * 2- host
-     * 3- realm
-     * 4- no host, no realm
-     *
-     * @param host
-     * @param realm
-     *
-     * @return the authentication token
-     */
-    public AuthenticationToken getAuthenticationToken(String host, String realm) {
-        AuthenticationToken token = null;
-        token = this.authenticationTokens.get(host.concat(realm));
-
-        if (token == null) {
-            // try with just the host
-            token = this.authenticationTokens.get(host);
-
-            // Try the realm
-            if (token == null) {
-                token = this.authenticationTokens.get(realm);
-            }
-
-            // if no host found, just query for default
-            if (token == null) {
-                token = this.authenticationTokens.get("");
-            }
-        }
+public interface CordovaWebViewClient {
 
-        return token;
-    }
+    void setWebView(CordovaWebView appView);
 
-    /**
-     * Clear all authentication tokens.
-     */
-    public void clearAuthenticationTokens() {
-        this.authenticationTokens.clear();
-    }
+    void onReceivedError(CordovaWebView me, int i, String string, String url);
 
 }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/19f76d34/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java b/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
index 63cfb91..dbdd85e 100644
--- a/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
+++ b/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
@@ -32,7 +32,7 @@ import android.webkit.WebResourceResponse;
 import android.webkit.WebView;
 
 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
-public class IceCreamCordovaWebViewClient extends CordovaWebViewClient {
+public class IceCreamCordovaWebViewClient extends AndroidWebViewClient implements CordovaWebViewClient{
 
     private static final String TAG = "IceCreamCordovaWebViewClient";
 
@@ -97,4 +97,10 @@ public class IceCreamCordovaWebViewClient extends CordovaWebViewClient {
         }
         return false;
     }
+
+    @Override
+    public void onReceivedError(CordovaWebView me, int i, String string,
+            String url) {
+        super.onReceivedError(me, i, string, url);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/19f76d34/framework/src/org/apache/cordova/LinearLayoutSoftKeyboardDetect.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/LinearLayoutSoftKeyboardDetect.java b/framework/src/org/apache/cordova/LinearLayoutSoftKeyboardDetect.java
index bb6b6a8..63dd9db 100755
--- a/framework/src/org/apache/cordova/LinearLayoutSoftKeyboardDetect.java
+++ b/framework/src/org/apache/cordova/LinearLayoutSoftKeyboardDetect.java
@@ -88,13 +88,13 @@ public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
         // gone away.
         else if (height > oldHeight) {
             if (app != null)
-                app.appView.sendJavascript("cordova.fireDocumentEvent('hidekeyboard');");
+                app.sendJavascript("cordova.fireDocumentEvent('hidekeyboard');");
         }
         // If the height as gotten smaller then we will assume the soft keyboard has 
         // been displayed.
         else if (height < oldHeight) {
             if (app != null)
-                app.appView.sendJavascript("cordova.fireDocumentEvent('showkeyboard');");
+                app.sendJavascript("cordova.fireDocumentEvent('showkeyboard');");
         }
 
         // Update the old height for the next event


[12/12] android commit: Try other constructors besides first

Posted by ia...@apache.org.
Try other constructors besides first


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

Branch: refs/heads/pluggable_webview
Commit: df05f3a3c07c0630c3d598409289db7a8f3c87e3
Parents: 8e31ef7
Author: Ian Clelland <ic...@chromium.org>
Authored: Thu Apr 24 14:58:16 2014 -0400
Committer: Ian Clelland <ic...@chromium.org>
Committed: Tue Apr 29 22:50:12 2014 -0400

----------------------------------------------------------------------
 .../src/org/apache/cordova/CordovaActivity.java   | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/df05f3a3/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 01eff1c..830332e 100755
--- a/framework/src/org/apache/cordova/CordovaActivity.java
+++ b/framework/src/org/apache/cordova/CordovaActivity.java
@@ -219,16 +219,18 @@ public class CordovaActivity extends Activity implements CordovaInterface {
         try {
             Class webViewClass = Class.forName(r);
             Constructor<CordovaWebView> [] webViewConstructors = webViewClass.getConstructors();
-            
-            
+
             if(CordovaWebView.class.isAssignableFrom(webViewClass)) {
-                CordovaWebView webView =  (CordovaWebView) webViewConstructors[0].newInstance(this);
-                return webView;
-            }
-            else
-            {
-                LOG.e(TAG, "The WebView Engine is NOT a proper WebView, defaulting to system WebView");
+                for (Constructor<CordovaWebView> constructor : webViewConstructors) {
+                    try {
+                        CordovaWebView webView = (CordovaWebView) constructor.newInstance(this);
+                        return webView;
+                    } catch (IllegalArgumentException e) {
+                        LOG.d(TAG, "Illegal arguments; trying next constructor.");
+                    }
+                }
             }
+            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) {


[06/12] android commit: Hurray! It runs! Now that we have the default WebView working, it's time to make things a little more pluggable.

Posted by ia...@apache.org.
Hurray! It runs! Now that we have the default WebView working, it's time
to make things a little more pluggable.


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

Branch: refs/heads/pluggable_webview
Commit: 19f76d34dba248e4549d3abe4e6e033b915d3e21
Parents: 25c8b2f
Author: Joe Bowser <bo...@apache.org>
Authored: Wed Mar 5 15:50:02 2014 -0800
Committer: Ian Clelland <ic...@chromium.org>
Committed: Tue Apr 29 22:50:11 2014 -0400

----------------------------------------------------------------------
 .../org/apache/cordova/AndroidChromeClient.java |  397 +++++++
 .../src/org/apache/cordova/AndroidWebView.java  | 1074 ++++++++++++++++++
 .../apache/cordova/AndroidWebViewClient.java    |  496 ++++++++
 .../src/org/apache/cordova/CordovaActivity.java |  114 +-
 .../org/apache/cordova/CordovaChromeClient.java |  369 +-----
 .../src/org/apache/cordova/CordovaWebView.java  | 1057 ++---------------
 .../apache/cordova/CordovaWebViewClient.java    |  480 +-------
 .../cordova/IceCreamCordovaWebViewClient.java   |    8 +-
 .../cordova/LinearLayoutSoftKeyboardDetect.java |    4 +-
 9 files changed, 2076 insertions(+), 1923 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/19f76d34/framework/src/org/apache/cordova/AndroidChromeClient.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/AndroidChromeClient.java b/framework/src/org/apache/cordova/AndroidChromeClient.java
new file mode 100755
index 0000000..1297a6c
--- /dev/null
+++ b/framework/src/org/apache/cordova/AndroidChromeClient.java
@@ -0,0 +1,397 @@
+/*
+       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.CordovaInterface;
+import org.apache.cordova.LOG;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import android.annotation.TargetApi;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.webkit.ConsoleMessage;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.webkit.ValueCallback;
+import android.webkit.WebChromeClient;
+import android.webkit.WebStorage;
+import android.webkit.WebView;
+import android.webkit.GeolocationPermissions.Callback;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+
+/**
+ * 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,
+ * such as onCreateWindow(), onConsoleMessage(), onProgressChanged(), etc. Related
+ * to but different than CordovaWebViewClient.
+ *
+ * @see <a href="http://developer.android.com/reference/android/webkit/WebChromeClient.html">WebChromeClient</a>
+ * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
+ * @see CordovaWebViewClient
+ * @see CordovaWebView
+ */
+public class AndroidChromeClient extends WebChromeClient implements CordovaChromeClient {
+
+    public static final int FILECHOOSER_RESULTCODE = 5173;
+    private static final String LOG_TAG = "CordovaChromeClient";
+    private String TAG = "CordovaLog";
+    private long MAX_QUOTA = 100 * 1024 * 1024;
+    protected CordovaInterface cordova;
+    protected CordovaWebView appView;
+
+    // the video progress view
+    private View mVideoProgressView;
+    
+    // File Chooser
+    public ValueCallback<Uri> mUploadMessage;
+    
+    /**
+     * Constructor.
+     *
+     * @param cordova
+     */
+    public AndroidChromeClient(CordovaInterface cordova) {
+        this.cordova = cordova;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param ctx
+     * @param app
+     */
+    public AndroidChromeClient(CordovaInterface ctx, CordovaWebView app) {
+        this.cordova = ctx;
+        this.appView = app;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param view
+     */
+    public void setWebView(CordovaWebView view) {
+        this.appView = view;
+    }
+
+    /**
+     * Tell the client to display a javascript alert dialog.
+     *
+     * @param view
+     * @param url
+     * @param message
+     * @param result
+     */
+    @Override
+    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
+        AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
+        dlg.setMessage(message);
+        dlg.setTitle("Alert");
+        //Don't let alerts break the back button
+        dlg.setCancelable(true);
+        dlg.setPositiveButton(android.R.string.ok,
+                new AlertDialog.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        result.confirm();
+                    }
+                });
+        dlg.setOnCancelListener(
+                new DialogInterface.OnCancelListener() {
+                    public void onCancel(DialogInterface dialog) {
+                        result.cancel();
+                    }
+                });
+        dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
+            //DO NOTHING
+            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                if (keyCode == KeyEvent.KEYCODE_BACK)
+                {
+                    result.confirm();
+                    return false;
+                }
+                else
+                    return true;
+            }
+        });
+        dlg.show();
+        return true;
+    }
+
+    /**
+     * Tell the client to display a confirm dialog to the user.
+     *
+     * @param view
+     * @param url
+     * @param message
+     * @param result
+     */
+    @Override
+    public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
+        AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
+        dlg.setMessage(message);
+        dlg.setTitle("Confirm");
+        dlg.setCancelable(true);
+        dlg.setPositiveButton(android.R.string.ok,
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        result.confirm();
+                    }
+                });
+        dlg.setNegativeButton(android.R.string.cancel,
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        result.cancel();
+                    }
+                });
+        dlg.setOnCancelListener(
+                new DialogInterface.OnCancelListener() {
+                    public void onCancel(DialogInterface dialog) {
+                        result.cancel();
+                    }
+                });
+        dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
+            //DO NOTHING
+            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                if (keyCode == KeyEvent.KEYCODE_BACK)
+                {
+                    result.cancel();
+                    return false;
+                }
+                else
+                    return true;
+            }
+        });
+        dlg.show();
+        return true;
+    }
+
+    /**
+     * Tell the client to display a prompt dialog to the user.
+     * If the client returns true, WebView will assume that the client will
+     * handle the prompt dialog and call the appropriate JsPromptResult method.
+     *
+     * Since we are hacking prompts for our own purposes, we should not be using them for
+     * this purpose, perhaps we should hack console.log to do this instead!
+     *
+     * @param view
+     * @param url
+     * @param message
+     * @param defaultValue
+     * @param result
+     */
+    @Override
+    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
+
+        // Security check to make sure any requests are coming from the page initially
+        // loaded in webview and not another loaded in an iframe.
+        boolean reqOk = false;
+        if (url.startsWith("file://") || Config.isUrlWhiteListed(url)) {
+            reqOk = true;
+        }
+
+        // Calling PluginManager.exec() to call a native service using 
+        // prompt(this.stringify(args), "gap:"+this.stringify([service, action, callbackId, true]));
+        if (reqOk && defaultValue != null && defaultValue.length() > 3 && defaultValue.substring(0, 4).equals("gap:")) {
+            JSONArray array;
+            try {
+                array = new JSONArray(defaultValue.substring(4));
+                String service = array.getString(0);
+                String action = array.getString(1);
+                String callbackId = array.getString(2);
+                
+                //String r = this.appView.exposedJsApi.exec(service, action, callbackId, message);
+                String r = this.appView.exec(service, action, callbackId, message);
+                result.confirm(r == null ? "" : r);
+            } catch (JSONException e) {
+                e.printStackTrace();
+                return false;
+            }
+        }
+
+        // Sets the native->JS bridge mode. 
+        else if (reqOk && defaultValue != null && defaultValue.equals("gap_bridge_mode:")) {
+        	try {
+                //this.appView.exposedJsApi.setNativeToJsBridgeMode(Integer.parseInt(message));
+        	    this.appView.setNativeToJsBridgeMode(Integer.parseInt(message));
+                result.confirm("");
+        	} catch (NumberFormatException e){
+                result.confirm("");
+                e.printStackTrace();
+        	}
+        }
+
+        // Polling for JavaScript messages 
+        else if (reqOk && defaultValue != null && defaultValue.equals("gap_poll:")) {
+            //String r = this.appView.exposedJsApi.retrieveJsMessages("1".equals(message));
+            String r = this.appView.retrieveJsMessages("1".equals(message));
+            result.confirm(r == null ? "" : r);
+        }
+
+        // Do NO-OP so older code doesn't display dialog
+        else if (defaultValue != null && defaultValue.equals("gap_init:")) {
+            result.confirm("OK");
+        }
+
+        // Show dialog
+        else {
+            final JsPromptResult res = result;
+            AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
+            dlg.setMessage(message);
+            final EditText input = new EditText(this.cordova.getActivity());
+            if (defaultValue != null) {
+                input.setText(defaultValue);
+            }
+            dlg.setView(input);
+            dlg.setCancelable(false);
+            dlg.setPositiveButton(android.R.string.ok,
+                    new DialogInterface.OnClickListener() {
+                        public void onClick(DialogInterface dialog, int which) {
+                            String usertext = input.getText().toString();
+                            res.confirm(usertext);
+                        }
+                    });
+            dlg.setNegativeButton(android.R.string.cancel,
+                    new DialogInterface.OnClickListener() {
+                        public void onClick(DialogInterface dialog, int which) {
+                            res.cancel();
+                        }
+                    });
+            dlg.show();
+        }
+        return true;
+    }
+
+    /**
+     * Handle database quota exceeded notification.
+     */
+    @Override
+    public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
+            long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
+    {
+        LOG.d(TAG, "onExceededDatabaseQuota estimatedSize: %d  currentQuota: %d  totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
+        quotaUpdater.updateQuota(MAX_QUOTA);
+    }
+
+    // console.log in api level 7: http://developer.android.com/guide/developing/debug-tasks.html
+    // Expect this to not compile in a future Android release!
+    @SuppressWarnings("deprecation")
+    @Override
+    public void onConsoleMessage(String message, int lineNumber, String sourceID)
+    {
+        //This is only for Android 2.1
+        if(android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.ECLAIR_MR1)
+        {
+            LOG.d(TAG, "%s: Line %d : %s", sourceID, lineNumber, message);
+            super.onConsoleMessage(message, lineNumber, sourceID);
+        }
+    }
+
+    @TargetApi(8)
+    @Override
+    public boolean onConsoleMessage(ConsoleMessage consoleMessage)
+    {
+        if (consoleMessage.message() != null)
+            LOG.d(TAG, "%s: Line %d : %s" , consoleMessage.sourceId() , consoleMessage.lineNumber(), consoleMessage.message());
+         return super.onConsoleMessage(consoleMessage);
+    }
+
+    @Override
+    /**
+     * Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin.
+     *
+     * @param origin
+     * @param callback
+     */
+    public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
+        super.onGeolocationPermissionsShowPrompt(origin, callback);
+        callback.invoke(origin, true, false);
+    }
+    
+    // API level 7 is required for this, see if we could lower this using something else
+    @Override
+    public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
+        this.appView.showCustomView(view, callback);
+    }
+
+	@Override
+	public void onHideCustomView() {
+    	this.appView.hideCustomView();
+	}
+    
+    @Override
+    /**
+     * Ask the host application for a custom progress view to show while
+     * a <video> is loading.
+     * @return View The progress view.
+     */
+    public View getVideoLoadingProgressView() {
+
+	    if (mVideoProgressView == null) {	        
+	    	// Create a new Loading view programmatically.
+	    	
+	    	// create the linear layout
+	    	LinearLayout layout = new LinearLayout(this.appView.getContext());
+	        layout.setOrientation(LinearLayout.VERTICAL);
+	        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+	        layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
+	        layout.setLayoutParams(layoutParams);
+	        // the proress bar
+	        ProgressBar bar = new ProgressBar(this.appView.getContext());
+	        LinearLayout.LayoutParams barLayoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+	        barLayoutParams.gravity = Gravity.CENTER;
+	        bar.setLayoutParams(barLayoutParams);   
+	        layout.addView(bar);
+	        
+	        mVideoProgressView = layout;
+	    }
+    return mVideoProgressView; 
+    }
+    
+    public void openFileChooser(ValueCallback<Uri> uploadMsg) {
+        this.openFileChooser(uploadMsg, "*/*");
+    }
+
+    public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) {
+        this.openFileChooser(uploadMsg, acceptType, null);
+    }
+    
+    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)
+    {
+        mUploadMessage = uploadMsg;
+        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
+        i.addCategory(Intent.CATEGORY_OPENABLE);
+        i.setType("*/*");
+        this.cordova.getActivity().startActivityForResult(Intent.createChooser(i, "File Browser"),
+                FILECHOOSER_RESULTCODE);
+    }
+    
+    public ValueCallback<Uri> getValueCallback() {
+        return this.mUploadMessage;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/19f76d34/framework/src/org/apache/cordova/AndroidWebView.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/AndroidWebView.java b/framework/src/org/apache/cordova/AndroidWebView.java
new file mode 100755
index 0000000..993629a
--- /dev/null
+++ b/framework/src/org/apache/cordova/AndroidWebView.java
@@ -0,0 +1,1074 @@
+/*
+       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 java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Locale;
+
+import org.apache.cordova.Config;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.LOG;
+import org.apache.cordova.PluginManager;
+import org.apache.cordova.PluginResult;
+import org.json.JSONException;
+
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+import android.webkit.WebBackForwardList;
+import android.webkit.WebHistoryItem;
+import android.webkit.WebChromeClient;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebSettings.LayoutAlgorithm;
+import android.webkit.WebViewClient;
+import android.widget.FrameLayout;
+
+/*
+ * This class is our web view.
+ *
+ * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
+ * @see <a href="http://developer.android.com/reference/android/webkit/WebView.html">WebView</a>
+ */
+public class AndroidWebView extends WebView implements CordovaWebView {
+
+    public static final String TAG = "CordovaWebView";
+    public static final String CORDOVA_VERSION = "3.5.0-dev";
+
+    private ArrayList<Integer> keyDownCodes = new ArrayList<Integer>();
+    private ArrayList<Integer> keyUpCodes = new ArrayList<Integer>();
+
+    PluginManager pluginManager;
+    private boolean paused;
+
+    private BroadcastReceiver receiver;
+
+
+    /** Activities and other important classes **/
+    private CordovaInterface cordova;
+    CordovaWebViewClient viewClient;
+    @SuppressWarnings("unused")
+    private CordovaChromeClient chromeClient;
+
+    private String url;
+
+    // Flag to track that a loadUrl timeout occurred
+    int loadUrlTimeout = 0;
+
+    private boolean bound;
+
+    private boolean handleButton = false;
+    
+    private long lastMenuEventTime = 0;
+
+    NativeToJsMessageQueue jsMessageQueue;
+    ExposedJsApi exposedJsApi;
+
+    /** custom view created by the browser (a video player for example) */
+    private View mCustomView;
+    private WebChromeClient.CustomViewCallback mCustomViewCallback;
+
+    private ActivityResult mResult = null;
+
+    private CordovaResourceApi resourceApi;
+
+    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,
+            ViewGroup.LayoutParams.MATCH_PARENT,
+            Gravity.CENTER);
+    
+    /**
+     * Constructor.
+     *
+     * @param context
+     */
+    public AndroidWebView(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.loadConfiguration();
+        this.setup();
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param context
+     * @param attrs
+     */
+    public AndroidWebView(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((CordovaChromeClient) new AndroidChromeClient(this.cordova, this));
+        this.initWebViewClient(this.cordova);
+        this.loadConfiguration();
+        this.setup();
+    }
+
+    /**
+     * 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.setWebChromeClient((CordovaChromeClient) new AndroidChromeClient(this.cordova, this));
+        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.setWebChromeClient((CordovaChromeClient) new AndroidChromeClient(this.cordova));
+        this.initWebViewClient(this.cordova);
+        this.loadConfiguration();
+        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((CordovaWebViewClient) new AndroidWebViewClient(this.cordova, this));
+        }
+        else
+        {
+            this.setWebViewClient((CordovaWebViewClient) new IceCreamCordovaWebViewClient(this.cordova, this));
+        }
+    }
+
+    /**
+     * Initialize webview.
+     */
+    @SuppressWarnings("deprecation")
+    @SuppressLint("NewApi")
+    private void setup() {
+        this.setInitialScale(0);
+        this.setVerticalScrollBarEnabled(false);
+        if (shouldRequestFocusOnInit()) {
+			this.requestFocusFromTouch();
+		}
+		// Enable JavaScript
+        WebSettings settings = this.getSettings();
+        settings.setJavaScriptEnabled(true);
+        settings.setJavaScriptCanOpenWindowsAutomatically(true);
+        settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
+        
+        // Set the nav dump for HTC 2.x devices (disabling for ICS, deprecated entirely for Jellybean 4.2)
+        try {
+            Method gingerbread_getMethod =  WebSettings.class.getMethod("setNavDump", new Class[] { boolean.class });
+            
+            String manufacturer = android.os.Build.MANUFACTURER;
+            Log.d(TAG, "CordovaWebView is running on device made by: " + manufacturer);
+            if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB &&
+                    android.os.Build.MANUFACTURER.contains("HTC"))
+            {
+                gingerbread_getMethod.invoke(settings, true);
+            }
+        } catch (NoSuchMethodException e) {
+            Log.d(TAG, "We are on a modern version of Android, we will deprecate HTC 2.3 devices in 2.8");
+        } catch (IllegalArgumentException e) {
+            Log.d(TAG, "Doing the NavDump failed with bad arguments");
+        } catch (IllegalAccessException e) {
+            Log.d(TAG, "This should never happen: IllegalAccessException means this isn't Android anymore");
+        } catch (InvocationTargetException e) {
+            Log.d(TAG, "This should never happen: InvocationTargetException means this isn't Android anymore.");
+        }
+
+        //We don't save any form data in the application
+        settings.setSaveFormData(false);
+        settings.setSavePassword(false);
+        
+        // Jellybean rightfully tried to lock this down. Too bad they didn't give us a whitelist
+        // while we do this
+        if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
+            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();
+        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();
+        }  
+        
+        settings.setGeolocationDatabasePath(databasePath);
+
+        // Enable DOM storage
+        settings.setDomStorageEnabled(true);
+
+        // Enable built-in geolocation
+        settings.setGeolocationEnabled(true);
+        
+        // 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.setAppCacheEnabled(true);
+        
+        // Fix for CB-1405
+        // Google issue 4641
+        this.updateUserAgentString();
+        
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+        if (this.receiver == null) {
+            this.receiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    updateUserAgentString();
+                }
+            };
+            this.cordova.getActivity().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();
+    }
+
+	/**
+	 * Override this method to decide whether or not you need to request the
+	 * focus when your application start
+	 * 
+	 * @return true unless this method is overriden to return a different value
+	 */
+    protected boolean shouldRequestFocusOnInit() {
+		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)) {
+            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
+            // use the prompt bridge instead.
+            return;            
+        } 
+        this.addJavascriptInterface(exposedJsApi, "_cordovaNative");
+    }
+
+    /**
+     * Set the WebViewClient.
+     *
+     * @param client
+     */
+    public void setWebViewClient(CordovaWebViewClient client) {
+        this.viewClient = client;
+        super.setWebViewClient((WebViewClient) client);
+    }
+
+    /**
+     * Set the WebChromeClient.
+     *
+     * @param client
+     */
+    public void setWebChromeClient(CordovaChromeClient client) {
+        this.chromeClient = client;
+        super.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 {
+
+            String initUrl = this.getProperty("url", null);
+
+            // If first page of app, then set URL to load to be the one passed in
+            if (initUrl == null) {
+                this.loadUrlIntoView(url);
+            }
+            // Otherwise use the URL specified in the activity's extras bundle
+            else {
+                this.loadUrlIntoView(initUrl);
+            }
+        }
+    }
+
+    /**
+     * 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 loadUrl(final String url, int time) {
+        String initUrl = this.getProperty("url", null);
+
+        // If first page of app, then set URL to load to be the one passed in
+        if (initUrl == null) {
+            this.loadUrlIntoView(url, time);
+        }
+        // Otherwise use the URL specified in the activity's extras bundle
+        else {
+            this.loadUrlIntoView(initUrl);
+        }
+    }
+
+    public void loadUrlIntoView(final String url) {
+        loadUrlIntoView(url, true);
+    }
+
+    /**
+     * Load the url into the webview.
+     *
+     * @param url
+     */
+    public void loadUrlIntoView(final String url, boolean recreatePlugins) {
+        LOG.d(TAG, ">>> loadUrl(" + url + ")");
+
+        if (recreatePlugins) {
+            this.url = url;
+            this.pluginManager.init();
+        }
+
+        // Create a timeout timer for loadUrl
+        final AndroidWebView me = this;
+        final int currentLoadUrlTimeout = me.loadUrlTimeout;
+        final int loadUrlTimeoutValue = Integer.parseInt(this.getProperty("LoadUrlTimeoutValue", "20000"));
+
+        // Timeout error method
+        final Runnable loadError = new Runnable() {
+            public void run() {
+                me.stopLoading();
+                LOG.e(TAG, "CordovaWebView: TIMEOUT ERROR!");
+                if (viewClient != null) {
+                    viewClient.onReceivedError(me, -6, "The connection to the server was unsuccessful.", url);
+                }
+            }
+        };
+
+        // Timeout timer method
+        final Runnable timeoutCheck = new Runnable() {
+            public void run() {
+                try {
+                    synchronized (this) {
+                        wait(loadUrlTimeoutValue);
+                    }
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+
+                // If timeout, then stop loading and handle error
+                if (me.loadUrlTimeout == currentLoadUrlTimeout) {
+                    me.cordova.getActivity().runOnUiThread(loadError);
+                }
+            }
+        };
+
+        // Load url
+        this.cordova.getActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                cordova.getThreadPool().execute(timeoutCheck);
+                me.loadUrlNow(url);
+            }
+        });
+    }
+
+    /**
+     * Load URL in webview.
+     *
+     * @param url
+     */
+    public void loadUrlNow(String url) {
+        if (LOG.isLoggable(LOG.DEBUG) && !url.startsWith("javascript:")) {
+            LOG.d(TAG, ">>> loadUrlNow()");
+        }
+        if (url.startsWith("file://") || url.startsWith("javascript:") || Config.isUrlWhiteListed(url)) {
+            super.loadUrl(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
+     */
+    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;
+        super.stopLoading();
+    }
+    
+    public void onScrollChanged(int l, int t, int oldl, int oldt)
+    {
+        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);
+    }
+    
+    /**
+     * Send JavaScript statement back to JavaScript.
+     * (This is a convenience method)
+     *
+     * @param statement
+     */
+    public void sendJavascript(String statement) {
+        this.jsMessageQueue.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);
+    }
+
+    /**
+     * 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)
+     *
+     * @return true if we went back, false if we are already at top
+     */
+    public boolean backHistory() {
+
+        // Check webview first to see if there is a history
+        // This is needed to support curPage#diffLink, since they are added to appView's history, but not our history url array (JQMobile behavior)
+        if (super.canGoBack()) {
+            printBackForwardList();
+            super.goBack();
+            
+            return true;
+        }
+        return false;
+    }
+
+
+    /**
+     * Load the specified URL in the Cordova webview or a new browser instance.
+     *
+     * NOTE: If openExternal is false, only URLs listed in whitelist can be loaded.
+     *
+     * @param url           The url to load.
+     * @param openExternal  Load url in browser instead of Cordova webview.
+     * @param clearHistory  Clear the history stack, so new page becomes top of history
+     * @param params        Parameters for new app
+     */
+    public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap<String, Object> params) {
+        LOG.d(TAG, "showWebPage(%s, %b, %b, HashMap", url, openExternal, clearHistory);
+
+        // If clearing history
+        if (clearHistory) {
+            this.clearHistory();
+        }
+
+        // If loading into our webview
+        if (!openExternal) {
+
+            // Make sure url is in whitelist
+            if (url.startsWith("file://") || Config.isUrlWhiteListed(url)) {
+                // TODO: What about params?
+                // Load new URL
+                this.loadUrl(url);
+                return;
+            }
+            // Load in default viewer if not
+            LOG.w(TAG, "showWebPage: Cannot load URL into webview since it is not in white list.  Loading into browser instead. (URL=" + url + ")");
+        }
+        try {
+            // Omitting the MIME type for file: URLs causes "No Activity found to handle Intent".
+            // Adding the MIME type to http: URLs causes them to not be handled by the downloader.
+            Intent intent = new Intent(Intent.ACTION_VIEW);
+            Uri uri = Uri.parse(url);
+            if ("file".equals(uri.getScheme())) {
+                intent.setDataAndType(uri, resourceApi.getMimeType(uri));
+            } else {
+                intent.setData(uri);
+            }
+            cordova.getActivity().startActivity(intent);
+        } catch (android.content.ActivityNotFoundException e) {
+            LOG.e(TAG, "Error loading url " + url, e);
+        }
+    }
+
+    /**
+     * 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.
+     *
+     * @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
+     */
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event)
+    {
+        if(keyDownCodes.contains(keyCode))
+        {
+            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
+                    // only override default behavior is event bound
+                    LOG.d(TAG, "Down Key Hit");
+                    this.loadUrl("javascript:cordova.fireDocumentEvent('volumedownbutton');");
+                    return true;
+            }
+            // If volumeup key
+            else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
+                    LOG.d(TAG, "Up Key Hit");
+                    this.loadUrl("javascript:cordova.fireDocumentEvent('volumeupbutton');");
+                    return true;
+            }
+            else
+            {
+                return super.onKeyDown(keyCode, event);
+            }
+        }
+        else if(keyCode == KeyEvent.KEYCODE_BACK)
+        {
+            return !(this.startOfHistory()) || this.bound;
+        }
+        else if(keyCode == KeyEvent.KEYCODE_MENU)
+        {
+            //How did we get here?  Is there a childView?
+            View childView = this.getFocusedChild();
+            if(childView != null)
+            {
+                //Make sure we close the keyboard if it's present
+                InputMethodManager imm = (InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+                imm.hideSoftInputFromWindow(childView.getWindowToken(), 0);
+                cordova.getActivity().openOptionsMenu();
+                return true;
+            } else {
+                return super.onKeyDown(keyCode, event);
+            }
+        }
+        
+        return super.onKeyDown(keyCode, event);
+    }
+    
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event)
+    {
+        // If back key
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            // A custom view is currently displayed  (e.g. playing a video)
+            if(mCustomView != null) {
+                this.hideCustomView();
+            } else {
+                // The webview is currently displayed
+                // If back key is bound, then send event to JavaScript
+                if (this.bound) {
+                    this.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');");
+                    return true;
+                } else {
+                    // If not bound
+                    // Go to previous page in webview if it is possible to go back
+                    if (this.backHistory()) {
+                        return true;
+                    }
+                    // If not, then invoke default behavior
+                    else {
+                        //this.activityState = ACTIVITY_EXITING;
+                    	//return false;
+                    	// If they hit back button when app is initializing, app should exit instead of hang until initialization (CB2-458)
+                    	this.cordova.getActivity().finish();
+                    }
+                }
+            }
+        }
+        // Legacy
+        else if (keyCode == KeyEvent.KEYCODE_MENU) {
+            if (this.lastMenuEventTime < event.getEventTime()) {
+                this.loadUrl("javascript:cordova.fireDocumentEvent('menubutton');");
+            }
+            this.lastMenuEventTime = event.getEventTime();
+            return super.onKeyUp(keyCode, event);
+        }
+        // If search key
+        else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
+            this.loadUrl("javascript:cordova.fireDocumentEvent('searchbutton');");
+            return true;
+        }
+        else if(keyUpCodes.contains(keyCode))
+        {
+            //What the hell should this do?
+            return super.onKeyUp(keyCode, event);
+        }
+
+        //Does webkit change this behavior?
+        return super.onKeyUp(keyCode, event);
+    }
+
+    
+    public void bindButton(boolean override)
+    {
+        this.bound = override;
+    }
+
+    public void bindButton(String button, boolean override) {
+        // TODO Auto-generated method stub
+        if (button.compareTo("volumeup")==0) {
+          keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_UP);
+        }
+        else if (button.compareTo("volumedown")==0) {
+          keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_DOWN);
+        }
+      }
+
+    public void bindButton(int keyCode, boolean keyDown, boolean override) {
+       if(keyDown)
+       {
+           keyDownCodes.add(keyCode);
+       }
+       else
+       {
+           keyUpCodes.add(keyCode);
+       }
+    }
+
+    public boolean isBackButtonBound()
+    {
+        return this.bound;
+    }
+    
+    public void handlePause(boolean keepRunning)
+    {
+        LOG.d(TAG, "Handle the pause");
+        // Send pause event to JavaScript
+        this.loadUrl("javascript:try{cordova.fireDocumentEvent('pause');}catch(e){console.log('exception firing pause event from native');};");
+
+        // Forward to plugins
+        if (this.pluginManager != null) {
+            this.pluginManager.onPause(keepRunning);
+        }
+
+        // If app doesn't want to run in background
+        if (!keepRunning) {
+            // 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
+        if (this.pluginManager != null) {
+            this.pluginManager.onResume(keepRunning);
+        }
+
+        // Resume JavaScript timers (including setInterval)
+        this.resumeTimers();
+        paused = false;
+    }
+    
+    public void handleDestroy()
+    {
+        // Send destroy event to JavaScript
+        this.loadUrl("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};");
+
+        // Load blank page so that JavaScript onunload is called
+        this.loadUrl("about:blank");
+
+        // Forward to plugins
+        if (this.pluginManager != null) {
+            this.pluginManager.onDestroy();
+        }
+        
+        // unregister the receiver
+        if (this.receiver != null) {
+            try {
+                this.cordova.getActivity().unregisterReceiver(this.receiver);
+            } catch (Exception e) {
+                Log.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e);
+            }
+        }
+    }
+    
+    public void onNewIntent(Intent intent)
+    {
+        //Forward to plugins
+        if (this.pluginManager != null) {
+            this.pluginManager.onNewIntent(intent);
+        }
+    }
+    
+    public boolean isPaused()
+    {
+        return paused;
+    }
+
+    public boolean hadKeyEvent() {
+        return handleButton;
+    }
+
+    // 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)
+    private static class Level16Apis {
+        static void enableUniversalAccess(WebSettings settings) {
+            settings.setAllowUniversalAccessFromFileURLs(true);
+        }
+    }
+    
+    public void printBackForwardList() {
+        WebBackForwardList currentList = this.copyBackForwardList();
+        int currentSize = currentList.getSize();
+        for(int i = 0; i < currentSize; ++i)
+        {
+            WebHistoryItem item = currentList.getItemAtIndex(i);
+            String url = item.getUrl();
+            LOG.d(TAG, "The URL at index: " + Integer.toString(i) + " is " + url );
+        }
+    }
+    
+    
+    //Can Go Back is BROKEN!
+    public boolean startOfHistory()
+    {
+        WebBackForwardList currentList = this.copyBackForwardList();
+        WebHistoryItem item = currentList.getItemAtIndex(0);
+        if( item!=null){	// Null-fence in case they haven't called loadUrl yet (CB-2458)
+	        String url = item.getUrl();
+	        String currentUrl = this.getUrl();
+	        LOG.d(TAG, "The current URL is: " + currentUrl);
+	        LOG.d(TAG, "The URL at item 0 is: " + url);
+	        return currentUrl.equals(url);
+        }
+        return false;
+    }
+
+    public void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
+        // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
+        Log.d(TAG, "showing Custom View");
+        // if a view already exists then immediately terminate the new one
+        if (mCustomView != null) {
+            callback.onCustomViewHidden();
+            return;
+        }
+        
+        // Store the view and its callback for later (to kill it properly)
+        mCustomView = view;
+        mCustomViewCallback = callback;
+        
+        // Add the custom view to its container.
+        ViewGroup parent = (ViewGroup) this.getParent();
+        parent.addView(view, COVER_SCREEN_GRAVITY_CENTER);
+        
+        // Hide the content view.
+        this.setVisibility(View.GONE);
+        
+        // Finally show the custom view container.
+        parent.setVisibility(View.VISIBLE);
+        parent.bringToFront();
+    }
+
+    public void hideCustomView() {
+        // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
+        Log.d(TAG, "Hiding Custom View");
+        if (mCustomView == null) return;
+
+        // Hide the custom view.
+        mCustomView.setVisibility(View.GONE);
+        
+        // Remove the custom view from its container.
+        ViewGroup parent = (ViewGroup) this.getParent();
+        parent.removeView(mCustomView);
+        mCustomView = null;
+        mCustomViewCallback.onCustomViewHidden();
+        
+        // Show the content view.
+        this.setVisibility(View.VISIBLE);
+    }
+    
+    /**
+     * if the video overlay is showing then we need to know 
+     * as it effects back button handling
+     * 
+     * @return true if custom view is showing
+     */
+    public boolean isCustomViewShowing() {
+        return mCustomView != null;
+    }
+    
+    public WebBackForwardList restoreState(Bundle savedInstanceState)
+    {
+        WebBackForwardList myList = super.restoreState(savedInstanceState);
+        Log.d(TAG, "WebView restoration crew now restoring!");
+        //Initialize the plugin manager once more
+        this.pluginManager.init();
+        return myList;
+    }
+
+    public void storeResult(int requestCode, int resultCode, Intent intent) {
+        mResult = new ActivityResult(requestCode, resultCode, intent);
+    }
+    
+    public CordovaResourceApi getResourceApi() {
+        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 String exec(String service, String action, String callbackId,
+            String message) throws JSONException {
+        return this.exposedJsApi.exec(service, action, callbackId, message);
+    }
+
+    @Override
+    public void setNativeToJsBridgeMode(int parseInt) {
+        this.exposedJsApi.setNativeToJsBridgeMode(parseInt);
+    }
+
+    @Override
+    public String retrieveJsMessages(boolean equals) {
+        return this.exposedJsApi.retrieveJsMessages(equals);
+    }
+
+    @Override
+    public boolean onOverrideUrlLoading(String url) {
+        return this.pluginManager.onOverrideUrlLoading(url);
+    }
+
+    @Override
+    public void resetJsMessageQueue() {
+        this.jsMessageQueue.reset();
+    }
+
+    @Override
+    public void onReset() {
+        this.pluginManager.onReset();
+    }
+
+    @Override
+    public void incUrlTimeout() {
+        this.loadUrlTimeout++;
+    }
+
+    @Override
+    public PluginManager getPluginManager() {
+        // TODO Auto-generated method stub
+        return this.pluginManager;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/19f76d34/framework/src/org/apache/cordova/AndroidWebViewClient.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/AndroidWebViewClient.java b/framework/src/org/apache/cordova/AndroidWebViewClient.java
new file mode 100755
index 0000000..3d82fca
--- /dev/null
+++ b/framework/src/org/apache/cordova/AndroidWebViewClient.java
@@ -0,0 +1,496 @@
+/*
+       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 java.io.ByteArrayInputStream;
+import java.util.Hashtable;
+
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.LOG;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.annotation.TargetApi;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.net.http.SslError;
+import android.util.Log;
+import android.view.View;
+import android.webkit.HttpAuthHandler;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebResourceResponse;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+/**
+ * This class is the WebViewClient that implements callbacks for our web view.
+ * The kind of callbacks that happen here are regarding the rendering of the
+ * document instead of the chrome surrounding it, such as onPageStarted(), 
+ * shouldOverrideUrlLoading(), etc. Related to but different than
+ * CordovaChromeClient.
+ *
+ * @see <a href="http://developer.android.com/reference/android/webkit/WebViewClient.html">WebViewClient</a>
+ * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
+ * @see CordovaChromeClient
+ * @see CordovaWebView
+ */
+public class AndroidWebViewClient extends WebViewClient implements CordovaWebViewClient{
+
+	private static final String TAG = "CordovaWebViewClient";
+	private static final String CORDOVA_EXEC_URL_PREFIX = "http://cdv_exec/";
+    CordovaInterface cordova;
+    CordovaWebView appView;
+    private boolean doClearHistory = false;
+    boolean isCurrentlyLoading;
+
+    /** The authorization tokens. */
+    private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
+
+    /**
+     * Constructor.
+     *
+     * @param cordova
+     */
+    public AndroidWebViewClient(CordovaInterface cordova) {
+        this.cordova = cordova;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param cordova
+     * @param view
+     */
+    public AndroidWebViewClient(CordovaInterface cordova, CordovaWebView view) {
+        this.cordova = cordova;
+        this.appView = view;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param view
+     */
+    public void setWebView(CordovaWebView view) {
+        this.appView = view;
+    }
+
+
+    // Parses commands sent by setting the webView's URL to:
+    // cdvbrg:service/action/callbackId#jsonArgs
+	private void handleExecUrl(String url) {
+		int idx1 = CORDOVA_EXEC_URL_PREFIX.length();
+		int idx2 = url.indexOf('#', idx1 + 1);
+		int idx3 = url.indexOf('#', idx2 + 1);
+		int idx4 = url.indexOf('#', idx3 + 1);
+		if (idx1 == -1 || idx2 == -1 || idx3 == -1 || idx4 == -1) {
+			Log.e(TAG, "Could not decode URL command: " + url);
+			return;
+		}
+		String service    = url.substring(idx1, idx2);
+		String action     = url.substring(idx2 + 1, idx3);
+		String callbackId = url.substring(idx3 + 1, idx4);
+		String jsonArgs   = url.substring(idx4 + 1);
+        try {
+            appView.exec(service, action, callbackId, jsonArgs);
+        } catch (JSONException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+	}
+
+    /**
+     * Give the host application a chance to take over the control when a new url
+     * is about to be loaded in the current WebView.
+     *
+     * @param view          The WebView that is initiating the callback.
+     * @param url           The url to be loaded.
+     * @return              true to override, false for default behavior
+     */
+	@Override
+    public boolean shouldOverrideUrlLoading(WebView view, String url) {
+    	// Check if it's an exec() bridge command message.
+    	if (NativeToJsMessageQueue.ENABLE_LOCATION_CHANGE_EXEC_MODE && url.startsWith(CORDOVA_EXEC_URL_PREFIX)) {
+    		handleExecUrl(url);
+    	}
+
+        // Give plugins the chance to handle the url
+    	else if (this.appView.onOverrideUrlLoading(url)) {
+        }
+
+        // If dialing phone (tel:5551212)
+        else if (url.startsWith(WebView.SCHEME_TEL)) {
+            try {
+                Intent intent = new Intent(Intent.ACTION_DIAL);
+                intent.setData(Uri.parse(url));
+                this.cordova.getActivity().startActivity(intent);
+            } catch (android.content.ActivityNotFoundException e) {
+                LOG.e(TAG, "Error dialing " + url + ": " + e.toString());
+            }
+        }
+
+        // If displaying map (geo:0,0?q=address)
+        else if (url.startsWith("geo:")) {
+            try {
+                Intent intent = new Intent(Intent.ACTION_VIEW);
+                intent.setData(Uri.parse(url));
+                this.cordova.getActivity().startActivity(intent);
+            } catch (android.content.ActivityNotFoundException e) {
+                LOG.e(TAG, "Error showing map " + url + ": " + e.toString());
+            }
+        }
+
+        // If sending email (mailto:abc@corp.com)
+        else if (url.startsWith(WebView.SCHEME_MAILTO)) {
+            try {
+                Intent intent = new Intent(Intent.ACTION_VIEW);
+                intent.setData(Uri.parse(url));
+                this.cordova.getActivity().startActivity(intent);
+            } catch (android.content.ActivityNotFoundException e) {
+                LOG.e(TAG, "Error sending email " + url + ": " + e.toString());
+            }
+        }
+
+        // If sms:5551212?body=This is the message
+        else if (url.startsWith("sms:")) {
+            try {
+                Intent intent = new Intent(Intent.ACTION_VIEW);
+
+                // Get address
+                String address = null;
+                int parmIndex = url.indexOf('?');
+                if (parmIndex == -1) {
+                    address = url.substring(4);
+                }
+                else {
+                    address = url.substring(4, parmIndex);
+
+                    // If body, then set sms body
+                    Uri uri = Uri.parse(url);
+                    String query = uri.getQuery();
+                    if (query != null) {
+                        if (query.startsWith("body=")) {
+                            intent.putExtra("sms_body", query.substring(5));
+                        }
+                    }
+                }
+                intent.setData(Uri.parse("sms:" + address));
+                intent.putExtra("address", address);
+                intent.setType("vnd.android-dir/mms-sms");
+                this.cordova.getActivity().startActivity(intent);
+            } catch (android.content.ActivityNotFoundException e) {
+                LOG.e(TAG, "Error sending sms " + url + ":" + e.toString());
+            }
+        }
+        
+        //Android Market
+        else if(url.startsWith("market:")) {
+            try {
+                Intent intent = new Intent(Intent.ACTION_VIEW);
+                intent.setData(Uri.parse(url));
+                this.cordova.getActivity().startActivity(intent);
+            } catch (android.content.ActivityNotFoundException e) {
+                LOG.e(TAG, "Error loading Google Play Store: " + url, e);
+            }
+        }
+
+        // All else
+        else {
+
+            // If our app or file:, then load into a new Cordova webview container by starting a new instance of our activity.
+            // Our app continues to run.  When BACK is pressed, our app is redisplayed.
+            if (url.startsWith("file://") || url.startsWith("data:")  || Config.isUrlWhiteListed(url)) {
+                return false;
+            }
+
+            // If not our application, let default viewer handle
+            else {
+                try {
+                    Intent intent = new Intent(Intent.ACTION_VIEW);
+                    intent.setData(Uri.parse(url));
+                    this.cordova.getActivity().startActivity(intent);
+                } catch (android.content.ActivityNotFoundException e) {
+                    LOG.e(TAG, "Error loading url " + url, e);
+                }
+            }
+        }
+        return true;
+    }
+    
+    /**
+     * 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) {
+
+        // Get the authentication token
+        AuthenticationToken token = this.getAuthenticationToken(host, realm);
+        if (token != null) {
+            handler.proceed(token.getUserName(), token.getPassword());
+        }
+        else {
+            // Handle 401 like we'd normally do!
+            super.onReceivedHttpAuthRequest(view, handler, host, realm);
+        }
+    }
+
+    /**
+     * Notify the host application that a page has started loading.
+     * This method is called once for each main frame load so a page with iframes or framesets will call onPageStarted
+     * one time for the main frame. This also means that onPageStarted will not be called when the contents of an
+     * embedded frame changes, i.e. clicking a link whose target is an iframe.
+     *
+     * @param view          The webview initiating the callback.
+     * @param url           The url of the page.
+     */
+    @Override
+    public void onPageStarted(WebView view, String url, Bitmap favicon) {
+        super.onPageStarted(view, url, favicon);
+        isCurrentlyLoading = true;
+        LOG.d(TAG, "onPageStarted(" + url + ")");
+        // Flush stale messages.
+        this.appView.resetJsMessageQueue();
+
+        // Broadcast message that page has loaded
+        this.appView.postMessage("onPageStarted", url);
+
+        // Notify all plugins of the navigation, so they can clean up if necessary.
+        this.appView.onReset();
+    }
+
+    /**
+     * Notify the host application that a page has finished loading.
+     * This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet.
+     *
+     *
+     * @param view          The webview initiating the callback.
+     * @param url           The url of the page.
+     */
+    @Override
+    public void onPageFinished(WebView view, String url) {
+        super.onPageFinished(view, url);
+        // Ignore excessive calls.
+        if (!isCurrentlyLoading) {
+            return;
+        }
+        isCurrentlyLoading = false;
+        LOG.d(TAG, "onPageFinished(" + url + ")");
+
+        /**
+         * Because of a timing issue we need to clear this history in onPageFinished as well as
+         * onPageStarted. However we only want to do this if the doClearHistory boolean is set to
+         * true. You see when you load a url with a # in it which is common in jQuery applications
+         * onPageStared is not called. Clearing the history at that point would break jQuery apps.
+         */
+        if (this.doClearHistory) {
+            view.clearHistory();
+            this.doClearHistory = false;
+        }
+
+        // Clear timeout flag
+        this.appView.incUrlTimeout();
+
+        // Broadcast message that page has loaded
+        this.appView.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) {
+            Thread t = new Thread(new Runnable() {
+                public void run() {
+                    try {
+                        Thread.sleep(2000);
+                        cordova.getActivity().runOnUiThread(new Runnable() {
+                            public void run() {
+                                appView.postMessage("spinner", "stop");
+                            }
+                        });
+                    } catch (InterruptedException e) {
+                    }
+                }
+            });
+            t.start();
+        }
+
+        // Shutdown if blank loaded
+        if (url.equals("about:blank")) {
+            appView.postMessage("exit", null);
+        }
+    }
+
+    /**
+     * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
+     * The errorCode parameter corresponds to one of the ERROR_* constants.
+     *
+     * @param view          The WebView that is initiating the callback.
+     * @param errorCode     The error code corresponding to an ERROR_* value.
+     * @param description   A String describing the error.
+     * @param failingUrl    The url that failed to load.
+     */
+    @Override
+    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+        // Ignore error due to stopLoading().
+        if (!isCurrentlyLoading) {
+            return;
+        }
+        LOG.d(TAG, "CordovaWebViewClient.onReceivedError: Error code=%s Description=%s URL=%s", errorCode, description, failingUrl);
+
+        // Clear timeout flag
+        this.appView.incUrlTimeout();
+
+        // Handle error
+        JSONObject data = new JSONObject();
+        try {
+            data.put("errorCode", errorCode);
+            data.put("description", description);
+            data.put("url", failingUrl);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        this.appView.postMessage("onReceivedError", data);
+    }
+
+    /**
+     * Notify the host application that an SSL error occurred while loading a resource.
+     * The host application must call either handler.cancel() or handler.proceed().
+     * Note that the decision may be retained for use in response to future SSL errors.
+     * The default behavior is to cancel the load.
+     *
+     * @param view          The WebView that is initiating the callback.
+     * @param handler       An SslErrorHandler object that will handle the user's response.
+     * @param error         The SSL error object.
+     */
+    @TargetApi(8)
+    @Override
+    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+
+        final String packageName = this.cordova.getActivity().getPackageName();
+        final PackageManager pm = this.cordova.getActivity().getPackageManager();
+
+        ApplicationInfo appInfo;
+        try {
+            appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
+            if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+                // debug = true
+                handler.proceed();
+                return;
+            } else {
+                // debug = false
+                super.onReceivedSslError(view, handler, error);
+            }
+        } catch (NameNotFoundException e) {
+            // When it doubt, lock it out!
+            super.onReceivedSslError(view, handler, error);
+        }
+    }
+
+
+    /**
+     * Sets the authentication token.
+     *
+     * @param authenticationToken
+     * @param host
+     * @param realm
+     */
+    public void setAuthenticationToken(AuthenticationToken authenticationToken, String host, String realm) {
+        if (host == null) {
+            host = "";
+        }
+        if (realm == null) {
+            realm = "";
+        }
+        this.authenticationTokens.put(host.concat(realm), authenticationToken);
+    }
+
+    /**
+     * Removes the authentication token.
+     *
+     * @param host
+     * @param realm
+     *
+     * @return the authentication token or null if did not exist
+     */
+    public AuthenticationToken removeAuthenticationToken(String host, String realm) {
+        return this.authenticationTokens.remove(host.concat(realm));
+    }
+
+    /**
+     * Gets the authentication token.
+     *
+     * In order it tries:
+     * 1- host + realm
+     * 2- host
+     * 3- realm
+     * 4- no host, no realm
+     *
+     * @param host
+     * @param realm
+     *
+     * @return the authentication token
+     */
+    public AuthenticationToken getAuthenticationToken(String host, String realm) {
+        AuthenticationToken token = null;
+        token = this.authenticationTokens.get(host.concat(realm));
+
+        if (token == null) {
+            // try with just the host
+            token = this.authenticationTokens.get(host);
+
+            // Try the realm
+            if (token == null) {
+                token = this.authenticationTokens.get(realm);
+            }
+
+            // if no host found, just query for default
+            if (token == null) {
+                token = this.authenticationTokens.get("");
+            }
+        }
+
+        return token;
+    }
+
+    /**
+     * Clear all authentication tokens.
+     */
+    public void clearAuthenticationTokens() {
+        this.authenticationTokens.clear();
+    }
+
+    @Override
+    public void onReceivedError(CordovaWebView me, int i, String string,
+            String url) {
+        // Only deal with this if we're dealing with a proper classic webview.
+        if(WebView.class.isInstance(me))
+        {
+            this.onReceivedError(me, i, string, url);
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/19f76d34/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 7d81825..6f66c52 100755
--- a/framework/src/org/apache/cordova/CordovaActivity.java
+++ b/framework/src/org/apache/cordova/CordovaActivity.java
@@ -147,63 +147,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
 
     private Object LOG_TAG;
 
-    /**
-    * Sets the authentication token.
-    *
-    * @param authenticationToken
-    * @param host
-    * @param realm
-    */
-    public void setAuthenticationToken(AuthenticationToken authenticationToken, String host, String realm) {
-        if (this.appView != null && this.appView.viewClient != null) {
-            this.appView.viewClient.setAuthenticationToken(authenticationToken, host, realm);
-        }
-    }
-
-    /**
-     * Removes the authentication token.
-     *
-     * @param host
-     * @param realm
-     *
-     * @return the authentication token or null if did not exist
-     */
-    public AuthenticationToken removeAuthenticationToken(String host, String realm) {
-        if (this.appView != null && this.appView.viewClient != null) {
-            return this.appView.viewClient.removeAuthenticationToken(host, realm);
-        }
-        return null;
-    }
-
-    /**
-     * Gets the authentication token.
-     *
-     * In order it tries:
-     * 1- host + realm
-     * 2- host
-     * 3- realm
-     * 4- no host, no realm
-     *
-     * @param host
-     * @param realm
-     *
-     * @return the authentication token
-     */
-    public AuthenticationToken getAuthenticationToken(String host, String realm) {
-        if (this.appView != null && this.appView.viewClient != null) {
-            return this.appView.viewClient.getAuthenticationToken(host, realm);
-        }
-        return null;
-    }
-
-    /**
-     * Clear all authentication tokens.
-     */
-    public void clearAuthenticationTokens() {
-        if (this.appView != null && this.appView.viewClient != null) {
-            this.appView.viewClient.clearAuthenticationTokens();
-        }
-    }
 
     /**
      * Called when the activity is first created.
@@ -269,7 +212,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
      * require a more specialized web view.
      */
     protected CordovaWebView makeWebView() {
-        return new CordovaWebView(CordovaActivity.this);
+        return (CordovaWebView) new AndroidWebView(CordovaActivity.this);
     }
 
     /**
@@ -282,9 +225,9 @@ public class CordovaActivity extends Activity implements CordovaInterface {
      */
     protected CordovaWebViewClient makeWebViewClient(CordovaWebView webView) {
         if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
-            return new CordovaWebViewClient(this, webView);
+            return (CordovaWebViewClient) new AndroidWebViewClient(this, webView);
         } else {
-            return new IceCreamCordovaWebViewClient(this, webView);
+            return (CordovaWebViewClient) new IceCreamCordovaWebViewClient(this, webView);
         }
     }
 
@@ -297,7 +240,7 @@ 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 (CordovaChromeClient) new AndroidChromeClient(this, webView);
     }
 
     /**
@@ -335,13 +278,14 @@ public class CordovaActivity extends Activity implements CordovaInterface {
 
         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);
+                //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(this.appView);
+        this.root.addView((View) this.appView);
         setContentView(this.root);
 
         // Clear cancel flag
@@ -408,17 +352,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
         this.splashscreenTime = time;
         this.loadUrl(url);
         
-        /*
-        // Init web view if not already done
-        if (this.appView == null) {
-            this.init();
-        }
-
-        this.splashscreenTime = time;
-        this.splashscreen = this.getIntegerProperty("SplashScreen", 0);
-        this.showSplashScreen(this.splashscreenTime);
-        this.appView.loadUrl(url, time);
-        */
     }
     
     /*
@@ -456,15 +389,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
 
 
     /**
-     * Cancel loadUrl before it has been loaded.
-     */
-    // TODO NO-OP
-    @Deprecated
-    public void cancelLoadUrl() {
-        this.cancelLoadUrl = true;
-    }
-
-    /**
      * Clear the resource cache.
      */
     public void clearCache() {
@@ -711,31 +635,18 @@ public class CordovaActivity extends Activity implements CordovaInterface {
         }
     }
 
-    /**
-     * @deprecated
-     * Add services to res/xml/plugins.xml instead.
-     *
-     * Add a class that implements a service.
-     *
-     * @param serviceType
-     * @param className
-     */
-    @Deprecated
-    public void addService(String serviceType, String className) {
-        if (this.appView != null && this.appView.pluginManager != null) {
-            this.appView.pluginManager.addService(serviceType, className);
-        }
-    }
 
     /**
      * Send JavaScript statement back to JavaScript.
      * (This is a convenience method)
      *
      * @param statement
+     * 
      */
     public void sendJavascript(String statement) {
         if (this.appView != null) {
-            this.appView.jsMessageQueue.addJavaScript(statement);
+            this.appView.addJavascript(statement);
+            //this.appView.jsMessageQueue.addJavaScript(statement);
         }
     }
 
@@ -814,7 +725,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
         super.onActivityResult(requestCode, resultCode, intent);
         Log.d(TAG, "Request code = " + requestCode);
         if (appView != null && requestCode == CordovaChromeClient.FILECHOOSER_RESULTCODE) {
-        	ValueCallback<Uri> mUploadMessage = this.appView.getWebChromeClient().getValueCallback();
+        	ValueCallback<Uri> mUploadMessage = ((CordovaChromeClient) this.appView.getWebChromeClient()).getValueCallback();
             Log.d(TAG, "did we get here?");
             if (null == mUploadMessage)
                 return;
@@ -829,7 +740,8 @@ public class CordovaActivity extends Activity implements CordovaInterface {
         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.pluginManager.getPlugin(initCallbackClass);
+            this.activityResultCallback = appView.getPlugin(initCallbackClass);
             callback = this.activityResultCallback;
         }
         if(callback != null) {


[11/12] android commit: Defer construction of client objects to WebView

Posted by ia...@apache.org.
Defer construction of client objects to WebView


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

Branch: refs/heads/pluggable_webview
Commit: 8e31ef7be6165d4566e2a27d1a72b9770db10ab9
Parents: f4555f7
Author: Ian Clelland <ic...@chromium.org>
Authored: Thu Apr 24 14:57:34 2014 -0400
Committer: Ian Clelland <ic...@chromium.org>
Committed: Tue Apr 29 22:50:12 2014 -0400

----------------------------------------------------------------------
 .../src/org/apache/cordova/AndroidWebView.java  | 27 +++++++++++++-------
 .../src/org/apache/cordova/CordovaActivity.java | 18 ++++++-------
 .../src/org/apache/cordova/CordovaWebView.java  |  4 +++
 3 files changed, 30 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/8e31ef7b/framework/src/org/apache/cordova/AndroidWebView.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/AndroidWebView.java b/framework/src/org/apache/cordova/AndroidWebView.java
index a940dd5..2603a86 100755
--- a/framework/src/org/apache/cordova/AndroidWebView.java
+++ b/framework/src/org/apache/cordova/AndroidWebView.java
@@ -166,8 +166,6 @@ public class AndroidWebView extends WebView implements CordovaWebView {
         {
             Log.d(TAG, "Your activity must implement CordovaInterface to work");
         }
-        this.setWebChromeClient((CordovaChromeClient) new AndroidChromeClient(this.cordova, this));
-        this.initWebViewClient(this.cordova);
         this.loadConfiguration();
         this.setup();
     }
@@ -190,7 +188,6 @@ public class AndroidWebView extends WebView implements CordovaWebView {
         {
             Log.d(TAG, "Your activity must implement CordovaInterface to work");
         }
-        this.setWebChromeClient((CordovaChromeClient) new AndroidChromeClient(this.cordova, this));
         this.loadConfiguration();
         this.setup();
     }
@@ -214,28 +211,40 @@ public class AndroidWebView extends WebView implements CordovaWebView {
         {
             Log.d(TAG, "Your activity must implement CordovaInterface to work");
         }
-        this.setWebChromeClient((CordovaChromeClient) new AndroidChromeClient(this.cordova));
-        this.initWebViewClient(this.cordova);
         this.loadConfiguration();
         this.setup();
     }
 
     /**
-     * set the WebViewClient, but provide special case handling for IceCreamSandwich.
+     * Create a default WebViewClient object for this webview. This can be overridden by the
+     * main application's CordovaActivity subclass.
+     *
+     * By default, it creates an AndroidWebViewClient, but we provide special case handling for
+     * IceCreamSandwich.
      */
-    private void initWebViewClient(CordovaInterface cordova) {
+    @Override
+    public CordovaWebViewClient makeWebViewClient() {
         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((CordovaWebViewClient) new AndroidWebViewClient(this.cordova, this));
+            return (CordovaWebViewClient) new AndroidWebViewClient(this.cordova, this);
         }
         else
         {
-            this.setWebViewClient((CordovaWebViewClient) new IceCreamCordovaWebViewClient(this.cordova, this));
+            return (CordovaWebViewClient) new IceCreamCordovaWebViewClient(this.cordova, this);
         }
     }
 
     /**
+     * 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);
+    }
+
+    /**
      * Initialize webview.
      */
     @SuppressWarnings("deprecation")

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/8e31ef7b/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 8931b51..01eff1c 100755
--- a/framework/src/org/apache/cordova/CordovaActivity.java
+++ b/framework/src/org/apache/cordova/CordovaActivity.java
@@ -248,29 +248,27 @@ public class CordovaActivity extends Activity implements CordovaInterface {
     /**
      * Construct the client for the default web view object.
      *
-     * This is intended to be overridable by subclasses of CordovaIntent which
-     * require a more specialized web view.
+     * 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) {
-        if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
-            return (CordovaWebViewClient) new AndroidWebViewClient(this, webView);
-        } else {
-            return (CordovaWebViewClient) new IceCreamCordovaWebViewClient(this, webView);
-        }
+        return webView.makeWebViewClient();
     }
 
     /**
      * Construct the chrome client for the default web view object.
      *
-     * This is intended to be overridable by subclasses of CordovaIntent which
-     * require a more specialized web view.
+     * 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 (CordovaChromeClient) new AndroidChromeClient(this, webView);
+        return webView.makeWebChromeClient();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/8e31ef7b/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 d23baee..a5496cf 100644
--- a/framework/src/org/apache/cordova/CordovaWebView.java
+++ b/framework/src/org/apache/cordova/CordovaWebView.java
@@ -19,6 +19,10 @@ public interface CordovaWebView {
 
     View getView();
 
+    CordovaWebViewClient makeWebViewClient();
+
+    CordovaChromeClient makeWebChromeClient();
+
     void setWebViewClient(CordovaWebViewClient webViewClient);
 
     void setWebChromeClient(CordovaChromeClient webChromeClient);


[04/12] android commit: Crosswalk runtime needs the two permissions to auto detect connection status.

Posted by ia...@apache.org.
Crosswalk runtime needs the two permissions to auto detect connection status.

See more details at: https://crosswalk-project.org/jira/browse/XWALK-1324


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

Branch: refs/heads/pluggable_webview
Commit: 4a67dd2e28aed257c85b75c11026ae7a2a19c2ad
Parents: bd806a3
Author: Ningxin Hu <ni...@intel.com>
Authored: Mon Apr 21 15:17:23 2014 +0800
Committer: Ian Clelland <ic...@chromium.org>
Committed: Tue Apr 29 22:50:11 2014 -0400

----------------------------------------------------------------------
 bin/templates/project/AndroidManifest.xml | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/4a67dd2e/bin/templates/project/AndroidManifest.xml
----------------------------------------------------------------------
diff --git a/bin/templates/project/AndroidManifest.xml b/bin/templates/project/AndroidManifest.xml
index b031b60..decb971 100644
--- a/bin/templates/project/AndroidManifest.xml
+++ b/bin/templates/project/AndroidManifest.xml
@@ -29,6 +29,8 @@
         />
 
     <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
 
     <application android:icon="@drawable/icon" android:label="@string/app_name"
         android:hardwareAccelerated="true">


[08/12] android commit: Add getView() API into CordovaWebView.

Posted by ia...@apache.org.
Add getView() API into CordovaWebView.

This API is to get the actual View.

The concrete webview implementation can use compositing instead of extending
underlying webview.


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

Branch: refs/heads/pluggable_webview
Commit: 8408da55ea2fa112b4faeec5ae70f5780eb4f4c0
Parents: 4a67dd2
Author: Ningxin Hu <ni...@intel.com>
Authored: Mon Apr 21 15:22:19 2014 +0800
Committer: Ian Clelland <ic...@chromium.org>
Committed: Tue Apr 29 22:50:11 2014 -0400

----------------------------------------------------------------------
 framework/src/org/apache/cordova/AndroidWebView.java  | 4 ++++
 framework/src/org/apache/cordova/CordovaActivity.java | 2 +-
 framework/src/org/apache/cordova/CordovaWebView.java  | 2 ++
 3 files changed, 7 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/8408da55/framework/src/org/apache/cordova/AndroidWebView.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/AndroidWebView.java b/framework/src/org/apache/cordova/AndroidWebView.java
index 00c4bb1..a940dd5 100755
--- a/framework/src/org/apache/cordova/AndroidWebView.java
+++ b/framework/src/org/apache/cordova/AndroidWebView.java
@@ -1078,4 +1078,8 @@ public class AndroidWebView extends WebView implements CordovaWebView {
         super.setLayoutParams(layoutParams);
     }
 
+    @Override
+    public View getView() {
+        return this;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/8408da55/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 a24555b..8931b51 100755
--- a/framework/src/org/apache/cordova/CordovaActivity.java
+++ b/framework/src/org/apache/cordova/CordovaActivity.java
@@ -315,7 +315,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
 
         // Add web view but make it invisible while loading URL
         this.appView.setVisibility(View.INVISIBLE);
-        this.root.addView((View) this.appView);
+        this.root.addView((View) this.appView.getView());
         setContentView(this.root);
 
         // Clear cancel flag

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/8408da55/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 f0d4a5f..d23baee 100644
--- a/framework/src/org/apache/cordova/CordovaWebView.java
+++ b/framework/src/org/apache/cordova/CordovaWebView.java
@@ -17,6 +17,8 @@ public interface CordovaWebView {
     Object pluginManager = null;
     Object jsMessageQueue = null;
 
+    View getView();
+
     void setWebViewClient(CordovaWebViewClient webViewClient);
 
     void setWebChromeClient(CordovaChromeClient webChromeClient);


[10/12] android commit: w00t! Managed to get XWalk to work. Next Step: Make it installable like a Cordova Plugin!

Posted by ia...@apache.org.
w00t! Managed to get XWalk to work.  Next Step: Make it installable
like a Cordova Plugin!


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

Branch: refs/heads/pluggable_webview
Commit: c17503ab784881419b5da0ac70bc47b95c13ac89
Parents: 19f76d3
Author: Joe Bowser <bo...@apache.org>
Authored: Fri Mar 7 15:03:22 2014 -0800
Committer: Ian Clelland <ic...@chromium.org>
Committed: Tue Apr 29 22:50:11 2014 -0400

----------------------------------------------------------------------
 framework/project.properties                    |    1 +
 framework/res/xml/config.xml                    |    1 +
 .../src/org/apache/cordova/AndroidWebView.java  |    7 +
 .../src/org/apache/cordova/CordovaActivity.java |   30 +
 .../src/org/apache/cordova/CordovaWebView.java  |    2 +
 .../src/org/apache/cordova/ExposedJsApi.java    |    2 +-
 .../apache/cordova/NativeToJsMessageQueue.java  |    2 +-
 .../src/org/apache/cordova/ScrollEvent.java     |    2 +-
 .../engine/crosswalk/XWalkCordovaWebView.java   | 1147 ++++++++++++++++++
 .../crosswalk/XWalkCordovaWebViewClient.java    |  636 ++++++++++
 .../crosswalk/XwalkCordovaChromeClient.java     |  428 +++++++
 .../CordovaXWalkCoreExtensionBridge.java        |   17 +
 12 files changed, 2272 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c17503ab/framework/project.properties
----------------------------------------------------------------------
diff --git a/framework/project.properties b/framework/project.properties
index 9fe04f3..5edb77d 100644
--- a/framework/project.properties
+++ b/framework/project.properties
@@ -14,3 +14,4 @@ target=android-19
 apk-configurations=
 renderscript.opt.level=O0
 android.library=true
+android.library.reference.1=../../crosswalk-cordova-android/framework/xwalk_core_library

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c17503ab/framework/res/xml/config.xml
----------------------------------------------------------------------
diff --git a/framework/res/xml/config.xml b/framework/res/xml/config.xml
index 24e5725..d6a1957 100644
--- a/framework/res/xml/config.xml
+++ b/framework/res/xml/config.xml
@@ -36,6 +36,7 @@
     <content src="index.html" />
 
     <preference name="loglevel" value="DEBUG" />
+        
     <!--
       <preference name="splashscreen" value="resourceName" />
       <preference name="backgroundColor" value="0xFFF" />

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c17503ab/framework/src/org/apache/cordova/AndroidWebView.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/AndroidWebView.java b/framework/src/org/apache/cordova/AndroidWebView.java
index 993629a..ed4c02c 100755
--- a/framework/src/org/apache/cordova/AndroidWebView.java
+++ b/framework/src/org/apache/cordova/AndroidWebView.java
@@ -130,6 +130,7 @@ public class AndroidWebView extends WebView implements CordovaWebView {
             ViewGroup.LayoutParams.MATCH_PARENT,
             Gravity.CENTER);
     
+    
     /**
      * Constructor.
      *
@@ -1071,4 +1072,10 @@ public class AndroidWebView extends WebView implements CordovaWebView {
         return this.pluginManager;
     }
 
+    @Override
+    public void setLayoutParams(
+            android.widget.FrameLayout.LayoutParams layoutParams) {
+        super.setLayoutParams(layoutParams);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c17503ab/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 6f66c52..a24555b 100755
--- a/framework/src/org/apache/cordova/CordovaActivity.java
+++ b/framework/src/org/apache/cordova/CordovaActivity.java
@@ -18,6 +18,8 @@
 */
 package org.apache.cordova;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.concurrent.ExecutorService;
@@ -212,6 +214,34 @@ public class CordovaActivity extends Activity implements CordovaInterface {
      * require a more specialized web view.
      */
     protected CordovaWebView makeWebView() {
+        String r = this.getStringProperty("webView", "org.apache.cordova.AndroidWebView");
+
+        try {
+            Class webViewClass = Class.forName(r);
+            Constructor<CordovaWebView> [] webViewConstructors = webViewClass.getConstructors();
+            
+            
+            if(CordovaWebView.class.isAssignableFrom(webViewClass)) {
+                CordovaWebView webView =  (CordovaWebView) webViewConstructors[0].newInstance(this);
+                return webView;
+            }
+            else
+            {
+                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(CordovaActivity.this);
     }
 

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c17503ab/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 737ee3a..f0d4a5f 100644
--- a/framework/src/org/apache/cordova/CordovaWebView.java
+++ b/framework/src/org/apache/cordova/CordovaWebView.java
@@ -107,4 +107,6 @@ public interface CordovaWebView {
     void sendPluginResult(PluginResult cr, String callbackId);
 
     PluginManager getPluginManager();
+
+    void setLayoutParams(android.widget.FrameLayout.LayoutParams layoutParams);
 }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c17503ab/framework/src/org/apache/cordova/ExposedJsApi.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/ExposedJsApi.java b/framework/src/org/apache/cordova/ExposedJsApi.java
index fde5722..103e546 100755
--- a/framework/src/org/apache/cordova/ExposedJsApi.java
+++ b/framework/src/org/apache/cordova/ExposedJsApi.java
@@ -27,7 +27,7 @@ import org.json.JSONException;
  * an equivalent entry in CordovaChromeClient.java, and be added to
  * cordova-js/lib/android/plugin/android/promptbasednativeapi.js
  */
-/* package */ class ExposedJsApi {
+public /* package */ class ExposedJsApi {
     
     private PluginManager pluginManager;
     private NativeToJsMessageQueue jsMessageQueue;

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c17503ab/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/NativeToJsMessageQueue.java b/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
index 5d0c061..c8a3b06 100755
--- a/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
+++ b/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
@@ -44,7 +44,7 @@ public class NativeToJsMessageQueue {
 
     // Disable URL-based exec() bridge by default since it's a bit of a
     // security concern.
-    static final boolean ENABLE_LOCATION_CHANGE_EXEC_MODE = false;
+    public static final boolean ENABLE_LOCATION_CHANGE_EXEC_MODE = false;
         
     // Disable sending back native->JS messages during an exec() when the active
     // exec() is asynchronous. Set this to true when running bridge benchmarks.

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c17503ab/framework/src/org/apache/cordova/ScrollEvent.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/ScrollEvent.java b/framework/src/org/apache/cordova/ScrollEvent.java
index 5546613..de1de8d 100644
--- a/framework/src/org/apache/cordova/ScrollEvent.java
+++ b/framework/src/org/apache/cordova/ScrollEvent.java
@@ -43,7 +43,7 @@ public class ScrollEvent {
      * @param view
      */
     
-    ScrollEvent(int nx, int ny, int x, int y, View view)
+    public ScrollEvent(int nx, int ny, int x, int y, View view)
     {
         l = x; y = t; nl = nx; nt = ny;
         targetView = view;

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c17503ab/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java b/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java
new file mode 100755
index 0000000..73195fe
--- /dev/null
+++ b/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java
@@ -0,0 +1,1147 @@
+/*
+       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.engine.crosswalk;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Locale;
+
+import org.apache.cordova.Config;
+import org.apache.cordova.CordovaChromeClient;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaResourceApi;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.CordovaWebViewClient;
+import org.apache.cordova.LOG;
+import org.apache.cordova.NativeToJsMessageQueue;
+import org.apache.cordova.ExposedJsApi;
+import org.apache.cordova.PluginManager;
+import org.apache.cordova.PluginResult;
+import org.apache.cordova.ScrollEvent;
+import org.json.JSONException;
+import org.xwalk.core.WebBackForwardList;
+import org.xwalk.core.WebHistoryItem;
+import org.xwalk.core.XWalkSettings;
+import org.xwalk.core.XWalkView;
+import org.xwalk.core.XWalkWebChromeClient;
+import org.xwalk.runtime.extension.XWalkExtensionManager;
+
+import android.app.Activity;
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+import android.webkit.WebChromeClient.CustomViewCallback;
+//import android.webkit.WebBackForwardList;
+//import android.webkit.WebHistoryItem;
+//import android.webkit.WebChromeClient;
+//import android.webkit.WebSettings;
+//import android.webkit.WebView;
+//import android.webkit.WebSettings.LayoutAlgorithm;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout.LayoutParams;
+
+/*
+ * This class is our web view.
+ *
+ * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
+ * @see <a href="http://developer.android.com/reference/android/webkit/WebView.html">WebView</a>
+ */
+public class XWalkCordovaWebView extends XWalkView implements CordovaWebView {
+
+    public static final String TAG = "CordovaWebView";
+    public static final String CORDOVA_VERSION = "3.3.0";
+
+    private ArrayList<Integer> keyDownCodes = new ArrayList<Integer>();
+    private ArrayList<Integer> keyUpCodes = new ArrayList<Integer>();
+
+    public PluginManager pluginManager;
+    private boolean paused;
+
+    private XWalkExtensionManager extensionManager;
+
+    private BroadcastReceiver receiver;
+
+
+    /** Activities and other important classes **/
+    private CordovaInterface cordova;
+    XWalkCordovaWebViewClient viewClient;
+    @SuppressWarnings("unused")
+    private XwalkCordovaChromeClient chromeClient;
+
+    private String url;
+
+    // Flag to track that a loadUrl timeout occurred
+    int loadUrlTimeout = 0;
+
+    private boolean bound;
+
+    private boolean handleButton = false;
+    
+    private long lastMenuEventTime = 0;
+
+    NativeToJsMessageQueue jsMessageQueue;
+    ExposedJsApi exposedJsApi;
+
+    /** custom view created by the browser (a video player for example) */
+    private View mCustomView;
+    private XWalkWebChromeClient.CustomViewCallback mCustomViewCallback;
+
+    private ActivityResult mResult = null;
+
+    private CordovaResourceApi resourceApi;
+
+    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,
+            ViewGroup.LayoutParams.MATCH_PARENT,
+            Gravity.CENTER);
+    
+    /**
+     * Constructor.
+     *
+     * @param context
+     */
+    public XWalkCordovaWebView(Context context) {
+        super(context, (Activity)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();
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param context
+     * @param attrs
+     */
+    public XWalkCordovaWebView(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 XwalkCordovaChromeClient(this.cordova, this));
+        this.initWebViewClient(this.cordova);
+        this.loadConfiguration();
+        this.setup();
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param context
+     * @param attrs
+     * @param defStyle
+     *
+     */
+    public XWalkCordovaWebView(Context context, AttributeSet attrs, int defStyle) {
+        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 XwalkCordovaChromeClient(this.cordova, this));
+        this.loadConfiguration();
+        this.setup();
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param context
+     * @param attrs
+     * @param defStyle
+     * @param privateBrowsing
+     */
+    @TargetApi(11)
+    public XWalkCordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) {
+        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 XwalkCordovaChromeClient(this.cordova));
+        this.initWebViewClient(this.cordova);
+        this.loadConfiguration();
+        this.setup();
+    }
+
+ 
+    private void initWebViewClient(CordovaInterface cordova) {
+            this.setWebViewClient(new XWalkCordovaWebViewClient(this.cordova, this));
+    }
+
+    /**
+     * Initialize webview.
+     */
+    @SuppressWarnings("deprecation")
+    @SuppressLint("NewApi")
+    private void setup() {
+        this.setInitialScale(0);
+        this.setVerticalScrollBarEnabled(false);
+        if (shouldRequestFocusOnInit()) {
+			this.requestFocusFromTouch();
+		}
+		// Enable JavaScript
+        XWalkSettings settings = this.getSettings();
+        settings.setJavaScriptEnabled(true);
+        settings.setJavaScriptCanOpenWindowsAutomatically(true);
+        // nhu: N/A
+        //settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
+
+        //We don't save any form data in the application
+        // nhu: N/A
+        //settings.setSaveFormData(false);
+        //settings.setSavePassword(false);
+        
+        // Jellybean rightfully tried to lock this down. Too bad they didn't give us a whitelist
+        // while we do this
+        if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
+            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();
+        //settings.setDatabaseEnabled(true);
+        //TODO: bring it back when it's ready in the XWalk.
+        //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)
+            {
+                //TODO: bring it back when it's ready in the XWalk.
+                //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);
+
+        // Enable DOM storage
+        settings.setDomStorageEnabled(true);
+
+        // Enable built-in geolocation
+        settings.setGeolocationEnabled(true);
+        
+        // Enable AppCache
+        // Fix for CB-2282
+        // nhu: N/A
+        //settings.setAppCacheMaxSize(5 * 1048576);
+        String pathToCache = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
+        settings.setAppCachePath(pathToCache);
+        settings.setAppCacheEnabled(true);
+
+        pluginManager = new PluginManager(this, this.cordova);
+        extensionManager = new XWalkExtensionManager(this.cordova.getActivity(), this.cordova.getActivity());
+        extensionManager.loadExtensions();
+        jsMessageQueue = new NativeToJsMessageQueue(this, cordova);
+        exposedJsApi = new ExposedJsApi(pluginManager, jsMessageQueue);
+        resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
+        exposeJsInterface();
+    }
+
+	/**
+	 * Override this method to decide whether or not you need to request the
+	 * focus when your application start
+	 * 
+	 * @return true unless this method is overriden to return a different value
+	 */
+    protected boolean shouldRequestFocusOnInit() {
+		return true;
+	}
+
+    private void exposeJsInterface() {
+        int SDK_INT = Build.VERSION.SDK_INT;
+        boolean isHoneycomb = (SDK_INT >= Build.VERSION_CODES.HONEYCOMB && SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2);
+        if (isHoneycomb || (SDK_INT < Build.VERSION_CODES.GINGERBREAD)) {
+            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
+            // use the prompt bridge instead.
+            return;            
+        } else if (SDK_INT < Build.VERSION_CODES.HONEYCOMB && Build.MANUFACTURER.equals("unknown")) {
+            // addJavascriptInterface crashes on the 2.3 emulator.
+            Log.i(TAG, "Disabled addJavascriptInterface() bridge callback due to a bug on the 2.3 emulator");
+            return;
+        }
+        this.addJavascriptInterface(exposedJsApi, "_cordovaNative");
+    }
+
+    /**
+     * Set the WebViewClient.
+     *
+     * @param client
+     */
+    public void setWebViewClient(XWalkCordovaWebViewClient client) {
+        this.viewClient = client;
+        super.setXWalkClient(client);
+    }
+
+    /**
+     * Set the WebChromeClient.
+     *
+     * @param client
+     */
+    public void setWebChromeClient(XwalkCordovaChromeClient client) {
+        this.chromeClient = client;
+        super.setXWalkWebChromeClient(client);
+    }
+    
+    public XwalkCordovaChromeClient 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 {
+
+            String initUrl = this.getProperty("url", null);
+
+            // If first page of app, then set URL to load to be the one passed in
+            if (initUrl == null) {
+                this.loadUrlIntoView(url);
+            }
+            // Otherwise use the URL specified in the activity's extras bundle
+            else {
+                this.loadUrlIntoView(initUrl);
+            }
+        }
+    }
+
+    /**
+     * 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 loadUrl(final String url, int time) {
+        String initUrl = this.getProperty("url", null);
+
+        // If first page of app, then set URL to load to be the one passed in
+        if (initUrl == null) {
+            this.loadUrlIntoView(url, time);
+        }
+        // Otherwise use the URL specified in the activity's extras bundle
+        else {
+            this.loadUrlIntoView(initUrl);
+        }
+    }
+
+    /**
+     * Load the url into the webview.
+     *
+     * @param url
+     */
+    public void loadUrlIntoView(final String url) {
+        LOG.d(TAG, ">>> loadUrl(" + url + ")");
+
+        this.url = url;
+        this.pluginManager.init();
+
+
+        // Create a timeout timer for loadUrl
+        final XWalkCordovaWebView me = this;
+        final int currentLoadUrlTimeout = me.loadUrlTimeout;
+        final int loadUrlTimeoutValue = Integer.parseInt(this.getProperty("LoadUrlTimeoutValue", "20000"));
+
+        // Timeout error method
+        final Runnable loadError = new Runnable() {
+            public void run() {
+                me.stopLoading();
+                LOG.e(TAG, "CordovaWebView: TIMEOUT ERROR!");
+                if (viewClient != null) {
+                    viewClient.onReceivedError((CordovaWebView) me, -6, "The connection to the server was unsuccessful.", url);
+                }
+            }
+        };
+
+        // Timeout timer method
+        final Runnable timeoutCheck = new Runnable() {
+            public void run() {
+                try {
+                    synchronized (this) {
+                        wait(loadUrlTimeoutValue);
+                    }
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+
+                // If timeout, then stop loading and handle error
+                if (me.loadUrlTimeout == currentLoadUrlTimeout) {
+                    me.cordova.getActivity().runOnUiThread(loadError);
+                }
+            }
+        };
+
+        // Load url
+        this.cordova.getActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                Thread thread = new Thread(timeoutCheck);
+                thread.start();
+                me.loadUrlNow(url);
+            }
+        });
+    }
+
+    /**
+     * Load URL in webview.
+     *
+     * @param url
+     */
+    public void loadUrlNow(String url) {
+        if (LOG.isLoggable(LOG.DEBUG) && !url.startsWith("javascript:")) {
+            LOG.d(TAG, ">>> loadUrlNow()");
+        }
+        if (url.startsWith("file://") || url.startsWith("javascript:") || Config.isUrlWhiteListed(url)) {
+            super.loadUrl(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
+     */
+    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);
+    }
+    
+    
+    public void onScrollChanged(int l, int t, int oldl, int oldt)
+    {
+        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);
+    }
+    
+    /**
+     * Send JavaScript statement back to JavaScript.
+     * (This is a convenience method)
+     *
+     * @param statement
+     */
+    public void sendJavascript(String statement) {
+        this.jsMessageQueue.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);
+    }
+
+    /**
+     * 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)
+     *
+     * @return true if we went back, false if we are already at top
+     */
+    public boolean backHistory() {
+
+        // Check webview first to see if there is a history
+        // This is needed to support curPage#diffLink, since they are added to appView's history, but not our history url array (JQMobile behavior)
+        if (super.canGoBack()) {
+            printBackForwardList();
+            super.goBack();
+            
+            return true;
+        }
+        return false;
+    }
+
+
+    /**
+     * Load the specified URL in the Cordova webview or a new browser instance.
+     *
+     * NOTE: If openExternal is false, only URLs listed in whitelist can be loaded.
+     *
+     * @param url           The url to load.
+     * @param openExternal  Load url in browser instead of Cordova webview.
+     * @param clearHistory  Clear the history stack, so new page becomes top of history
+     * @param params        Parameters for new app
+     */
+    public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap<String, Object> params) {
+        LOG.d(TAG, "showWebPage(%s, %b, %b, HashMap", url, openExternal, clearHistory);
+
+        // If clearing history
+        if (clearHistory) {
+            this.clearHistory();
+        }
+
+        // If loading into our webview
+        if (!openExternal) {
+
+            // Make sure url is in whitelist
+            if (url.startsWith("file://") || Config.isUrlWhiteListed(url)) {
+                // TODO: What about params?
+                // Load new URL
+                this.loadUrl(url);
+            }
+            // Load in default viewer if not
+            else {
+                LOG.w(TAG, "showWebPage: Cannot load URL into webview since it is not in white list.  Loading into browser instead. (URL=" + url + ")");
+                try {
+                    Intent intent = new Intent(Intent.ACTION_VIEW);
+                    intent.setData(Uri.parse(url));
+                    cordova.getActivity().startActivity(intent);
+                } catch (android.content.ActivityNotFoundException e) {
+                    LOG.e(TAG, "Error loading url " + url, e);
+                }
+            }
+        }
+
+        // Load in default view intent
+        else {
+            try {
+                Intent intent = new Intent(Intent.ACTION_VIEW);
+                intent.setData(Uri.parse(url));
+                cordova.getActivity().startActivity(intent);
+            } catch (android.content.ActivityNotFoundException e) {
+                LOG.e(TAG, "Error loading url " + url, e);
+            }
+        }
+    }
+
+    /**
+     * 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.
+     *
+     * @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
+     */
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event)
+    {
+        if(keyDownCodes.contains(keyCode))
+        {
+            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
+                    // only override default behavior is event bound
+                    LOG.d(TAG, "Down Key Hit");
+                    this.loadUrl("javascript:cordova.fireDocumentEvent('volumedownbutton');");
+                    return true;
+            }
+            // If volumeup key
+            else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
+                    LOG.d(TAG, "Up Key Hit");
+                    this.loadUrl("javascript:cordova.fireDocumentEvent('volumeupbutton');");
+                    return true;
+            }
+            else
+            {
+                return super.onKeyDown(keyCode, event);
+            }
+        }
+        else if(keyCode == KeyEvent.KEYCODE_BACK)
+        {
+            return !(this.startOfHistory()) || this.bound;
+        }
+        else if(keyCode == KeyEvent.KEYCODE_MENU)
+        {
+            //How did we get here?  Is there a childView?
+            View childView = (View) this.getFocusedChild();
+            if(childView != null)
+            {
+                //Make sure we close the keyboard if it's present
+                InputMethodManager imm = (InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+                imm.hideSoftInputFromWindow(childView.getWindowToken(), 0);
+                cordova.getActivity().openOptionsMenu();
+                return true;
+            } else {
+                return super.onKeyDown(keyCode, event);
+            }
+        }
+        
+        return super.onKeyDown(keyCode, event);
+    }
+    
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event)
+    {
+        // If back key
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            // A custom view is currently displayed  (e.g. playing a video)
+            if (this.isFullscreen()) {
+                this.exitFullscreen();
+                return true;
+            } else if (mCustomView != null) {
+                this.hideCustomView();
+                return true;
+            } else {
+                // The webview is currently displayed
+                // If back key is bound, then send event to JavaScript
+                if (this.bound) {
+                    this.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');");
+                    return true;
+                } else {
+                    // If not bound
+                    // Go to previous page in webview if it is possible to go back
+                    if (this.backHistory()) {
+                        return true;
+                    }
+                    // If not, then invoke default behaviour
+                    else {
+                        //this.activityState = ACTIVITY_EXITING;
+                    	//return false;
+                    	// If they hit back button when app is initializing, app should exit instead of hang until initilazation (CB2-458)
+                    	this.cordova.getActivity().finish();
+                    	return false;
+                    }
+                }
+            }
+        }
+        // Legacy
+        else if (keyCode == KeyEvent.KEYCODE_MENU) {
+            if (this.lastMenuEventTime < event.getEventTime()) {
+                this.loadUrl("javascript:cordova.fireDocumentEvent('menubutton');");
+            }
+            this.lastMenuEventTime = event.getEventTime();
+            return super.onKeyUp(keyCode, event);
+        }
+        // If search key
+        else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
+            this.loadUrl("javascript:cordova.fireDocumentEvent('searchbutton');");
+            return true;
+        }
+        else if(keyUpCodes.contains(keyCode))
+        {
+            //What the hell should this do?
+            return super.onKeyUp(keyCode, event);
+        }
+
+        //Does webkit change this behavior?
+        return super.onKeyUp(keyCode, event);
+    }
+
+    
+    public void bindButton(boolean override)
+    {
+        this.bound = override;
+    }
+
+    public void bindButton(String button, boolean override) {
+        // TODO Auto-generated method stub
+        if (button.compareTo("volumeup")==0) {
+          keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_UP);
+        }
+        else if (button.compareTo("volumedown")==0) {
+          keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_DOWN);
+        }
+      }
+
+    public void bindButton(int keyCode, boolean keyDown, boolean override) {
+       if(keyDown)
+       {
+           keyDownCodes.add(keyCode);
+       }
+       else
+       {
+           keyUpCodes.add(keyCode);
+       }
+    }
+
+    public boolean isBackButtonBound()
+    {
+        return this.bound;
+    }
+    
+    public void handlePause(boolean keepRunning)
+    {
+        LOG.d(TAG, "Handle the pause");
+        // Send pause event to JavaScript
+        this.loadUrl("javascript:try{cordova.fireDocumentEvent('pause');}catch(e){console.log('exception firing pause event from native');};");
+
+        // Forward to plugins
+        if (this.pluginManager != null) {
+            this.pluginManager.onPause(keepRunning);
+        }
+
+        if (this.extensionManager != null) {
+            this.extensionManager.onPause();
+        }
+
+        // If app doesn't want to run in background
+        if (!keepRunning) {
+            // 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
+        if (this.pluginManager != null) {
+            this.pluginManager.onResume(keepRunning);
+        }
+
+        if (this.extensionManager != null) {
+            this.extensionManager.onResume();
+        }
+
+        // Resume JavaScript timers (including setInterval)
+        this.resumeTimers();
+        paused = false;
+    }
+    
+    public void handleDestroy()
+    {
+        // Send destroy event to JavaScript
+        this.loadUrl("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};");
+
+        // Load blank page so that JavaScript onunload is called
+        this.loadUrl("about:blank");
+
+        // Forward to plugins
+        if (this.pluginManager != null) {
+            this.pluginManager.onDestroy();
+        }
+
+        if (this.extensionManager != null) {
+            this.extensionManager.onDestroy();
+        }
+        
+        // unregister the receiver
+        if (this.receiver != null) {
+            try {
+                this.cordova.getActivity().unregisterReceiver(this.receiver);
+            } catch (Exception e) {
+                Log.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e);
+            }
+        }
+    }
+    
+    public void onNewIntent(Intent intent)
+    {
+        //Forward to plugins
+        if (this.pluginManager != null) {
+            this.pluginManager.onNewIntent(intent);
+        }
+    }
+    
+    public boolean isPaused()
+    {
+        return paused;
+    }
+
+    public boolean hadKeyEvent() {
+        return handleButton;
+    }
+
+    // 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)
+    private static class Level16Apis {
+        static void enableUniversalAccess(XWalkSettings settings) {
+            settings.setAllowUniversalAccessFromFileURLs(true);
+        }
+    }
+    
+    public void printBackForwardList() {
+        WebBackForwardList currentList = this.copyBackForwardList();
+        int currentSize = currentList.getSize();
+        for(int i = 0; i < currentSize; ++i)
+        {
+            WebHistoryItem item = currentList.getItemAtIndex(i);
+            String url = item.getUrl();
+            LOG.d(TAG, "The URL at index: " + Integer.toString(i) + " is " + url );
+        }
+    }
+    
+    
+    //Can Go Back is BROKEN!
+    public boolean startOfHistory()
+    {
+        WebBackForwardList currentList = this.copyBackForwardList();
+        WebHistoryItem item = currentList.getItemAtIndex(0);
+        if( item!=null){	// Null-fence in case they haven't called loadUrl yet (CB-2458)
+	        String url = item.getUrl();
+	        String currentUrl = this.getUrl();
+	        LOG.d(TAG, "The current URL is: " + currentUrl);
+	        LOG.d(TAG, "The URL at item 0 is: " + url);
+	        return currentUrl.equals(url);
+        }
+        return false;
+    }
+
+    public void showCustomView(View view, XWalkWebChromeClient.CustomViewCallback callback) {
+        // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
+        Log.d(TAG, "showing Custom View");
+        // if a view already exists then immediately terminate the new one
+        if (mCustomView != null) {
+            callback.onCustomViewHidden();
+            return;
+        }
+        
+        // Store the view and its callback for later (to kill it properly)
+        mCustomView = view;
+        mCustomViewCallback = callback;
+        
+        // Add the custom view to its container.
+        ViewGroup parent = (ViewGroup) this.getParent();
+        parent.addView(view, COVER_SCREEN_GRAVITY_CENTER);
+        
+        // Hide the content view.
+        this.setVisibility(View.GONE);
+        
+        // Finally show the custom view container.
+        parent.setVisibility(View.VISIBLE);
+        parent.bringToFront();
+    }
+
+    public void hideCustomView() {
+        // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
+        Log.d(TAG, "Hidding Custom View");
+        if (mCustomView == null) return;
+
+        // Hide the custom view.
+        mCustomView.setVisibility(View.GONE);
+        
+        // Remove the custom view from its container.
+        ViewGroup parent = (ViewGroup) this.getParent();
+        parent.removeView(mCustomView);
+        mCustomView = null;
+        mCustomViewCallback.onCustomViewHidden();
+        
+        // Show the content view.
+        this.setVisibility(View.VISIBLE);
+    }
+    
+    /**
+     * if the video overlay is showing then we need to know 
+     * as it effects back button handling
+     * 
+     * @return true if custom view is showing
+     */
+    public boolean isCustomViewShowing() {
+        return mCustomView != null;
+    }
+    
+    public WebBackForwardList restoreState(Bundle savedInstanceState)
+    {
+        WebBackForwardList myList = super.restoreState(savedInstanceState);
+        Log.d(TAG, "WebView restoration crew now restoring!");
+        //Initialize the plugin manager once more
+        this.pluginManager.init();
+        return myList;
+    }
+
+    public void storeResult(int requestCode, int resultCode, Intent intent) {
+        mResult = new ActivityResult(requestCode, resultCode, intent);
+    }
+    
+    public CordovaResourceApi getResourceApi() {
+        return resourceApi;
+    }
+
+    @Override
+    public void setWebViewClient(CordovaWebViewClient webViewClient) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void setWebChromeClient(CordovaChromeClient webChromeClient) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void setId(int i) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void setLayoutParams(LayoutParams layoutParams) {
+        // TODO Figure out how the XWalk gets laid out.  This is goofy! 
+    }
+
+    @Override
+    public void setVisibility(int invisible) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public boolean canGoBack() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void clearCache(boolean b) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void clearHistory() {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void addJavascript(String statement) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public CordovaPlugin getPlugin(String initCallbackClass) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public View getFocusedChild() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public String exec(String service, String action, String callbackId,
+            String message) throws JSONException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void setNativeToJsBridgeMode(int parseInt) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public String retrieveJsMessages(boolean equals) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void showCustomView(View view, CustomViewCallback callback) {
+        // TODO Auto-generated method stub
+        
+    }
+
+
+
+    @Override
+    public boolean onOverrideUrlLoading(String url) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void resetJsMessageQueue() {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void onReset() {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public int getVisibility() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void incUrlTimeout() {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void setOverScrollMode(int overScrollNever) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void setNetworkAvailable(boolean online) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public PluginManager getPluginManager() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void setLayoutParams(
+            android.widget.LinearLayout.LayoutParams layoutParams) {
+        // TODO Auto-generated method stub
+        
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c17503ab/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebViewClient.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebViewClient.java b/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebViewClient.java
new file mode 100755
index 0000000..262ae91
--- /dev/null
+++ b/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebViewClient.java
@@ -0,0 +1,636 @@
+/*
+       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.engine.crosswalk;
+
+import java.io.ByteArrayInputStream;
+import java.util.Hashtable;
+
+import org.apache.cordova.AuthenticationToken;
+import org.apache.cordova.Config;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.CordovaWebViewClient;
+import org.apache.cordova.LOG;
+import org.apache.cordova.NativeToJsMessageQueue;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.annotation.TargetApi;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.net.http.SslError;
+import android.util.Log;
+import android.view.View;
+//import android.webkit.HttpAuthHandler;
+//import android.webkit.SslErrorHandler;
+import android.webkit.WebResourceResponse;
+
+
+
+
+
+//import android.webkit.WebView;
+//import android.webkit.WebViewClient;
+import org.chromium.net.NetError;
+import org.xwalk.core.XWalkView;
+import org.xwalk.core.XWalkClient;
+import org.xwalk.core.XWalkHttpAuthHandler;
+import org.xwalk.core.SslErrorHandler;
+
+/**
+ * This class is the WebViewClient that implements callbacks for our web view.
+ * The kind of callbacks that happen here are regarding the rendering of the
+ * document instead of the chrome surrounding it, such as onPageStarted(), 
+ * shouldOverrideUrlLoading(), etc. Related to but different than
+ * CordovaChromeClient.
+ *
+ * @see <a href="http://developer.android.com/reference/android/webkit/WebViewClient.html">WebViewClient</a>
+ * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
+ * @see XwalkCordovaChromeClient
+ * @see XWalkCordovaWebView
+ */
+public class XWalkCordovaWebViewClient extends XWalkClient implements CordovaWebViewClient {
+
+	private static final String TAG = "CordovaWebViewClient";
+	private static final String CORDOVA_EXEC_URL_PREFIX = "http://cdv_exec/";
+    CordovaInterface cordova;
+    XWalkCordovaWebView appView;
+    private boolean doClearHistory = false;
+
+    // Success
+    public static final int ERROR_OK = 0;
+    // Generic error
+    public static final int ERROR_UNKNOWN = -1;
+    // Server or proxy hostname lookup failed
+    public static final int ERROR_HOST_LOOKUP = -2;
+    // Unsupported authentication scheme (not basic or digest)
+    public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3;
+    // User authentication failed on server
+    public static final int ERROR_AUTHENTICATION = -4;
+    // User authentication failed on proxy
+    public static final int ERROR_PROXY_AUTHENTICATION = -5;
+    // Failed to connect to the server
+    public static final int ERROR_CONNECT = -6;
+    // Failed to read or write to the server
+    public static final int ERROR_IO = -7;
+    // Connection timed out
+    public static final int ERROR_TIMEOUT = -8;
+    // Too many redirects
+    public static final int ERROR_REDIRECT_LOOP = -9;
+    // Unsupported URI scheme
+    public static final int ERROR_UNSUPPORTED_SCHEME = -10;
+    // Failed to perform SSL handshake
+    public static final int ERROR_FAILED_SSL_HANDSHAKE = -11;
+    // Malformed URL
+    public static final int ERROR_BAD_URL = -12;
+    // Generic file error
+    public static final int ERROR_FILE = -13;
+    // File not found
+    public static final int ERROR_FILE_NOT_FOUND = -14;
+    // Too many requests during this load
+    public static final int ERROR_TOO_MANY_REQUESTS = -15;
+
+    /** The authorization tokens. */
+    private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
+
+    /**
+     * Constructor.
+     *
+     * @param cordova
+     */
+    public XWalkCordovaWebViewClient(CordovaInterface cordova) {
+        this.cordova = cordova;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param cordova
+     * @param view
+     */
+    public XWalkCordovaWebViewClient(CordovaInterface cordova, XWalkCordovaWebView view) {
+        this.cordova = cordova;
+        this.appView = view;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param view
+     */
+    public void setWebView(XWalkCordovaWebView view) {
+        this.appView = view;
+    }
+
+
+    // Parses commands sent by setting the webView's URL to:
+    // cdvbrg:service/action/callbackId#jsonArgs
+	private void handleExecUrl(String url) {
+		int idx1 = CORDOVA_EXEC_URL_PREFIX.length();
+		int idx2 = url.indexOf('#', idx1 + 1);
+		int idx3 = url.indexOf('#', idx2 + 1);
+		int idx4 = url.indexOf('#', idx3 + 1);
+		if (idx1 == -1 || idx2 == -1 || idx3 == -1 || idx4 == -1) {
+			Log.e(TAG, "Could not decode URL command: " + url);
+			return;
+		}
+		String service    = url.substring(idx1, idx2);
+		String action     = url.substring(idx2 + 1, idx3);
+		String callbackId = url.substring(idx3 + 1, idx4);
+		String jsonArgs   = url.substring(idx4 + 1);
+        appView.pluginManager.exec(service, action, callbackId, jsonArgs);
+	}
+
+    // Map XWalk error code about loading a page to Android specific ones.
+    // XWalk shares the error code with chromium currently.
+    private int convertErrorCode(int netError) {
+        // Note: many NetError.Error constants don't have an obvious mapping.
+        // These will be handled by the default case, ERROR_UNKNOWN.
+        switch (netError) {
+            case NetError.ERR_UNSUPPORTED_AUTH_SCHEME:
+                return ERROR_UNSUPPORTED_AUTH_SCHEME;
+
+            case NetError.ERR_INVALID_AUTH_CREDENTIALS:
+            case NetError.ERR_MISSING_AUTH_CREDENTIALS:
+            case NetError.ERR_MISCONFIGURED_AUTH_ENVIRONMENT:
+                return ERROR_AUTHENTICATION;
+
+            case NetError.ERR_TOO_MANY_REDIRECTS:
+                return ERROR_REDIRECT_LOOP;
+
+            case NetError.ERR_UPLOAD_FILE_CHANGED:
+                return ERROR_FILE_NOT_FOUND;
+
+            case NetError.ERR_INVALID_URL:
+                return ERROR_BAD_URL;
+
+            case NetError.ERR_DISALLOWED_URL_SCHEME:
+            case NetError.ERR_UNKNOWN_URL_SCHEME:
+                return ERROR_UNSUPPORTED_SCHEME;
+
+            case NetError.ERR_IO_PENDING:
+            case NetError.ERR_NETWORK_IO_SUSPENDED:
+                return ERROR_IO;
+
+            case NetError.ERR_CONNECTION_TIMED_OUT:
+            case NetError.ERR_TIMED_OUT:
+                return ERROR_TIMEOUT;
+
+            case NetError.ERR_FILE_TOO_BIG:
+                return ERROR_FILE;
+
+            case NetError.ERR_HOST_RESOLVER_QUEUE_TOO_LARGE:
+            case NetError.ERR_INSUFFICIENT_RESOURCES:
+            case NetError.ERR_OUT_OF_MEMORY:
+                return ERROR_TOO_MANY_REQUESTS;
+
+            case NetError.ERR_CONNECTION_CLOSED:
+            case NetError.ERR_CONNECTION_RESET:
+            case NetError.ERR_CONNECTION_REFUSED:
+            case NetError.ERR_CONNECTION_ABORTED:
+            case NetError.ERR_CONNECTION_FAILED:
+            case NetError.ERR_SOCKET_NOT_CONNECTED:
+                return ERROR_CONNECT;
+
+            case NetError.ERR_INTERNET_DISCONNECTED:
+            case NetError.ERR_ADDRESS_INVALID:
+            case NetError.ERR_ADDRESS_UNREACHABLE:
+            case NetError.ERR_NAME_NOT_RESOLVED:
+            case NetError.ERR_NAME_RESOLUTION_FAILED:
+                return ERROR_HOST_LOOKUP;
+
+            case NetError.ERR_SSL_PROTOCOL_ERROR:
+            case NetError.ERR_SSL_CLIENT_AUTH_CERT_NEEDED:
+            case NetError.ERR_TUNNEL_CONNECTION_FAILED:
+            case NetError.ERR_NO_SSL_VERSIONS_ENABLED:
+            case NetError.ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
+            case NetError.ERR_SSL_RENEGOTIATION_REQUESTED:
+            case NetError.ERR_CERT_ERROR_IN_SSL_RENEGOTIATION:
+            case NetError.ERR_BAD_SSL_CLIENT_AUTH_CERT:
+            case NetError.ERR_SSL_NO_RENEGOTIATION:
+            case NetError.ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
+            case NetError.ERR_SSL_BAD_RECORD_MAC_ALERT:
+            case NetError.ERR_SSL_UNSAFE_NEGOTIATION:
+            case NetError.ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY:
+            case NetError.ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED:
+            case NetError.ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY:
+                return ERROR_FAILED_SSL_HANDSHAKE;
+
+            case NetError.ERR_PROXY_AUTH_UNSUPPORTED:
+            case NetError.ERR_PROXY_AUTH_REQUESTED:
+            case NetError.ERR_PROXY_CONNECTION_FAILED:
+            case NetError.ERR_UNEXPECTED_PROXY_AUTH:
+                return ERROR_PROXY_AUTHENTICATION;
+
+            // The certificate errors are handled by onReceivedSslError
+            // and don't need to be reported here.
+            case NetError.ERR_CERT_COMMON_NAME_INVALID:
+            case NetError.ERR_CERT_DATE_INVALID:
+            case NetError.ERR_CERT_AUTHORITY_INVALID:
+            case NetError.ERR_CERT_CONTAINS_ERRORS:
+            case NetError.ERR_CERT_NO_REVOCATION_MECHANISM:
+            case NetError.ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
+            case NetError.ERR_CERT_REVOKED:
+            case NetError.ERR_CERT_INVALID:
+            case NetError.ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
+            case NetError.ERR_CERT_NON_UNIQUE_NAME:
+                return ERROR_OK;
+
+            default:
+                return ERROR_UNKNOWN;
+        }
+    }
+
+    /**
+     * Give the host application a chance to take over the control when a new url
+     * is about to be loaded in the current WebView.
+     *
+     * @param view          The WebView that is initiating the callback.
+     * @param url           The url to be loaded.
+     * @return              true to override, false for default behavior
+     */
+	@Override
+    public boolean shouldOverrideUrlLoading(XWalkView view, String url) {
+    	// Check if it's an exec() bridge command message.
+    	if (NativeToJsMessageQueue.ENABLE_LOCATION_CHANGE_EXEC_MODE && url.startsWith(CORDOVA_EXEC_URL_PREFIX)) {
+    		handleExecUrl(url);
+    	}
+
+        // Give plugins the chance to handle the url
+    	else if ((this.appView.pluginManager != null) && this.appView.pluginManager.onOverrideUrlLoading(url)) {
+        }
+
+        // If dialing phone (tel:5551212)
+        else if (url.startsWith("tel:")) {
+            try {
+                Intent intent = new Intent(Intent.ACTION_DIAL);
+                intent.setData(Uri.parse(url));
+                this.cordova.getActivity().startActivity(intent);
+            } catch (android.content.ActivityNotFoundException e) {
+                LOG.e(TAG, "Error dialing " + url + ": " + e.toString());
+            }
+        }
+
+        // If displaying map (geo:0,0?q=address)
+        else if (url.startsWith("geo:")) {
+            try {
+                Intent intent = new Intent(Intent.ACTION_VIEW);
+                intent.setData(Uri.parse(url));
+                this.cordova.getActivity().startActivity(intent);
+            } catch (android.content.ActivityNotFoundException e) {
+                LOG.e(TAG, "Error showing map " + url + ": " + e.toString());
+            }
+        }
+
+        // If sending email (mailto:abc@corp.com)
+        else if (url.startsWith("mailto:")) {
+            try {
+                Intent intent = new Intent(Intent.ACTION_VIEW);
+                intent.setData(Uri.parse(url));
+                this.cordova.getActivity().startActivity(intent);
+            } catch (android.content.ActivityNotFoundException e) {
+                LOG.e(TAG, "Error sending email " + url + ": " + e.toString());
+            }
+        }
+
+        // If sms:5551212?body=This is the message
+        else if (url.startsWith("sms:")) {
+            try {
+                Intent intent = new Intent(Intent.ACTION_VIEW);
+
+                // Get address
+                String address = null;
+                int parmIndex = url.indexOf('?');
+                if (parmIndex == -1) {
+                    address = url.substring(4);
+                }
+                else {
+                    address = url.substring(4, parmIndex);
+
+                    // If body, then set sms body
+                    Uri uri = Uri.parse(url);
+                    String query = uri.getQuery();
+                    if (query != null) {
+                        if (query.startsWith("body=")) {
+                            intent.putExtra("sms_body", query.substring(5));
+                        }
+                    }
+                }
+                intent.setData(Uri.parse("sms:" + address));
+                intent.putExtra("address", address);
+                intent.setType("vnd.android-dir/mms-sms");
+                this.cordova.getActivity().startActivity(intent);
+            } catch (android.content.ActivityNotFoundException e) {
+                LOG.e(TAG, "Error sending sms " + url + ":" + e.toString());
+            }
+        }
+        
+        //Android Market
+        else if(url.startsWith("market:")) {
+            try {
+                Intent intent = new Intent(Intent.ACTION_VIEW);
+                intent.setData(Uri.parse(url));
+                this.cordova.getActivity().startActivity(intent);
+            } catch (android.content.ActivityNotFoundException e) {
+                LOG.e(TAG, "Error loading Google Play Store: " + url, e);
+            }
+        }
+
+        // All else
+        else {
+
+            // If our app or file:, then load into a new Cordova webview container by starting a new instance of our activity.
+            // Our app continues to run.  When BACK is pressed, our app is redisplayed.
+            if (url.startsWith("file://") || url.startsWith("data:")  || Config.isUrlWhiteListed(url)) {
+                return false;
+            }
+
+            // If not our application, let default viewer handle
+            else {
+                try {
+                    Intent intent = new Intent(Intent.ACTION_VIEW);
+                    intent.setData(Uri.parse(url));
+                    this.cordova.getActivity().startActivity(intent);
+                } catch (android.content.ActivityNotFoundException e) {
+                    LOG.e(TAG, "Error loading url " + url, e);
+                }
+            }
+        }
+        return true;
+    }
+    
+    /**
+     * 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(XWalkView view, XWalkHttpAuthHandler handler, String host, String realm) {
+
+        // Get the authentication token
+        AuthenticationToken token = this.getAuthenticationToken(host, realm);
+        if (token != null) {
+            handler.proceed(token.getUserName(), token.getPassword());
+        }
+        else {
+            // Handle 401 like we'd normally do!
+            super.onReceivedHttpAuthRequest(view, handler, host, realm);
+        }
+    }
+
+    /**
+     * Notify the host application that a page has started loading.
+     * This method is called once for each main frame load so a page with iframes or framesets will call onPageStarted
+     * one time for the main frame. This also means that onPageStarted will not be called when the contents of an
+     * embedded frame changes, i.e. clicking a link whose target is an iframe.
+     *
+     * @param view          The webview initiating the callback.
+     * @param url           The url of the page.
+     */
+    @Override
+    public void onPageStarted(XWalkView view, String url, Bitmap favicon) {
+
+        // Flush stale messages.
+        this.appView.resetJsMessageQueue();
+
+        // Broadcast message that page has loaded
+        this.appView.postMessage("onPageStarted", url);
+
+        // Notify all plugins of the navigation, so they can clean up if necessary.
+        if (this.appView.pluginManager != null) {
+            this.appView.pluginManager.onReset();
+        }
+    }
+
+    /**
+     * Notify the host application that a page has finished loading.
+     * This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet.
+     *
+     *
+     * @param view          The webview initiating the callback.
+     * @param url           The url of the page.
+     */
+    @Override
+    public void onPageFinished(XWalkView view, String url) {
+        super.onPageFinished(view, url);
+        LOG.d(TAG, "onPageFinished(" + url + ")");
+
+        /**
+         * Because of a timing issue we need to clear this history in onPageFinished as well as
+         * onPageStarted. However we only want to do this if the doClearHistory boolean is set to
+         * true. You see when you load a url with a # in it which is common in jQuery applications
+         * onPageStared is not called. Clearing the history at that point would break jQuery apps.
+         */
+        if (this.doClearHistory) {
+            view.clearHistory();
+            this.doClearHistory = false;
+        }
+
+        // Clear timeout flag
+        this.appView.loadUrlTimeout++;
+
+        // Broadcast message that page has loaded
+        this.appView.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) {
+            Thread t = new Thread(new Runnable() {
+                public void run() {
+                    try {
+                        Thread.sleep(2000);
+                        cordova.getActivity().runOnUiThread(new Runnable() {
+                            public void run() {
+                                appView.postMessage("spinner", "stop");
+                            }
+                        });
+                    } catch (InterruptedException e) {
+                    }
+                }
+            });
+            t.start();
+        }
+
+        // Shutdown if blank loaded
+        if (url.equals("about:blank")) {
+            appView.postMessage("exit", null);
+        }
+    }
+
+    /**
+     * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
+     * The errorCode parameter corresponds to one of the ERROR_* constants.
+     *
+     * @param view          The WebView that is initiating the callback.
+     * @param errorCode     The error code corresponding to an ERROR_* value.
+     * @param description   A String describing the error.
+     * @param failingUrl    The url that failed to load.
+     */
+    @Override
+    public void onReceivedError(XWalkView view, int errorCode, String description, String failingUrl) {
+        LOG.d(TAG, "CordovaWebViewClient.onReceivedError: Error code=%s Description=%s URL=%s", errorCode, description, failingUrl);
+
+        // Clear timeout flag
+        this.appView.loadUrlTimeout++;
+
+        // Convert the XWalk error code to Cordova error code, which follows the Android spec,
+        // http://developer.android.com/reference/android/webkit/WebViewClient.html.
+        errorCode = convertErrorCode(errorCode);
+
+        // Handle error
+        JSONObject data = new JSONObject();
+        try {
+            data.put("errorCode", errorCode);
+            data.put("description", description);
+            data.put("url", failingUrl);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        this.appView.postMessage("onReceivedError", data);
+    }
+
+    /**
+     * Notify the host application that an SSL error occurred while loading a resource.
+     * The host application must call either handler.cancel() or handler.proceed().
+     * Note that the decision may be retained for use in response to future SSL errors.
+     * The default behavior is to cancel the load.
+     *
+     * @param view          The WebView that is initiating the callback.
+     * @param handler       An SslErrorHandler object that will handle the user's response.
+     * @param error         The SSL error object.
+     */
+    @TargetApi(8)
+    @Override
+    public void onReceivedSslError(XWalkView view, SslErrorHandler handler, SslError error) {
+
+        final String packageName = this.cordova.getActivity().getPackageName();
+        final PackageManager pm = this.cordova.getActivity().getPackageManager();
+
+        ApplicationInfo appInfo;
+        try {
+            appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
+            if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+                // debug = true
+                handler.proceed();
+                return;
+            } else {
+                // debug = false
+                super.onReceivedSslError(view, handler, error);
+            }
+        } catch (NameNotFoundException e) {
+            // When it doubt, lock it out!
+            super.onReceivedSslError(view, handler, error);
+        }
+    }
+
+
+    /**
+     * Sets the authentication token.
+     *
+     * @param authenticationToken
+     * @param host
+     * @param realm
+     */
+    public void setAuthenticationToken(AuthenticationToken authenticationToken, String host, String realm) {
+        if (host == null) {
+            host = "";
+        }
+        if (realm == null) {
+            realm = "";
+        }
+        this.authenticationTokens.put(host.concat(realm), authenticationToken);
+    }
+
+    /**
+     * Removes the authentication token.
+     *
+     * @param host
+     * @param realm
+     *
+     * @return the authentication token or null if did not exist
+     */
+    public AuthenticationToken removeAuthenticationToken(String host, String realm) {
+        return this.authenticationTokens.remove(host.concat(realm));
+    }
+
+    /**
+     * Gets the authentication token.
+     *
+     * In order it tries:
+     * 1- host + realm
+     * 2- host
+     * 3- realm
+     * 4- no host, no realm
+     *
+     * @param host
+     * @param realm
+     *
+     * @return the authentication token
+     */
+    public AuthenticationToken getAuthenticationToken(String host, String realm) {
+        AuthenticationToken token = null;
+        token = this.authenticationTokens.get(host.concat(realm));
+
+        if (token == null) {
+            // try with just the host
+            token = this.authenticationTokens.get(host);
+
+            // Try the realm
+            if (token == null) {
+                token = this.authenticationTokens.get(realm);
+            }
+
+            // if no host found, just query for default
+            if (token == null) {
+                token = this.authenticationTokens.get("");
+            }
+        }
+
+        return token;
+    }
+
+    /**
+     * Clear all authentication tokens.
+     */
+    public void clearAuthenticationTokens() {
+        this.authenticationTokens.clear();
+    }
+
+    @Override
+    public void setWebView(CordovaWebView appView) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void onReceivedError(CordovaWebView me, int i, String string,
+            String url) {
+        //This should work, but may run into casting errors! 
+        this.onReceivedError((XWalkView) me, i, string, url);
+        
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c17503ab/framework/src/org/apache/cordova/engine/crosswalk/XwalkCordovaChromeClient.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/engine/crosswalk/XwalkCordovaChromeClient.java b/framework/src/org/apache/cordova/engine/crosswalk/XwalkCordovaChromeClient.java
new file mode 100755
index 0000000..342011e
--- /dev/null
+++ b/framework/src/org/apache/cordova/engine/crosswalk/XwalkCordovaChromeClient.java
@@ -0,0 +1,428 @@
+/*
+       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.engine.crosswalk;
+
+import org.apache.cordova.Config;
+import org.apache.cordova.CordovaChromeClient;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.CordovaWebViewClient;
+import org.apache.cordova.LOG;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import android.annotation.TargetApi;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.webkit.ConsoleMessage;
+
+
+
+
+//import android.webkit.JsPromptResult;
+//import android.webkit.JsResult;
+import org.xwalk.core.JsPromptResult;
+import org.xwalk.core.JsResult;
+
+import android.webkit.ValueCallback;
+
+
+
+
+//import android.webkit.WebChromeClient;
+import org.xwalk.core.XWalkWebChromeClient;
+import org.xwalk.core.client.XWalkDefaultWebChromeClient;
+
+import android.webkit.WebStorage;
+
+
+
+
+//import android.webkit.WebView;
+import org.xwalk.core.XWalkView;
+import org.xwalk.core.XWalkGeolocationPermissions;
+
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+
+/**
+ * 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,
+ * such as onCreateWindow(), onConsoleMessage(), onProgressChanged(), etc. Related
+ * to but different than CordovaWebViewClient.
+ *
+ * @see <a href="http://developer.android.com/reference/android/webkit/WebChromeClient.html">WebChromeClient</a>
+ * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
+ * @see XWalkCordovaWebViewClient
+ * @see XWalkCordovaWebView
+ */
+public class XwalkCordovaChromeClient extends XWalkDefaultWebChromeClient implements CordovaChromeClient {
+
+    public static final int FILECHOOSER_RESULTCODE = 5173;
+    private static final String LOG_TAG = "CordovaChromeClient";
+    private String TAG = "CordovaLog";
+    private long MAX_QUOTA = 100 * 1024 * 1024;
+    protected CordovaInterface cordova;
+    protected XWalkCordovaWebView appView;
+
+    // the video progress view
+    private View mVideoProgressView;
+    
+    // File Chooser
+    public ValueCallback<Uri> mUploadMessage;
+    
+    /**
+     * Constructor.
+     *
+     * @param cordova
+     */
+    public XwalkCordovaChromeClient(CordovaInterface cordova) {
+        super(cordova.getActivity(), null);
+        this.cordova = cordova;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param ctx
+     * @param app
+     */
+    public XwalkCordovaChromeClient(CordovaInterface ctx, XWalkCordovaWebView app) {
+        super(ctx.getActivity(), app);
+        this.cordova = ctx;
+        this.appView = app;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param view
+     */
+    public void setWebView(XWalkCordovaWebView view) {
+        this.appView = view;
+    }
+
+    /**
+     * Tell the client to display a javascript alert dialog.
+     *
+     * @param view
+     * @param url
+     * @param message
+     * @param result
+     */
+    @Override
+    public boolean onJsAlert(XWalkView view, String url, String message, final JsResult result) {
+        AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
+        dlg.setMessage(message);
+        dlg.setTitle("Alert");
+        //Don't let alerts break the back button
+        dlg.setCancelable(true);
+        dlg.setPositiveButton(android.R.string.ok,
+                new AlertDialog.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        result.confirm();
+                    }
+                });
+        dlg.setOnCancelListener(
+                new DialogInterface.OnCancelListener() {
+                    public void onCancel(DialogInterface dialog) {
+                        result.cancel();
+                    }
+                });
+        dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
+            //DO NOTHING
+            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                if (keyCode == KeyEvent.KEYCODE_BACK)
+                {
+                    result.confirm();
+                    return false;
+                }
+                else
+                    return true;
+            }
+        });
+        dlg.create();
+        dlg.show();
+        return true;
+    }
+
+    /**
+     * Tell the client to display a confirm dialog to the user.
+     *
+     * @param view
+     * @param url
+     * @param message
+     * @param result
+     */
+    @Override
+    public boolean onJsConfirm(XWalkView view, String url, String message, final JsResult result) {
+        AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
+        dlg.setMessage(message);
+        dlg.setTitle("Confirm");
+        dlg.setCancelable(true);
+        dlg.setPositiveButton(android.R.string.ok,
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        result.confirm();
+                    }
+                });
+        dlg.setNegativeButton(android.R.string.cancel,
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        result.cancel();
+                    }
+                });
+        dlg.setOnCancelListener(
+                new DialogInterface.OnCancelListener() {
+                    public void onCancel(DialogInterface dialog) {
+                        result.cancel();
+                    }
+                });
+        dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
+            //DO NOTHING
+            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                if (keyCode == KeyEvent.KEYCODE_BACK)
+                {
+                    result.cancel();
+                    return false;
+                }
+                else
+                    return true;
+            }
+        });
+        dlg.create();
+        dlg.show();
+        return true;
+    }
+
+    /**
+     * Tell the client to display a prompt dialog to the user.
+     * If the client returns true, WebView will assume that the client will
+     * handle the prompt dialog and call the appropriate JsPromptResult method.
+     *
+     * Since we are hacking prompts for our own purposes, we should not be using them for
+     * this purpose, perhaps we should hack console.log to do this instead!
+     *
+     * @param view
+     * @param url
+     * @param message
+     * @param defaultValue
+     * @param result
+     */
+    @Override
+    public boolean onJsPrompt(XWalkView view, String url, String message, String defaultValue, JsPromptResult result) {
+
+        // Security check to make sure any requests are coming from the page initially
+        // loaded in webview and not another loaded in an iframe.
+        boolean reqOk = false;
+        if (url.startsWith("file://") || Config.isUrlWhiteListed(url)) {
+            reqOk = true;
+        }
+
+        // Calling PluginManager.exec() to call a native service using 
+        // prompt(this.stringify(args), "gap:"+this.stringify([service, action, callbackId, true]));
+        if (reqOk && defaultValue != null && defaultValue.length() > 3 && defaultValue.substring(0, 4).equals("gap:")) {
+            JSONArray array;
+            try {
+                array = new JSONArray(defaultValue.substring(4));
+                String service = array.getString(0);
+                String action = array.getString(1);
+                String callbackId = array.getString(2);
+                String r = this.appView.exec(service, action, callbackId, message);
+                result.confirm(r == null ? "" : r);
+            } catch (JSONException e) {
+                e.printStackTrace();
+                return false;
+            }
+        }
+
+        // Sets the native->JS bridge mode. 
+        else if (reqOk && defaultValue != null && defaultValue.equals("gap_bridge_mode:")) {
+        	try {
+                this.appView.setNativeToJsBridgeMode(Integer.parseInt(message));
+                result.confirm("");
+        	} catch (NumberFormatException e){
+                result.confirm("");
+                e.printStackTrace();
+        	}
+        }
+
+        // Polling for JavaScript messages 
+        else if (reqOk && defaultValue != null && defaultValue.equals("gap_poll:")) {
+            String r = this.appView.retrieveJsMessages("1".equals(message));
+            result.confirm(r == null ? "" : r);
+        }
+
+        // Do NO-OP so older code doesn't display dialog
+        else if (defaultValue != null && defaultValue.equals("gap_init:")) {
+            result.confirm("OK");
+        }
+
+        // Show dialog
+        else {
+            final JsPromptResult res = result;
+            AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
+            dlg.setMessage(message);
+            final EditText input = new EditText(this.cordova.getActivity());
+            if (defaultValue != null) {
+                input.setText(defaultValue);
+            }
+            dlg.setView(input);
+            dlg.setCancelable(false);
+            dlg.setPositiveButton(android.R.string.ok,
+                    new DialogInterface.OnClickListener() {
+                        public void onClick(DialogInterface dialog, int which) {
+                            String usertext = input.getText().toString();
+                            res.confirm(usertext);
+                        }
+                    });
+            dlg.setNegativeButton(android.R.string.cancel,
+                    new DialogInterface.OnClickListener() {
+                        public void onClick(DialogInterface dialog, int which) {
+                            res.cancel();
+                        }
+                    });
+            dlg.create();
+            dlg.show();
+        }
+        return true;
+    }
+
+    /**
+     * Handle database quota exceeded notification.
+     */
+    @Override
+    public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
+            long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
+    {
+        LOG.d(TAG, "onExceededDatabaseQuota estimatedSize: %d  currentQuota: %d  totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
+        quotaUpdater.updateQuota(MAX_QUOTA);
+    }
+
+    // console.log in api level 7: http://developer.android.com/guide/developing/debug-tasks.html
+    // Expect this to not compile in a future Android release!
+    @SuppressWarnings("deprecation")
+    @Override
+    public void onConsoleMessage(String message, int lineNumber, String sourceID)
+    {
+        //This is only for Android 2.1
+        if(android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.ECLAIR_MR1)
+        {
+            LOG.d(TAG, "%s: Line %d : %s", sourceID, lineNumber, message);
+            super.onConsoleMessage(message, lineNumber, sourceID);
+        }
+    }
+
+    @TargetApi(8)
+    @Override
+    public boolean onConsoleMessage(ConsoleMessage consoleMessage)
+    {
+        if (consoleMessage.message() != null)
+            LOG.d(TAG, "%s: Line %d : %s" , consoleMessage.sourceId() , consoleMessage.lineNumber(), consoleMessage.message());
+         return super.onConsoleMessage(consoleMessage);
+    }
+
+    @Override
+    /**
+     * Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin.
+     *
+     * @param origin
+     * @param callback
+     */
+    public void onGeolocationPermissionsShowPrompt(String origin, XWalkGeolocationPermissions.Callback callback) {
+        super.onGeolocationPermissionsShowPrompt(origin, callback);
+        callback.invoke(origin, true, false);
+    }
+    
+    // API level 7 is required for this, see if we could lower this using something else
+    @Override
+    public void onShowCustomView(View view, XWalkWebChromeClient.CustomViewCallback callback) {
+        this.appView.showCustomView(view, callback);
+    }
+
+	@Override
+	public void onHideCustomView() {
+    	this.appView.hideCustomView();
+	}
+    
+    @Override
+    /**
+     * Ask the host application for a custom progress view to show while
+     * a <video> is loading.
+     * @return View The progress view.
+     */
+    public View getVideoLoadingProgressView() {
+
+	    if (mVideoProgressView == null) {	        
+	    	// Create a new Loading view programmatically.
+	    	
+	    	// create the linear layout
+	    	LinearLayout layout = new LinearLayout(this.appView.getContext());
+	        layout.setOrientation(LinearLayout.VERTICAL);
+	        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+	        layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
+	        layout.setLayoutParams(layoutParams);
+	        // the proress bar
+	        ProgressBar bar = new ProgressBar(this.appView.getContext());
+	        LinearLayout.LayoutParams barLayoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+	        barLayoutParams.gravity = Gravity.CENTER;
+	        bar.setLayoutParams(barLayoutParams);   
+	        layout.addView(bar);
+	        
+	        mVideoProgressView = layout;
+	    }
+    return mVideoProgressView; 
+    }
+    
+    public void openFileChooser(ValueCallback<Uri> uploadMsg) {
+        this.openFileChooser(uploadMsg, "*/*");
+    }
+
+    public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) {
+        this.openFileChooser(uploadMsg, acceptType, null);
+    }
+    
+    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)
+    {
+        mUploadMessage = uploadMsg;
+        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
+        i.addCategory(Intent.CATEGORY_OPENABLE);
+        i.setType("*/*");
+        this.cordova.getActivity().startActivityForResult(Intent.createChooser(i, "File Browser"),
+                FILECHOOSER_RESULTCODE);
+    }
+    
+    public ValueCallback<Uri> getValueCallback() {
+        return this.mUploadMessage;
+    }
+
+    @Override
+    public void setWebView(CordovaWebView appView) {
+        // TODO Auto-generated method stub
+        
+    }
+}


[09/12] w00t! Managed to get XWalk to work. Next Step: Make it installable like a Cordova Plugin!

Posted by ia...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c17503ab/framework/src/org/xwalk/runtime/extension/CordovaXWalkCoreExtensionBridge.java
----------------------------------------------------------------------
diff --git a/framework/src/org/xwalk/runtime/extension/CordovaXWalkCoreExtensionBridge.java b/framework/src/org/xwalk/runtime/extension/CordovaXWalkCoreExtensionBridge.java
new file mode 100644
index 0000000..e80ea51
--- /dev/null
+++ b/framework/src/org/xwalk/runtime/extension/CordovaXWalkCoreExtensionBridge.java
@@ -0,0 +1,17 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.runtime.extension;
+
+import org.xwalk.runtime.extension.XWalkExtension;
+
+/**
+ * This class is a public wrapper for XWalkCoreExtensionBridge.
+ */
+public class CordovaXWalkCoreExtensionBridge extends XWalkCoreExtensionBridge {
+
+    public CordovaXWalkCoreExtensionBridge(XWalkExtension extension) {
+        super(extension);
+    }
+}


[03/12] android commit: Got the bridge to work with Crosswalk

Posted by ia...@apache.org.
Got the bridge to work with Crosswalk


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

Branch: refs/heads/pluggable_webview
Commit: 2f7e833a794f557cc2041b7b697a5b7cfb0f959e
Parents: c17503a
Author: Joe Bowser <bo...@apache.org>
Authored: Mon Mar 10 14:39:43 2014 -0700
Committer: Ian Clelland <ic...@chromium.org>
Committed: Tue Apr 29 22:50:11 2014 -0400

----------------------------------------------------------------------
 .../org/apache/cordova/AndroidExposedJsApi.java | 76 ++++++++++++++++++++
 .../src/org/apache/cordova/AndroidWebView.java  |  2 +-
 .../org/apache/cordova/CordovaResourceApi.java  |  2 +-
 .../src/org/apache/cordova/ExposedJsApi.java    | 75 +++----------------
 .../apache/cordova/NativeToJsMessageQueue.java  |  2 +-
 .../engine/crosswalk/XWalkCordovaWebView.java   |  4 +-
 6 files changed, 89 insertions(+), 72 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/2f7e833a/framework/src/org/apache/cordova/AndroidExposedJsApi.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/AndroidExposedJsApi.java b/framework/src/org/apache/cordova/AndroidExposedJsApi.java
new file mode 100755
index 0000000..74945cc
--- /dev/null
+++ b/framework/src/org/apache/cordova/AndroidExposedJsApi.java
@@ -0,0 +1,76 @@
+/*
+       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.webkit.JavascriptInterface;
+import org.apache.cordova.PluginManager;
+import org.json.JSONException;
+
+/**
+ * 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 /* package */ class AndroidExposedJsApi implements ExposedJsApi {
+    
+    private PluginManager pluginManager;
+    private NativeToJsMessageQueue jsMessageQueue;
+    
+    public AndroidExposedJsApi(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue) {
+        this.pluginManager = pluginManager;
+        this.jsMessageQueue = jsMessageQueue;
+    }
+
+    @JavascriptInterface
+    public String exec(String service, String action, String callbackId, String arguments) throws JSONException {
+        // 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);
+        }
+    }
+    
+    @JavascriptInterface
+    public void setNativeToJsBridgeMode(int value) {
+        jsMessageQueue.setBridgeMode(value);
+    }
+    
+    @JavascriptInterface
+    public String retrieveJsMessages(boolean fromOnlineEvent) {
+        return jsMessageQueue.popAndEncode(fromOnlineEvent);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/2f7e833a/framework/src/org/apache/cordova/AndroidWebView.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/AndroidWebView.java b/framework/src/org/apache/cordova/AndroidWebView.java
index ed4c02c..00c4bb1 100755
--- a/framework/src/org/apache/cordova/AndroidWebView.java
+++ b/framework/src/org/apache/cordova/AndroidWebView.java
@@ -343,7 +343,7 @@ public class AndroidWebView extends WebView implements CordovaWebView {
 
         pluginManager = new PluginManager(this, this.cordova);
         jsMessageQueue = new NativeToJsMessageQueue(this, cordova);
-        exposedJsApi = new ExposedJsApi(pluginManager, jsMessageQueue);
+        exposedJsApi = new AndroidExposedJsApi(pluginManager, jsMessageQueue);
         resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
         exposeJsInterface();
     }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/2f7e833a/framework/src/org/apache/cordova/CordovaResourceApi.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/CordovaResourceApi.java b/framework/src/org/apache/cordova/CordovaResourceApi.java
index f1770fd..ff2c5c5 100644
--- a/framework/src/org/apache/cordova/CordovaResourceApi.java
+++ b/framework/src/org/apache/cordova/CordovaResourceApi.java
@@ -84,7 +84,7 @@ public class CordovaResourceApi {
     // Creating this is light-weight.
     private static OkHttpClient httpClient = new OkHttpClient();
     
-    static Thread jsThread;
+    public static Thread jsThread;
 
     private final AssetManager assetManager;
     private final ContentResolver contentResolver;

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/2f7e833a/framework/src/org/apache/cordova/ExposedJsApi.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/ExposedJsApi.java b/framework/src/org/apache/cordova/ExposedJsApi.java
old mode 100755
new mode 100644
index 103e546..d0f8abf
--- a/framework/src/org/apache/cordova/ExposedJsApi.java
+++ b/framework/src/org/apache/cordova/ExposedJsApi.java
@@ -1,76 +1,17 @@
-/*
-       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.webkit.JavascriptInterface;
-import org.apache.cordova.PluginManager;
 import org.json.JSONException;
 
-/**
- * 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
+import android.webkit.JavascriptInterface;
+
+/*
+ * Any exposed Javascript API MUST implement these three things!
  */
-public /* package */ class ExposedJsApi {
-    
-    private PluginManager pluginManager;
-    private NativeToJsMessageQueue jsMessageQueue;
-    
-    public ExposedJsApi(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue) {
-        this.pluginManager = pluginManager;
-        this.jsMessageQueue = jsMessageQueue;
-    }
 
-    @JavascriptInterface
-    public String exec(String service, String action, String callbackId, String arguments) throws JSONException {
-        // 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.";
-        }
+public interface ExposedJsApi {
 
-        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);
-        }
-    }
-    
-    @JavascriptInterface
-    public void setNativeToJsBridgeMode(int value) {
-        jsMessageQueue.setBridgeMode(value);
-    }
-    
     @JavascriptInterface
-    public String retrieveJsMessages(boolean fromOnlineEvent) {
-        return jsMessageQueue.popAndEncode(fromOnlineEvent);
-    }
+    public String exec(String service, String action, String callbackId, String arguments) throws JSONException;
+    public void setNativeToJsBridgeMode(int value);
+    public String retrieveJsMessages(boolean fromOnlineEvent);
 }

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/2f7e833a/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/NativeToJsMessageQueue.java b/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
index c8a3b06..7fb6c06 100755
--- a/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
+++ b/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
@@ -48,7 +48,7 @@ public class NativeToJsMessageQueue {
         
     // Disable sending back native->JS messages during an exec() when the active
     // exec() is asynchronous. Set this to true when running bridge benchmarks.
-    static final boolean DISABLE_EXEC_CHAINING = false;
+    public static final boolean DISABLE_EXEC_CHAINING = false;
     
     // Arbitrarily chosen upper limit for how much data to send to JS in one shot.
     // This currently only chops up on message boundaries. It may be useful

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/2f7e833a/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java b/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java
index 73195fe..682e28b 100755
--- a/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java
+++ b/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java
@@ -117,7 +117,7 @@ public class XWalkCordovaWebView extends XWalkView implements CordovaWebView {
     private long lastMenuEventTime = 0;
 
     NativeToJsMessageQueue jsMessageQueue;
-    ExposedJsApi exposedJsApi;
+    XwalkExposedJsApi exposedJsApi;
 
     /** custom view created by the browser (a video player for example) */
     private View mCustomView;
@@ -319,7 +319,7 @@ public class XWalkCordovaWebView extends XWalkView implements CordovaWebView {
         extensionManager = new XWalkExtensionManager(this.cordova.getActivity(), this.cordova.getActivity());
         extensionManager.loadExtensions();
         jsMessageQueue = new NativeToJsMessageQueue(this, cordova);
-        exposedJsApi = new ExposedJsApi(pluginManager, jsMessageQueue);
+        exposedJsApi = new XwalkExposedJsApi(pluginManager, jsMessageQueue);
         resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
         exposeJsInterface();
     }


[07/12] android commit: Removing the xwalk_core_library reference so we can use this with MozillaView

Posted by ia...@apache.org.
Removing the xwalk_core_library reference so we can use this with MozillaView


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

Branch: refs/heads/pluggable_webview
Commit: f4555f7c96aed412d15e87a9def8a9e69039a10a
Parents: 8408da5
Author: Joe Bowser <bo...@apache.org>
Authored: Wed Apr 23 14:31:30 2014 -0700
Committer: Ian Clelland <ic...@chromium.org>
Committed: Tue Apr 29 22:50:11 2014 -0400

----------------------------------------------------------------------
 framework/project.properties | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/f4555f7c/framework/project.properties
----------------------------------------------------------------------
diff --git a/framework/project.properties b/framework/project.properties
index 5edb77d..9fe04f3 100644
--- a/framework/project.properties
+++ b/framework/project.properties
@@ -14,4 +14,3 @@ target=android-19
 apk-configurations=
 renderscript.opt.level=O0
 android.library=true
-android.library.reference.1=../../crosswalk-cordova-android/framework/xwalk_core_library


[02/12] android commit: Removing XWalkWebView and making it a plugin component

Posted by ia...@apache.org.
Removing XWalkWebView and making it a plugin component


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

Branch: refs/heads/pluggable_webview
Commit: bd806a34d83ac086c3854ee7d0f74da534125a77
Parents: 2f7e833
Author: Joe Bowser <bo...@apache.org>
Authored: Wed Mar 12 15:04:28 2014 -0700
Committer: Ian Clelland <ic...@chromium.org>
Committed: Tue Apr 29 22:50:11 2014 -0400

----------------------------------------------------------------------
 .../engine/crosswalk/XWalkCordovaWebView.java   | 1147 ------------------
 .../crosswalk/XWalkCordovaWebViewClient.java    |  636 ----------
 .../crosswalk/XwalkCordovaChromeClient.java     |  428 -------
 .../CordovaXWalkCoreExtensionBridge.java        |   17 -
 4 files changed, 2228 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/bd806a34/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java b/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java
deleted file mode 100755
index 682e28b..0000000
--- a/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java
+++ /dev/null
@@ -1,1147 +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.engine.crosswalk;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Locale;
-
-import org.apache.cordova.Config;
-import org.apache.cordova.CordovaChromeClient;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaResourceApi;
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.CordovaWebViewClient;
-import org.apache.cordova.LOG;
-import org.apache.cordova.NativeToJsMessageQueue;
-import org.apache.cordova.ExposedJsApi;
-import org.apache.cordova.PluginManager;
-import org.apache.cordova.PluginResult;
-import org.apache.cordova.ScrollEvent;
-import org.json.JSONException;
-import org.xwalk.core.WebBackForwardList;
-import org.xwalk.core.WebHistoryItem;
-import org.xwalk.core.XWalkSettings;
-import org.xwalk.core.XWalkView;
-import org.xwalk.core.XWalkWebChromeClient;
-import org.xwalk.runtime.extension.XWalkExtensionManager;
-
-import android.app.Activity;
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.inputmethod.InputMethodManager;
-import android.webkit.WebChromeClient.CustomViewCallback;
-//import android.webkit.WebBackForwardList;
-//import android.webkit.WebHistoryItem;
-//import android.webkit.WebChromeClient;
-//import android.webkit.WebSettings;
-//import android.webkit.WebView;
-//import android.webkit.WebSettings.LayoutAlgorithm;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout.LayoutParams;
-
-/*
- * This class is our web view.
- *
- * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
- * @see <a href="http://developer.android.com/reference/android/webkit/WebView.html">WebView</a>
- */
-public class XWalkCordovaWebView extends XWalkView implements CordovaWebView {
-
-    public static final String TAG = "CordovaWebView";
-    public static final String CORDOVA_VERSION = "3.3.0";
-
-    private ArrayList<Integer> keyDownCodes = new ArrayList<Integer>();
-    private ArrayList<Integer> keyUpCodes = new ArrayList<Integer>();
-
-    public PluginManager pluginManager;
-    private boolean paused;
-
-    private XWalkExtensionManager extensionManager;
-
-    private BroadcastReceiver receiver;
-
-
-    /** Activities and other important classes **/
-    private CordovaInterface cordova;
-    XWalkCordovaWebViewClient viewClient;
-    @SuppressWarnings("unused")
-    private XwalkCordovaChromeClient chromeClient;
-
-    private String url;
-
-    // Flag to track that a loadUrl timeout occurred
-    int loadUrlTimeout = 0;
-
-    private boolean bound;
-
-    private boolean handleButton = false;
-    
-    private long lastMenuEventTime = 0;
-
-    NativeToJsMessageQueue jsMessageQueue;
-    XwalkExposedJsApi exposedJsApi;
-
-    /** custom view created by the browser (a video player for example) */
-    private View mCustomView;
-    private XWalkWebChromeClient.CustomViewCallback mCustomViewCallback;
-
-    private ActivityResult mResult = null;
-
-    private CordovaResourceApi resourceApi;
-
-    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,
-            ViewGroup.LayoutParams.MATCH_PARENT,
-            Gravity.CENTER);
-    
-    /**
-     * Constructor.
-     *
-     * @param context
-     */
-    public XWalkCordovaWebView(Context context) {
-        super(context, (Activity)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();
-    }
-
-    /**
-     * Constructor.
-     *
-     * @param context
-     * @param attrs
-     */
-    public XWalkCordovaWebView(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 XwalkCordovaChromeClient(this.cordova, this));
-        this.initWebViewClient(this.cordova);
-        this.loadConfiguration();
-        this.setup();
-    }
-
-    /**
-     * Constructor.
-     *
-     * @param context
-     * @param attrs
-     * @param defStyle
-     *
-     */
-    public XWalkCordovaWebView(Context context, AttributeSet attrs, int defStyle) {
-        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 XwalkCordovaChromeClient(this.cordova, this));
-        this.loadConfiguration();
-        this.setup();
-    }
-
-    /**
-     * Constructor.
-     *
-     * @param context
-     * @param attrs
-     * @param defStyle
-     * @param privateBrowsing
-     */
-    @TargetApi(11)
-    public XWalkCordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) {
-        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 XwalkCordovaChromeClient(this.cordova));
-        this.initWebViewClient(this.cordova);
-        this.loadConfiguration();
-        this.setup();
-    }
-
- 
-    private void initWebViewClient(CordovaInterface cordova) {
-            this.setWebViewClient(new XWalkCordovaWebViewClient(this.cordova, this));
-    }
-
-    /**
-     * Initialize webview.
-     */
-    @SuppressWarnings("deprecation")
-    @SuppressLint("NewApi")
-    private void setup() {
-        this.setInitialScale(0);
-        this.setVerticalScrollBarEnabled(false);
-        if (shouldRequestFocusOnInit()) {
-			this.requestFocusFromTouch();
-		}
-		// Enable JavaScript
-        XWalkSettings settings = this.getSettings();
-        settings.setJavaScriptEnabled(true);
-        settings.setJavaScriptCanOpenWindowsAutomatically(true);
-        // nhu: N/A
-        //settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
-
-        //We don't save any form data in the application
-        // nhu: N/A
-        //settings.setSaveFormData(false);
-        //settings.setSavePassword(false);
-        
-        // Jellybean rightfully tried to lock this down. Too bad they didn't give us a whitelist
-        // while we do this
-        if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
-            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();
-        //settings.setDatabaseEnabled(true);
-        //TODO: bring it back when it's ready in the XWalk.
-        //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)
-            {
-                //TODO: bring it back when it's ready in the XWalk.
-                //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);
-
-        // Enable DOM storage
-        settings.setDomStorageEnabled(true);
-
-        // Enable built-in geolocation
-        settings.setGeolocationEnabled(true);
-        
-        // Enable AppCache
-        // Fix for CB-2282
-        // nhu: N/A
-        //settings.setAppCacheMaxSize(5 * 1048576);
-        String pathToCache = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
-        settings.setAppCachePath(pathToCache);
-        settings.setAppCacheEnabled(true);
-
-        pluginManager = new PluginManager(this, this.cordova);
-        extensionManager = new XWalkExtensionManager(this.cordova.getActivity(), this.cordova.getActivity());
-        extensionManager.loadExtensions();
-        jsMessageQueue = new NativeToJsMessageQueue(this, cordova);
-        exposedJsApi = new XwalkExposedJsApi(pluginManager, jsMessageQueue);
-        resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
-        exposeJsInterface();
-    }
-
-	/**
-	 * Override this method to decide whether or not you need to request the
-	 * focus when your application start
-	 * 
-	 * @return true unless this method is overriden to return a different value
-	 */
-    protected boolean shouldRequestFocusOnInit() {
-		return true;
-	}
-
-    private void exposeJsInterface() {
-        int SDK_INT = Build.VERSION.SDK_INT;
-        boolean isHoneycomb = (SDK_INT >= Build.VERSION_CODES.HONEYCOMB && SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2);
-        if (isHoneycomb || (SDK_INT < Build.VERSION_CODES.GINGERBREAD)) {
-            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
-            // use the prompt bridge instead.
-            return;            
-        } else if (SDK_INT < Build.VERSION_CODES.HONEYCOMB && Build.MANUFACTURER.equals("unknown")) {
-            // addJavascriptInterface crashes on the 2.3 emulator.
-            Log.i(TAG, "Disabled addJavascriptInterface() bridge callback due to a bug on the 2.3 emulator");
-            return;
-        }
-        this.addJavascriptInterface(exposedJsApi, "_cordovaNative");
-    }
-
-    /**
-     * Set the WebViewClient.
-     *
-     * @param client
-     */
-    public void setWebViewClient(XWalkCordovaWebViewClient client) {
-        this.viewClient = client;
-        super.setXWalkClient(client);
-    }
-
-    /**
-     * Set the WebChromeClient.
-     *
-     * @param client
-     */
-    public void setWebChromeClient(XwalkCordovaChromeClient client) {
-        this.chromeClient = client;
-        super.setXWalkWebChromeClient(client);
-    }
-    
-    public XwalkCordovaChromeClient 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 {
-
-            String initUrl = this.getProperty("url", null);
-
-            // If first page of app, then set URL to load to be the one passed in
-            if (initUrl == null) {
-                this.loadUrlIntoView(url);
-            }
-            // Otherwise use the URL specified in the activity's extras bundle
-            else {
-                this.loadUrlIntoView(initUrl);
-            }
-        }
-    }
-
-    /**
-     * 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 loadUrl(final String url, int time) {
-        String initUrl = this.getProperty("url", null);
-
-        // If first page of app, then set URL to load to be the one passed in
-        if (initUrl == null) {
-            this.loadUrlIntoView(url, time);
-        }
-        // Otherwise use the URL specified in the activity's extras bundle
-        else {
-            this.loadUrlIntoView(initUrl);
-        }
-    }
-
-    /**
-     * Load the url into the webview.
-     *
-     * @param url
-     */
-    public void loadUrlIntoView(final String url) {
-        LOG.d(TAG, ">>> loadUrl(" + url + ")");
-
-        this.url = url;
-        this.pluginManager.init();
-
-
-        // Create a timeout timer for loadUrl
-        final XWalkCordovaWebView me = this;
-        final int currentLoadUrlTimeout = me.loadUrlTimeout;
-        final int loadUrlTimeoutValue = Integer.parseInt(this.getProperty("LoadUrlTimeoutValue", "20000"));
-
-        // Timeout error method
-        final Runnable loadError = new Runnable() {
-            public void run() {
-                me.stopLoading();
-                LOG.e(TAG, "CordovaWebView: TIMEOUT ERROR!");
-                if (viewClient != null) {
-                    viewClient.onReceivedError((CordovaWebView) me, -6, "The connection to the server was unsuccessful.", url);
-                }
-            }
-        };
-
-        // Timeout timer method
-        final Runnable timeoutCheck = new Runnable() {
-            public void run() {
-                try {
-                    synchronized (this) {
-                        wait(loadUrlTimeoutValue);
-                    }
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
-                }
-
-                // If timeout, then stop loading and handle error
-                if (me.loadUrlTimeout == currentLoadUrlTimeout) {
-                    me.cordova.getActivity().runOnUiThread(loadError);
-                }
-            }
-        };
-
-        // Load url
-        this.cordova.getActivity().runOnUiThread(new Runnable() {
-            public void run() {
-                Thread thread = new Thread(timeoutCheck);
-                thread.start();
-                me.loadUrlNow(url);
-            }
-        });
-    }
-
-    /**
-     * Load URL in webview.
-     *
-     * @param url
-     */
-    public void loadUrlNow(String url) {
-        if (LOG.isLoggable(LOG.DEBUG) && !url.startsWith("javascript:")) {
-            LOG.d(TAG, ">>> loadUrlNow()");
-        }
-        if (url.startsWith("file://") || url.startsWith("javascript:") || Config.isUrlWhiteListed(url)) {
-            super.loadUrl(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
-     */
-    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);
-    }
-    
-    
-    public void onScrollChanged(int l, int t, int oldl, int oldt)
-    {
-        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);
-    }
-    
-    /**
-     * Send JavaScript statement back to JavaScript.
-     * (This is a convenience method)
-     *
-     * @param statement
-     */
-    public void sendJavascript(String statement) {
-        this.jsMessageQueue.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);
-    }
-
-    /**
-     * 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)
-     *
-     * @return true if we went back, false if we are already at top
-     */
-    public boolean backHistory() {
-
-        // Check webview first to see if there is a history
-        // This is needed to support curPage#diffLink, since they are added to appView's history, but not our history url array (JQMobile behavior)
-        if (super.canGoBack()) {
-            printBackForwardList();
-            super.goBack();
-            
-            return true;
-        }
-        return false;
-    }
-
-
-    /**
-     * Load the specified URL in the Cordova webview or a new browser instance.
-     *
-     * NOTE: If openExternal is false, only URLs listed in whitelist can be loaded.
-     *
-     * @param url           The url to load.
-     * @param openExternal  Load url in browser instead of Cordova webview.
-     * @param clearHistory  Clear the history stack, so new page becomes top of history
-     * @param params        Parameters for new app
-     */
-    public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap<String, Object> params) {
-        LOG.d(TAG, "showWebPage(%s, %b, %b, HashMap", url, openExternal, clearHistory);
-
-        // If clearing history
-        if (clearHistory) {
-            this.clearHistory();
-        }
-
-        // If loading into our webview
-        if (!openExternal) {
-
-            // Make sure url is in whitelist
-            if (url.startsWith("file://") || Config.isUrlWhiteListed(url)) {
-                // TODO: What about params?
-                // Load new URL
-                this.loadUrl(url);
-            }
-            // Load in default viewer if not
-            else {
-                LOG.w(TAG, "showWebPage: Cannot load URL into webview since it is not in white list.  Loading into browser instead. (URL=" + url + ")");
-                try {
-                    Intent intent = new Intent(Intent.ACTION_VIEW);
-                    intent.setData(Uri.parse(url));
-                    cordova.getActivity().startActivity(intent);
-                } catch (android.content.ActivityNotFoundException e) {
-                    LOG.e(TAG, "Error loading url " + url, e);
-                }
-            }
-        }
-
-        // Load in default view intent
-        else {
-            try {
-                Intent intent = new Intent(Intent.ACTION_VIEW);
-                intent.setData(Uri.parse(url));
-                cordova.getActivity().startActivity(intent);
-            } catch (android.content.ActivityNotFoundException e) {
-                LOG.e(TAG, "Error loading url " + url, e);
-            }
-        }
-    }
-
-    /**
-     * 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.
-     *
-     * @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
-     */
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event)
-    {
-        if(keyDownCodes.contains(keyCode))
-        {
-            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
-                    // only override default behavior is event bound
-                    LOG.d(TAG, "Down Key Hit");
-                    this.loadUrl("javascript:cordova.fireDocumentEvent('volumedownbutton');");
-                    return true;
-            }
-            // If volumeup key
-            else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
-                    LOG.d(TAG, "Up Key Hit");
-                    this.loadUrl("javascript:cordova.fireDocumentEvent('volumeupbutton');");
-                    return true;
-            }
-            else
-            {
-                return super.onKeyDown(keyCode, event);
-            }
-        }
-        else if(keyCode == KeyEvent.KEYCODE_BACK)
-        {
-            return !(this.startOfHistory()) || this.bound;
-        }
-        else if(keyCode == KeyEvent.KEYCODE_MENU)
-        {
-            //How did we get here?  Is there a childView?
-            View childView = (View) this.getFocusedChild();
-            if(childView != null)
-            {
-                //Make sure we close the keyboard if it's present
-                InputMethodManager imm = (InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
-                imm.hideSoftInputFromWindow(childView.getWindowToken(), 0);
-                cordova.getActivity().openOptionsMenu();
-                return true;
-            } else {
-                return super.onKeyDown(keyCode, event);
-            }
-        }
-        
-        return super.onKeyDown(keyCode, event);
-    }
-    
-
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event)
-    {
-        // If back key
-        if (keyCode == KeyEvent.KEYCODE_BACK) {
-            // A custom view is currently displayed  (e.g. playing a video)
-            if (this.isFullscreen()) {
-                this.exitFullscreen();
-                return true;
-            } else if (mCustomView != null) {
-                this.hideCustomView();
-                return true;
-            } else {
-                // The webview is currently displayed
-                // If back key is bound, then send event to JavaScript
-                if (this.bound) {
-                    this.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');");
-                    return true;
-                } else {
-                    // If not bound
-                    // Go to previous page in webview if it is possible to go back
-                    if (this.backHistory()) {
-                        return true;
-                    }
-                    // If not, then invoke default behaviour
-                    else {
-                        //this.activityState = ACTIVITY_EXITING;
-                    	//return false;
-                    	// If they hit back button when app is initializing, app should exit instead of hang until initilazation (CB2-458)
-                    	this.cordova.getActivity().finish();
-                    	return false;
-                    }
-                }
-            }
-        }
-        // Legacy
-        else if (keyCode == KeyEvent.KEYCODE_MENU) {
-            if (this.lastMenuEventTime < event.getEventTime()) {
-                this.loadUrl("javascript:cordova.fireDocumentEvent('menubutton');");
-            }
-            this.lastMenuEventTime = event.getEventTime();
-            return super.onKeyUp(keyCode, event);
-        }
-        // If search key
-        else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
-            this.loadUrl("javascript:cordova.fireDocumentEvent('searchbutton');");
-            return true;
-        }
-        else if(keyUpCodes.contains(keyCode))
-        {
-            //What the hell should this do?
-            return super.onKeyUp(keyCode, event);
-        }
-
-        //Does webkit change this behavior?
-        return super.onKeyUp(keyCode, event);
-    }
-
-    
-    public void bindButton(boolean override)
-    {
-        this.bound = override;
-    }
-
-    public void bindButton(String button, boolean override) {
-        // TODO Auto-generated method stub
-        if (button.compareTo("volumeup")==0) {
-          keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_UP);
-        }
-        else if (button.compareTo("volumedown")==0) {
-          keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_DOWN);
-        }
-      }
-
-    public void bindButton(int keyCode, boolean keyDown, boolean override) {
-       if(keyDown)
-       {
-           keyDownCodes.add(keyCode);
-       }
-       else
-       {
-           keyUpCodes.add(keyCode);
-       }
-    }
-
-    public boolean isBackButtonBound()
-    {
-        return this.bound;
-    }
-    
-    public void handlePause(boolean keepRunning)
-    {
-        LOG.d(TAG, "Handle the pause");
-        // Send pause event to JavaScript
-        this.loadUrl("javascript:try{cordova.fireDocumentEvent('pause');}catch(e){console.log('exception firing pause event from native');};");
-
-        // Forward to plugins
-        if (this.pluginManager != null) {
-            this.pluginManager.onPause(keepRunning);
-        }
-
-        if (this.extensionManager != null) {
-            this.extensionManager.onPause();
-        }
-
-        // If app doesn't want to run in background
-        if (!keepRunning) {
-            // 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
-        if (this.pluginManager != null) {
-            this.pluginManager.onResume(keepRunning);
-        }
-
-        if (this.extensionManager != null) {
-            this.extensionManager.onResume();
-        }
-
-        // Resume JavaScript timers (including setInterval)
-        this.resumeTimers();
-        paused = false;
-    }
-    
-    public void handleDestroy()
-    {
-        // Send destroy event to JavaScript
-        this.loadUrl("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};");
-
-        // Load blank page so that JavaScript onunload is called
-        this.loadUrl("about:blank");
-
-        // Forward to plugins
-        if (this.pluginManager != null) {
-            this.pluginManager.onDestroy();
-        }
-
-        if (this.extensionManager != null) {
-            this.extensionManager.onDestroy();
-        }
-        
-        // unregister the receiver
-        if (this.receiver != null) {
-            try {
-                this.cordova.getActivity().unregisterReceiver(this.receiver);
-            } catch (Exception e) {
-                Log.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e);
-            }
-        }
-    }
-    
-    public void onNewIntent(Intent intent)
-    {
-        //Forward to plugins
-        if (this.pluginManager != null) {
-            this.pluginManager.onNewIntent(intent);
-        }
-    }
-    
-    public boolean isPaused()
-    {
-        return paused;
-    }
-
-    public boolean hadKeyEvent() {
-        return handleButton;
-    }
-
-    // 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)
-    private static class Level16Apis {
-        static void enableUniversalAccess(XWalkSettings settings) {
-            settings.setAllowUniversalAccessFromFileURLs(true);
-        }
-    }
-    
-    public void printBackForwardList() {
-        WebBackForwardList currentList = this.copyBackForwardList();
-        int currentSize = currentList.getSize();
-        for(int i = 0; i < currentSize; ++i)
-        {
-            WebHistoryItem item = currentList.getItemAtIndex(i);
-            String url = item.getUrl();
-            LOG.d(TAG, "The URL at index: " + Integer.toString(i) + " is " + url );
-        }
-    }
-    
-    
-    //Can Go Back is BROKEN!
-    public boolean startOfHistory()
-    {
-        WebBackForwardList currentList = this.copyBackForwardList();
-        WebHistoryItem item = currentList.getItemAtIndex(0);
-        if( item!=null){	// Null-fence in case they haven't called loadUrl yet (CB-2458)
-	        String url = item.getUrl();
-	        String currentUrl = this.getUrl();
-	        LOG.d(TAG, "The current URL is: " + currentUrl);
-	        LOG.d(TAG, "The URL at item 0 is: " + url);
-	        return currentUrl.equals(url);
-        }
-        return false;
-    }
-
-    public void showCustomView(View view, XWalkWebChromeClient.CustomViewCallback callback) {
-        // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
-        Log.d(TAG, "showing Custom View");
-        // if a view already exists then immediately terminate the new one
-        if (mCustomView != null) {
-            callback.onCustomViewHidden();
-            return;
-        }
-        
-        // Store the view and its callback for later (to kill it properly)
-        mCustomView = view;
-        mCustomViewCallback = callback;
-        
-        // Add the custom view to its container.
-        ViewGroup parent = (ViewGroup) this.getParent();
-        parent.addView(view, COVER_SCREEN_GRAVITY_CENTER);
-        
-        // Hide the content view.
-        this.setVisibility(View.GONE);
-        
-        // Finally show the custom view container.
-        parent.setVisibility(View.VISIBLE);
-        parent.bringToFront();
-    }
-
-    public void hideCustomView() {
-        // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
-        Log.d(TAG, "Hidding Custom View");
-        if (mCustomView == null) return;
-
-        // Hide the custom view.
-        mCustomView.setVisibility(View.GONE);
-        
-        // Remove the custom view from its container.
-        ViewGroup parent = (ViewGroup) this.getParent();
-        parent.removeView(mCustomView);
-        mCustomView = null;
-        mCustomViewCallback.onCustomViewHidden();
-        
-        // Show the content view.
-        this.setVisibility(View.VISIBLE);
-    }
-    
-    /**
-     * if the video overlay is showing then we need to know 
-     * as it effects back button handling
-     * 
-     * @return true if custom view is showing
-     */
-    public boolean isCustomViewShowing() {
-        return mCustomView != null;
-    }
-    
-    public WebBackForwardList restoreState(Bundle savedInstanceState)
-    {
-        WebBackForwardList myList = super.restoreState(savedInstanceState);
-        Log.d(TAG, "WebView restoration crew now restoring!");
-        //Initialize the plugin manager once more
-        this.pluginManager.init();
-        return myList;
-    }
-
-    public void storeResult(int requestCode, int resultCode, Intent intent) {
-        mResult = new ActivityResult(requestCode, resultCode, intent);
-    }
-    
-    public CordovaResourceApi getResourceApi() {
-        return resourceApi;
-    }
-
-    @Override
-    public void setWebViewClient(CordovaWebViewClient webViewClient) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public void setWebChromeClient(CordovaChromeClient webChromeClient) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public void setId(int i) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public void setLayoutParams(LayoutParams layoutParams) {
-        // TODO Figure out how the XWalk gets laid out.  This is goofy! 
-    }
-
-    @Override
-    public void setVisibility(int invisible) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public boolean canGoBack() {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void clearCache(boolean b) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public void clearHistory() {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public void addJavascript(String statement) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public CordovaPlugin getPlugin(String initCallbackClass) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public View getFocusedChild() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public String exec(String service, String action, String callbackId,
-            String message) throws JSONException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void setNativeToJsBridgeMode(int parseInt) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public String retrieveJsMessages(boolean equals) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void showCustomView(View view, CustomViewCallback callback) {
-        // TODO Auto-generated method stub
-        
-    }
-
-
-
-    @Override
-    public boolean onOverrideUrlLoading(String url) {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void resetJsMessageQueue() {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public void onReset() {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public int getVisibility() {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public void incUrlTimeout() {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public void setOverScrollMode(int overScrollNever) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public void setNetworkAvailable(boolean online) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public PluginManager getPluginManager() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void setLayoutParams(
-            android.widget.LinearLayout.LayoutParams layoutParams) {
-        // TODO Auto-generated method stub
-        
-    }
-}

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/bd806a34/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebViewClient.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebViewClient.java b/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebViewClient.java
deleted file mode 100755
index 262ae91..0000000
--- a/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebViewClient.java
+++ /dev/null
@@ -1,636 +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.engine.crosswalk;
-
-import java.io.ByteArrayInputStream;
-import java.util.Hashtable;
-
-import org.apache.cordova.AuthenticationToken;
-import org.apache.cordova.Config;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.CordovaWebViewClient;
-import org.apache.cordova.LOG;
-import org.apache.cordova.NativeToJsMessageQueue;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.annotation.TargetApi;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.net.http.SslError;
-import android.util.Log;
-import android.view.View;
-//import android.webkit.HttpAuthHandler;
-//import android.webkit.SslErrorHandler;
-import android.webkit.WebResourceResponse;
-
-
-
-
-
-//import android.webkit.WebView;
-//import android.webkit.WebViewClient;
-import org.chromium.net.NetError;
-import org.xwalk.core.XWalkView;
-import org.xwalk.core.XWalkClient;
-import org.xwalk.core.XWalkHttpAuthHandler;
-import org.xwalk.core.SslErrorHandler;
-
-/**
- * This class is the WebViewClient that implements callbacks for our web view.
- * The kind of callbacks that happen here are regarding the rendering of the
- * document instead of the chrome surrounding it, such as onPageStarted(), 
- * shouldOverrideUrlLoading(), etc. Related to but different than
- * CordovaChromeClient.
- *
- * @see <a href="http://developer.android.com/reference/android/webkit/WebViewClient.html">WebViewClient</a>
- * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
- * @see XwalkCordovaChromeClient
- * @see XWalkCordovaWebView
- */
-public class XWalkCordovaWebViewClient extends XWalkClient implements CordovaWebViewClient {
-
-	private static final String TAG = "CordovaWebViewClient";
-	private static final String CORDOVA_EXEC_URL_PREFIX = "http://cdv_exec/";
-    CordovaInterface cordova;
-    XWalkCordovaWebView appView;
-    private boolean doClearHistory = false;
-
-    // Success
-    public static final int ERROR_OK = 0;
-    // Generic error
-    public static final int ERROR_UNKNOWN = -1;
-    // Server or proxy hostname lookup failed
-    public static final int ERROR_HOST_LOOKUP = -2;
-    // Unsupported authentication scheme (not basic or digest)
-    public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3;
-    // User authentication failed on server
-    public static final int ERROR_AUTHENTICATION = -4;
-    // User authentication failed on proxy
-    public static final int ERROR_PROXY_AUTHENTICATION = -5;
-    // Failed to connect to the server
-    public static final int ERROR_CONNECT = -6;
-    // Failed to read or write to the server
-    public static final int ERROR_IO = -7;
-    // Connection timed out
-    public static final int ERROR_TIMEOUT = -8;
-    // Too many redirects
-    public static final int ERROR_REDIRECT_LOOP = -9;
-    // Unsupported URI scheme
-    public static final int ERROR_UNSUPPORTED_SCHEME = -10;
-    // Failed to perform SSL handshake
-    public static final int ERROR_FAILED_SSL_HANDSHAKE = -11;
-    // Malformed URL
-    public static final int ERROR_BAD_URL = -12;
-    // Generic file error
-    public static final int ERROR_FILE = -13;
-    // File not found
-    public static final int ERROR_FILE_NOT_FOUND = -14;
-    // Too many requests during this load
-    public static final int ERROR_TOO_MANY_REQUESTS = -15;
-
-    /** The authorization tokens. */
-    private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
-
-    /**
-     * Constructor.
-     *
-     * @param cordova
-     */
-    public XWalkCordovaWebViewClient(CordovaInterface cordova) {
-        this.cordova = cordova;
-    }
-
-    /**
-     * Constructor.
-     *
-     * @param cordova
-     * @param view
-     */
-    public XWalkCordovaWebViewClient(CordovaInterface cordova, XWalkCordovaWebView view) {
-        this.cordova = cordova;
-        this.appView = view;
-    }
-
-    /**
-     * Constructor.
-     *
-     * @param view
-     */
-    public void setWebView(XWalkCordovaWebView view) {
-        this.appView = view;
-    }
-
-
-    // Parses commands sent by setting the webView's URL to:
-    // cdvbrg:service/action/callbackId#jsonArgs
-	private void handleExecUrl(String url) {
-		int idx1 = CORDOVA_EXEC_URL_PREFIX.length();
-		int idx2 = url.indexOf('#', idx1 + 1);
-		int idx3 = url.indexOf('#', idx2 + 1);
-		int idx4 = url.indexOf('#', idx3 + 1);
-		if (idx1 == -1 || idx2 == -1 || idx3 == -1 || idx4 == -1) {
-			Log.e(TAG, "Could not decode URL command: " + url);
-			return;
-		}
-		String service    = url.substring(idx1, idx2);
-		String action     = url.substring(idx2 + 1, idx3);
-		String callbackId = url.substring(idx3 + 1, idx4);
-		String jsonArgs   = url.substring(idx4 + 1);
-        appView.pluginManager.exec(service, action, callbackId, jsonArgs);
-	}
-
-    // Map XWalk error code about loading a page to Android specific ones.
-    // XWalk shares the error code with chromium currently.
-    private int convertErrorCode(int netError) {
-        // Note: many NetError.Error constants don't have an obvious mapping.
-        // These will be handled by the default case, ERROR_UNKNOWN.
-        switch (netError) {
-            case NetError.ERR_UNSUPPORTED_AUTH_SCHEME:
-                return ERROR_UNSUPPORTED_AUTH_SCHEME;
-
-            case NetError.ERR_INVALID_AUTH_CREDENTIALS:
-            case NetError.ERR_MISSING_AUTH_CREDENTIALS:
-            case NetError.ERR_MISCONFIGURED_AUTH_ENVIRONMENT:
-                return ERROR_AUTHENTICATION;
-
-            case NetError.ERR_TOO_MANY_REDIRECTS:
-                return ERROR_REDIRECT_LOOP;
-
-            case NetError.ERR_UPLOAD_FILE_CHANGED:
-                return ERROR_FILE_NOT_FOUND;
-
-            case NetError.ERR_INVALID_URL:
-                return ERROR_BAD_URL;
-
-            case NetError.ERR_DISALLOWED_URL_SCHEME:
-            case NetError.ERR_UNKNOWN_URL_SCHEME:
-                return ERROR_UNSUPPORTED_SCHEME;
-
-            case NetError.ERR_IO_PENDING:
-            case NetError.ERR_NETWORK_IO_SUSPENDED:
-                return ERROR_IO;
-
-            case NetError.ERR_CONNECTION_TIMED_OUT:
-            case NetError.ERR_TIMED_OUT:
-                return ERROR_TIMEOUT;
-
-            case NetError.ERR_FILE_TOO_BIG:
-                return ERROR_FILE;
-
-            case NetError.ERR_HOST_RESOLVER_QUEUE_TOO_LARGE:
-            case NetError.ERR_INSUFFICIENT_RESOURCES:
-            case NetError.ERR_OUT_OF_MEMORY:
-                return ERROR_TOO_MANY_REQUESTS;
-
-            case NetError.ERR_CONNECTION_CLOSED:
-            case NetError.ERR_CONNECTION_RESET:
-            case NetError.ERR_CONNECTION_REFUSED:
-            case NetError.ERR_CONNECTION_ABORTED:
-            case NetError.ERR_CONNECTION_FAILED:
-            case NetError.ERR_SOCKET_NOT_CONNECTED:
-                return ERROR_CONNECT;
-
-            case NetError.ERR_INTERNET_DISCONNECTED:
-            case NetError.ERR_ADDRESS_INVALID:
-            case NetError.ERR_ADDRESS_UNREACHABLE:
-            case NetError.ERR_NAME_NOT_RESOLVED:
-            case NetError.ERR_NAME_RESOLUTION_FAILED:
-                return ERROR_HOST_LOOKUP;
-
-            case NetError.ERR_SSL_PROTOCOL_ERROR:
-            case NetError.ERR_SSL_CLIENT_AUTH_CERT_NEEDED:
-            case NetError.ERR_TUNNEL_CONNECTION_FAILED:
-            case NetError.ERR_NO_SSL_VERSIONS_ENABLED:
-            case NetError.ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
-            case NetError.ERR_SSL_RENEGOTIATION_REQUESTED:
-            case NetError.ERR_CERT_ERROR_IN_SSL_RENEGOTIATION:
-            case NetError.ERR_BAD_SSL_CLIENT_AUTH_CERT:
-            case NetError.ERR_SSL_NO_RENEGOTIATION:
-            case NetError.ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
-            case NetError.ERR_SSL_BAD_RECORD_MAC_ALERT:
-            case NetError.ERR_SSL_UNSAFE_NEGOTIATION:
-            case NetError.ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY:
-            case NetError.ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED:
-            case NetError.ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY:
-                return ERROR_FAILED_SSL_HANDSHAKE;
-
-            case NetError.ERR_PROXY_AUTH_UNSUPPORTED:
-            case NetError.ERR_PROXY_AUTH_REQUESTED:
-            case NetError.ERR_PROXY_CONNECTION_FAILED:
-            case NetError.ERR_UNEXPECTED_PROXY_AUTH:
-                return ERROR_PROXY_AUTHENTICATION;
-
-            // The certificate errors are handled by onReceivedSslError
-            // and don't need to be reported here.
-            case NetError.ERR_CERT_COMMON_NAME_INVALID:
-            case NetError.ERR_CERT_DATE_INVALID:
-            case NetError.ERR_CERT_AUTHORITY_INVALID:
-            case NetError.ERR_CERT_CONTAINS_ERRORS:
-            case NetError.ERR_CERT_NO_REVOCATION_MECHANISM:
-            case NetError.ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
-            case NetError.ERR_CERT_REVOKED:
-            case NetError.ERR_CERT_INVALID:
-            case NetError.ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
-            case NetError.ERR_CERT_NON_UNIQUE_NAME:
-                return ERROR_OK;
-
-            default:
-                return ERROR_UNKNOWN;
-        }
-    }
-
-    /**
-     * Give the host application a chance to take over the control when a new url
-     * is about to be loaded in the current WebView.
-     *
-     * @param view          The WebView that is initiating the callback.
-     * @param url           The url to be loaded.
-     * @return              true to override, false for default behavior
-     */
-	@Override
-    public boolean shouldOverrideUrlLoading(XWalkView view, String url) {
-    	// Check if it's an exec() bridge command message.
-    	if (NativeToJsMessageQueue.ENABLE_LOCATION_CHANGE_EXEC_MODE && url.startsWith(CORDOVA_EXEC_URL_PREFIX)) {
-    		handleExecUrl(url);
-    	}
-
-        // Give plugins the chance to handle the url
-    	else if ((this.appView.pluginManager != null) && this.appView.pluginManager.onOverrideUrlLoading(url)) {
-        }
-
-        // If dialing phone (tel:5551212)
-        else if (url.startsWith("tel:")) {
-            try {
-                Intent intent = new Intent(Intent.ACTION_DIAL);
-                intent.setData(Uri.parse(url));
-                this.cordova.getActivity().startActivity(intent);
-            } catch (android.content.ActivityNotFoundException e) {
-                LOG.e(TAG, "Error dialing " + url + ": " + e.toString());
-            }
-        }
-
-        // If displaying map (geo:0,0?q=address)
-        else if (url.startsWith("geo:")) {
-            try {
-                Intent intent = new Intent(Intent.ACTION_VIEW);
-                intent.setData(Uri.parse(url));
-                this.cordova.getActivity().startActivity(intent);
-            } catch (android.content.ActivityNotFoundException e) {
-                LOG.e(TAG, "Error showing map " + url + ": " + e.toString());
-            }
-        }
-
-        // If sending email (mailto:abc@corp.com)
-        else if (url.startsWith("mailto:")) {
-            try {
-                Intent intent = new Intent(Intent.ACTION_VIEW);
-                intent.setData(Uri.parse(url));
-                this.cordova.getActivity().startActivity(intent);
-            } catch (android.content.ActivityNotFoundException e) {
-                LOG.e(TAG, "Error sending email " + url + ": " + e.toString());
-            }
-        }
-
-        // If sms:5551212?body=This is the message
-        else if (url.startsWith("sms:")) {
-            try {
-                Intent intent = new Intent(Intent.ACTION_VIEW);
-
-                // Get address
-                String address = null;
-                int parmIndex = url.indexOf('?');
-                if (parmIndex == -1) {
-                    address = url.substring(4);
-                }
-                else {
-                    address = url.substring(4, parmIndex);
-
-                    // If body, then set sms body
-                    Uri uri = Uri.parse(url);
-                    String query = uri.getQuery();
-                    if (query != null) {
-                        if (query.startsWith("body=")) {
-                            intent.putExtra("sms_body", query.substring(5));
-                        }
-                    }
-                }
-                intent.setData(Uri.parse("sms:" + address));
-                intent.putExtra("address", address);
-                intent.setType("vnd.android-dir/mms-sms");
-                this.cordova.getActivity().startActivity(intent);
-            } catch (android.content.ActivityNotFoundException e) {
-                LOG.e(TAG, "Error sending sms " + url + ":" + e.toString());
-            }
-        }
-        
-        //Android Market
-        else if(url.startsWith("market:")) {
-            try {
-                Intent intent = new Intent(Intent.ACTION_VIEW);
-                intent.setData(Uri.parse(url));
-                this.cordova.getActivity().startActivity(intent);
-            } catch (android.content.ActivityNotFoundException e) {
-                LOG.e(TAG, "Error loading Google Play Store: " + url, e);
-            }
-        }
-
-        // All else
-        else {
-
-            // If our app or file:, then load into a new Cordova webview container by starting a new instance of our activity.
-            // Our app continues to run.  When BACK is pressed, our app is redisplayed.
-            if (url.startsWith("file://") || url.startsWith("data:")  || Config.isUrlWhiteListed(url)) {
-                return false;
-            }
-
-            // If not our application, let default viewer handle
-            else {
-                try {
-                    Intent intent = new Intent(Intent.ACTION_VIEW);
-                    intent.setData(Uri.parse(url));
-                    this.cordova.getActivity().startActivity(intent);
-                } catch (android.content.ActivityNotFoundException e) {
-                    LOG.e(TAG, "Error loading url " + url, e);
-                }
-            }
-        }
-        return true;
-    }
-    
-    /**
-     * 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(XWalkView view, XWalkHttpAuthHandler handler, String host, String realm) {
-
-        // Get the authentication token
-        AuthenticationToken token = this.getAuthenticationToken(host, realm);
-        if (token != null) {
-            handler.proceed(token.getUserName(), token.getPassword());
-        }
-        else {
-            // Handle 401 like we'd normally do!
-            super.onReceivedHttpAuthRequest(view, handler, host, realm);
-        }
-    }
-
-    /**
-     * Notify the host application that a page has started loading.
-     * This method is called once for each main frame load so a page with iframes or framesets will call onPageStarted
-     * one time for the main frame. This also means that onPageStarted will not be called when the contents of an
-     * embedded frame changes, i.e. clicking a link whose target is an iframe.
-     *
-     * @param view          The webview initiating the callback.
-     * @param url           The url of the page.
-     */
-    @Override
-    public void onPageStarted(XWalkView view, String url, Bitmap favicon) {
-
-        // Flush stale messages.
-        this.appView.resetJsMessageQueue();
-
-        // Broadcast message that page has loaded
-        this.appView.postMessage("onPageStarted", url);
-
-        // Notify all plugins of the navigation, so they can clean up if necessary.
-        if (this.appView.pluginManager != null) {
-            this.appView.pluginManager.onReset();
-        }
-    }
-
-    /**
-     * Notify the host application that a page has finished loading.
-     * This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet.
-     *
-     *
-     * @param view          The webview initiating the callback.
-     * @param url           The url of the page.
-     */
-    @Override
-    public void onPageFinished(XWalkView view, String url) {
-        super.onPageFinished(view, url);
-        LOG.d(TAG, "onPageFinished(" + url + ")");
-
-        /**
-         * Because of a timing issue we need to clear this history in onPageFinished as well as
-         * onPageStarted. However we only want to do this if the doClearHistory boolean is set to
-         * true. You see when you load a url with a # in it which is common in jQuery applications
-         * onPageStared is not called. Clearing the history at that point would break jQuery apps.
-         */
-        if (this.doClearHistory) {
-            view.clearHistory();
-            this.doClearHistory = false;
-        }
-
-        // Clear timeout flag
-        this.appView.loadUrlTimeout++;
-
-        // Broadcast message that page has loaded
-        this.appView.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) {
-            Thread t = new Thread(new Runnable() {
-                public void run() {
-                    try {
-                        Thread.sleep(2000);
-                        cordova.getActivity().runOnUiThread(new Runnable() {
-                            public void run() {
-                                appView.postMessage("spinner", "stop");
-                            }
-                        });
-                    } catch (InterruptedException e) {
-                    }
-                }
-            });
-            t.start();
-        }
-
-        // Shutdown if blank loaded
-        if (url.equals("about:blank")) {
-            appView.postMessage("exit", null);
-        }
-    }
-
-    /**
-     * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
-     * The errorCode parameter corresponds to one of the ERROR_* constants.
-     *
-     * @param view          The WebView that is initiating the callback.
-     * @param errorCode     The error code corresponding to an ERROR_* value.
-     * @param description   A String describing the error.
-     * @param failingUrl    The url that failed to load.
-     */
-    @Override
-    public void onReceivedError(XWalkView view, int errorCode, String description, String failingUrl) {
-        LOG.d(TAG, "CordovaWebViewClient.onReceivedError: Error code=%s Description=%s URL=%s", errorCode, description, failingUrl);
-
-        // Clear timeout flag
-        this.appView.loadUrlTimeout++;
-
-        // Convert the XWalk error code to Cordova error code, which follows the Android spec,
-        // http://developer.android.com/reference/android/webkit/WebViewClient.html.
-        errorCode = convertErrorCode(errorCode);
-
-        // Handle error
-        JSONObject data = new JSONObject();
-        try {
-            data.put("errorCode", errorCode);
-            data.put("description", description);
-            data.put("url", failingUrl);
-        } catch (JSONException e) {
-            e.printStackTrace();
-        }
-        this.appView.postMessage("onReceivedError", data);
-    }
-
-    /**
-     * Notify the host application that an SSL error occurred while loading a resource.
-     * The host application must call either handler.cancel() or handler.proceed().
-     * Note that the decision may be retained for use in response to future SSL errors.
-     * The default behavior is to cancel the load.
-     *
-     * @param view          The WebView that is initiating the callback.
-     * @param handler       An SslErrorHandler object that will handle the user's response.
-     * @param error         The SSL error object.
-     */
-    @TargetApi(8)
-    @Override
-    public void onReceivedSslError(XWalkView view, SslErrorHandler handler, SslError error) {
-
-        final String packageName = this.cordova.getActivity().getPackageName();
-        final PackageManager pm = this.cordova.getActivity().getPackageManager();
-
-        ApplicationInfo appInfo;
-        try {
-            appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
-            if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
-                // debug = true
-                handler.proceed();
-                return;
-            } else {
-                // debug = false
-                super.onReceivedSslError(view, handler, error);
-            }
-        } catch (NameNotFoundException e) {
-            // When it doubt, lock it out!
-            super.onReceivedSslError(view, handler, error);
-        }
-    }
-
-
-    /**
-     * Sets the authentication token.
-     *
-     * @param authenticationToken
-     * @param host
-     * @param realm
-     */
-    public void setAuthenticationToken(AuthenticationToken authenticationToken, String host, String realm) {
-        if (host == null) {
-            host = "";
-        }
-        if (realm == null) {
-            realm = "";
-        }
-        this.authenticationTokens.put(host.concat(realm), authenticationToken);
-    }
-
-    /**
-     * Removes the authentication token.
-     *
-     * @param host
-     * @param realm
-     *
-     * @return the authentication token or null if did not exist
-     */
-    public AuthenticationToken removeAuthenticationToken(String host, String realm) {
-        return this.authenticationTokens.remove(host.concat(realm));
-    }
-
-    /**
-     * Gets the authentication token.
-     *
-     * In order it tries:
-     * 1- host + realm
-     * 2- host
-     * 3- realm
-     * 4- no host, no realm
-     *
-     * @param host
-     * @param realm
-     *
-     * @return the authentication token
-     */
-    public AuthenticationToken getAuthenticationToken(String host, String realm) {
-        AuthenticationToken token = null;
-        token = this.authenticationTokens.get(host.concat(realm));
-
-        if (token == null) {
-            // try with just the host
-            token = this.authenticationTokens.get(host);
-
-            // Try the realm
-            if (token == null) {
-                token = this.authenticationTokens.get(realm);
-            }
-
-            // if no host found, just query for default
-            if (token == null) {
-                token = this.authenticationTokens.get("");
-            }
-        }
-
-        return token;
-    }
-
-    /**
-     * Clear all authentication tokens.
-     */
-    public void clearAuthenticationTokens() {
-        this.authenticationTokens.clear();
-    }
-
-    @Override
-    public void setWebView(CordovaWebView appView) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public void onReceivedError(CordovaWebView me, int i, String string,
-            String url) {
-        //This should work, but may run into casting errors! 
-        this.onReceivedError((XWalkView) me, i, string, url);
-        
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/bd806a34/framework/src/org/apache/cordova/engine/crosswalk/XwalkCordovaChromeClient.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/engine/crosswalk/XwalkCordovaChromeClient.java b/framework/src/org/apache/cordova/engine/crosswalk/XwalkCordovaChromeClient.java
deleted file mode 100755
index 342011e..0000000
--- a/framework/src/org/apache/cordova/engine/crosswalk/XwalkCordovaChromeClient.java
+++ /dev/null
@@ -1,428 +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.engine.crosswalk;
-
-import org.apache.cordova.Config;
-import org.apache.cordova.CordovaChromeClient;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.CordovaWebViewClient;
-import org.apache.cordova.LOG;
-import org.json.JSONArray;
-import org.json.JSONException;
-
-import android.annotation.TargetApi;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.Uri;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.webkit.ConsoleMessage;
-
-
-
-
-//import android.webkit.JsPromptResult;
-//import android.webkit.JsResult;
-import org.xwalk.core.JsPromptResult;
-import org.xwalk.core.JsResult;
-
-import android.webkit.ValueCallback;
-
-
-
-
-//import android.webkit.WebChromeClient;
-import org.xwalk.core.XWalkWebChromeClient;
-import org.xwalk.core.client.XWalkDefaultWebChromeClient;
-
-import android.webkit.WebStorage;
-
-
-
-
-//import android.webkit.WebView;
-import org.xwalk.core.XWalkView;
-import org.xwalk.core.XWalkGeolocationPermissions;
-
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-
-/**
- * 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,
- * such as onCreateWindow(), onConsoleMessage(), onProgressChanged(), etc. Related
- * to but different than CordovaWebViewClient.
- *
- * @see <a href="http://developer.android.com/reference/android/webkit/WebChromeClient.html">WebChromeClient</a>
- * @see <a href="http://developer.android.com/guide/webapps/webview.html">WebView guide</a>
- * @see XWalkCordovaWebViewClient
- * @see XWalkCordovaWebView
- */
-public class XwalkCordovaChromeClient extends XWalkDefaultWebChromeClient implements CordovaChromeClient {
-
-    public static final int FILECHOOSER_RESULTCODE = 5173;
-    private static final String LOG_TAG = "CordovaChromeClient";
-    private String TAG = "CordovaLog";
-    private long MAX_QUOTA = 100 * 1024 * 1024;
-    protected CordovaInterface cordova;
-    protected XWalkCordovaWebView appView;
-
-    // the video progress view
-    private View mVideoProgressView;
-    
-    // File Chooser
-    public ValueCallback<Uri> mUploadMessage;
-    
-    /**
-     * Constructor.
-     *
-     * @param cordova
-     */
-    public XwalkCordovaChromeClient(CordovaInterface cordova) {
-        super(cordova.getActivity(), null);
-        this.cordova = cordova;
-    }
-
-    /**
-     * Constructor.
-     * 
-     * @param ctx
-     * @param app
-     */
-    public XwalkCordovaChromeClient(CordovaInterface ctx, XWalkCordovaWebView app) {
-        super(ctx.getActivity(), app);
-        this.cordova = ctx;
-        this.appView = app;
-    }
-
-    /**
-     * Constructor.
-     * 
-     * @param view
-     */
-    public void setWebView(XWalkCordovaWebView view) {
-        this.appView = view;
-    }
-
-    /**
-     * Tell the client to display a javascript alert dialog.
-     *
-     * @param view
-     * @param url
-     * @param message
-     * @param result
-     */
-    @Override
-    public boolean onJsAlert(XWalkView view, String url, String message, final JsResult result) {
-        AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
-        dlg.setMessage(message);
-        dlg.setTitle("Alert");
-        //Don't let alerts break the back button
-        dlg.setCancelable(true);
-        dlg.setPositiveButton(android.R.string.ok,
-                new AlertDialog.OnClickListener() {
-                    public void onClick(DialogInterface dialog, int which) {
-                        result.confirm();
-                    }
-                });
-        dlg.setOnCancelListener(
-                new DialogInterface.OnCancelListener() {
-                    public void onCancel(DialogInterface dialog) {
-                        result.cancel();
-                    }
-                });
-        dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
-            //DO NOTHING
-            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
-                if (keyCode == KeyEvent.KEYCODE_BACK)
-                {
-                    result.confirm();
-                    return false;
-                }
-                else
-                    return true;
-            }
-        });
-        dlg.create();
-        dlg.show();
-        return true;
-    }
-
-    /**
-     * Tell the client to display a confirm dialog to the user.
-     *
-     * @param view
-     * @param url
-     * @param message
-     * @param result
-     */
-    @Override
-    public boolean onJsConfirm(XWalkView view, String url, String message, final JsResult result) {
-        AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
-        dlg.setMessage(message);
-        dlg.setTitle("Confirm");
-        dlg.setCancelable(true);
-        dlg.setPositiveButton(android.R.string.ok,
-                new DialogInterface.OnClickListener() {
-                    public void onClick(DialogInterface dialog, int which) {
-                        result.confirm();
-                    }
-                });
-        dlg.setNegativeButton(android.R.string.cancel,
-                new DialogInterface.OnClickListener() {
-                    public void onClick(DialogInterface dialog, int which) {
-                        result.cancel();
-                    }
-                });
-        dlg.setOnCancelListener(
-                new DialogInterface.OnCancelListener() {
-                    public void onCancel(DialogInterface dialog) {
-                        result.cancel();
-                    }
-                });
-        dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
-            //DO NOTHING
-            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
-                if (keyCode == KeyEvent.KEYCODE_BACK)
-                {
-                    result.cancel();
-                    return false;
-                }
-                else
-                    return true;
-            }
-        });
-        dlg.create();
-        dlg.show();
-        return true;
-    }
-
-    /**
-     * Tell the client to display a prompt dialog to the user.
-     * If the client returns true, WebView will assume that the client will
-     * handle the prompt dialog and call the appropriate JsPromptResult method.
-     *
-     * Since we are hacking prompts for our own purposes, we should not be using them for
-     * this purpose, perhaps we should hack console.log to do this instead!
-     *
-     * @param view
-     * @param url
-     * @param message
-     * @param defaultValue
-     * @param result
-     */
-    @Override
-    public boolean onJsPrompt(XWalkView view, String url, String message, String defaultValue, JsPromptResult result) {
-
-        // Security check to make sure any requests are coming from the page initially
-        // loaded in webview and not another loaded in an iframe.
-        boolean reqOk = false;
-        if (url.startsWith("file://") || Config.isUrlWhiteListed(url)) {
-            reqOk = true;
-        }
-
-        // Calling PluginManager.exec() to call a native service using 
-        // prompt(this.stringify(args), "gap:"+this.stringify([service, action, callbackId, true]));
-        if (reqOk && defaultValue != null && defaultValue.length() > 3 && defaultValue.substring(0, 4).equals("gap:")) {
-            JSONArray array;
-            try {
-                array = new JSONArray(defaultValue.substring(4));
-                String service = array.getString(0);
-                String action = array.getString(1);
-                String callbackId = array.getString(2);
-                String r = this.appView.exec(service, action, callbackId, message);
-                result.confirm(r == null ? "" : r);
-            } catch (JSONException e) {
-                e.printStackTrace();
-                return false;
-            }
-        }
-
-        // Sets the native->JS bridge mode. 
-        else if (reqOk && defaultValue != null && defaultValue.equals("gap_bridge_mode:")) {
-        	try {
-                this.appView.setNativeToJsBridgeMode(Integer.parseInt(message));
-                result.confirm("");
-        	} catch (NumberFormatException e){
-                result.confirm("");
-                e.printStackTrace();
-        	}
-        }
-
-        // Polling for JavaScript messages 
-        else if (reqOk && defaultValue != null && defaultValue.equals("gap_poll:")) {
-            String r = this.appView.retrieveJsMessages("1".equals(message));
-            result.confirm(r == null ? "" : r);
-        }
-
-        // Do NO-OP so older code doesn't display dialog
-        else if (defaultValue != null && defaultValue.equals("gap_init:")) {
-            result.confirm("OK");
-        }
-
-        // Show dialog
-        else {
-            final JsPromptResult res = result;
-            AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity());
-            dlg.setMessage(message);
-            final EditText input = new EditText(this.cordova.getActivity());
-            if (defaultValue != null) {
-                input.setText(defaultValue);
-            }
-            dlg.setView(input);
-            dlg.setCancelable(false);
-            dlg.setPositiveButton(android.R.string.ok,
-                    new DialogInterface.OnClickListener() {
-                        public void onClick(DialogInterface dialog, int which) {
-                            String usertext = input.getText().toString();
-                            res.confirm(usertext);
-                        }
-                    });
-            dlg.setNegativeButton(android.R.string.cancel,
-                    new DialogInterface.OnClickListener() {
-                        public void onClick(DialogInterface dialog, int which) {
-                            res.cancel();
-                        }
-                    });
-            dlg.create();
-            dlg.show();
-        }
-        return true;
-    }
-
-    /**
-     * Handle database quota exceeded notification.
-     */
-    @Override
-    public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
-            long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
-    {
-        LOG.d(TAG, "onExceededDatabaseQuota estimatedSize: %d  currentQuota: %d  totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
-        quotaUpdater.updateQuota(MAX_QUOTA);
-    }
-
-    // console.log in api level 7: http://developer.android.com/guide/developing/debug-tasks.html
-    // Expect this to not compile in a future Android release!
-    @SuppressWarnings("deprecation")
-    @Override
-    public void onConsoleMessage(String message, int lineNumber, String sourceID)
-    {
-        //This is only for Android 2.1
-        if(android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.ECLAIR_MR1)
-        {
-            LOG.d(TAG, "%s: Line %d : %s", sourceID, lineNumber, message);
-            super.onConsoleMessage(message, lineNumber, sourceID);
-        }
-    }
-
-    @TargetApi(8)
-    @Override
-    public boolean onConsoleMessage(ConsoleMessage consoleMessage)
-    {
-        if (consoleMessage.message() != null)
-            LOG.d(TAG, "%s: Line %d : %s" , consoleMessage.sourceId() , consoleMessage.lineNumber(), consoleMessage.message());
-         return super.onConsoleMessage(consoleMessage);
-    }
-
-    @Override
-    /**
-     * Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin.
-     *
-     * @param origin
-     * @param callback
-     */
-    public void onGeolocationPermissionsShowPrompt(String origin, XWalkGeolocationPermissions.Callback callback) {
-        super.onGeolocationPermissionsShowPrompt(origin, callback);
-        callback.invoke(origin, true, false);
-    }
-    
-    // API level 7 is required for this, see if we could lower this using something else
-    @Override
-    public void onShowCustomView(View view, XWalkWebChromeClient.CustomViewCallback callback) {
-        this.appView.showCustomView(view, callback);
-    }
-
-	@Override
-	public void onHideCustomView() {
-    	this.appView.hideCustomView();
-	}
-    
-    @Override
-    /**
-     * Ask the host application for a custom progress view to show while
-     * a <video> is loading.
-     * @return View The progress view.
-     */
-    public View getVideoLoadingProgressView() {
-
-	    if (mVideoProgressView == null) {	        
-	    	// Create a new Loading view programmatically.
-	    	
-	    	// create the linear layout
-	    	LinearLayout layout = new LinearLayout(this.appView.getContext());
-	        layout.setOrientation(LinearLayout.VERTICAL);
-	        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
-	        layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
-	        layout.setLayoutParams(layoutParams);
-	        // the proress bar
-	        ProgressBar bar = new ProgressBar(this.appView.getContext());
-	        LinearLayout.LayoutParams barLayoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
-	        barLayoutParams.gravity = Gravity.CENTER;
-	        bar.setLayoutParams(barLayoutParams);   
-	        layout.addView(bar);
-	        
-	        mVideoProgressView = layout;
-	    }
-    return mVideoProgressView; 
-    }
-    
-    public void openFileChooser(ValueCallback<Uri> uploadMsg) {
-        this.openFileChooser(uploadMsg, "*/*");
-    }
-
-    public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) {
-        this.openFileChooser(uploadMsg, acceptType, null);
-    }
-    
-    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)
-    {
-        mUploadMessage = uploadMsg;
-        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
-        i.addCategory(Intent.CATEGORY_OPENABLE);
-        i.setType("*/*");
-        this.cordova.getActivity().startActivityForResult(Intent.createChooser(i, "File Browser"),
-                FILECHOOSER_RESULTCODE);
-    }
-    
-    public ValueCallback<Uri> getValueCallback() {
-        return this.mUploadMessage;
-    }
-
-    @Override
-    public void setWebView(CordovaWebView appView) {
-        // TODO Auto-generated method stub
-        
-    }
-}

http://git-wip-us.apache.org/repos/asf/cordova-android/blob/bd806a34/framework/src/org/xwalk/runtime/extension/CordovaXWalkCoreExtensionBridge.java
----------------------------------------------------------------------
diff --git a/framework/src/org/xwalk/runtime/extension/CordovaXWalkCoreExtensionBridge.java b/framework/src/org/xwalk/runtime/extension/CordovaXWalkCoreExtensionBridge.java
deleted file mode 100644
index e80ea51..0000000
--- a/framework/src/org/xwalk/runtime/extension/CordovaXWalkCoreExtensionBridge.java
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2013 Intel Corporation. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.xwalk.runtime.extension;
-
-import org.xwalk.runtime.extension.XWalkExtension;
-
-/**
- * This class is a public wrapper for XWalkCoreExtensionBridge.
- */
-public class CordovaXWalkCoreExtensionBridge extends XWalkCoreExtensionBridge {
-
-    public CordovaXWalkCoreExtensionBridge(XWalkExtension extension) {
-        super(extension);
-    }
-}