cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From na...@apache.org
Subject [15/50] git commit: Amazon related fixes after uplevel.
Date Thu, 28 Aug 2014 19:03:29 GMT
Amazon related fixes after uplevel.


Project: http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/commit/5843c7e0
Tree: http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/tree/5843c7e0
Diff: http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/diff/5843c7e0

Branch: refs/heads/master
Commit: 5843c7e037d29c09549bb81e9095c98ed62032ce
Parents: 7d68405
Author: Archana Naik <naika@lab126.com>
Authored: Thu Aug 14 11:16:40 2014 -0700
Committer: Archana Naik <naika@lab126.com>
Committed: Thu Aug 14 11:16:40 2014 -0700

----------------------------------------------------------------------
 bin/templates/cordova/version                   |    2 +-
 framework/src/org/apache/cordova/App.java       |   18 +-
 .../src/org/apache/cordova/CordovaActivity.java |   14 +-
 .../org/apache/cordova/CordovaChromeClient.java |    3 +-
 .../src/org/apache/cordova/CordovaWebView.java  |   48 +-
 .../src/org/apache/cordova/PluginManager.java   |   81 +-
 test/assets/www/cordova.js                      | 1388 ++++++++----------
 .../test/CordovaWebViewTestActivity.java        |    5 +-
 .../test/junit/BackButtonMultiPageTest.java     |    6 +-
 .../cordova/test/junit/PluginManagerTest.java   |   11 +-
 10 files changed, 688 insertions(+), 888 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/5843c7e0/bin/templates/cordova/version
----------------------------------------------------------------------
diff --git a/bin/templates/cordova/version b/bin/templates/cordova/version
index 61b62e6..0828627 100755
--- a/bin/templates/cordova/version
+++ b/bin/templates/cordova/version
@@ -20,6 +20,6 @@
 */
 
 // Coho updates this line:
-var VERSION = "3.4.0-dev";
+var VERSION = “3.6.0-dev";
 
 console.log(VERSION);

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/5843c7e0/framework/src/org/apache/cordova/App.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/App.java b/framework/src/org/apache/cordova/App.java
index 160923c..7eaceea 100755
--- a/framework/src/org/apache/cordova/App.java
+++ b/framework/src/org/apache/cordova/App.java
@@ -33,6 +33,7 @@ import android.content.Intent;
 import android.content.IntentFilter;
 import android.telephony.TelephonyManager;
 import android.view.KeyEvent;
+import android.util.Log;
 
 import java.util.HashMap;
 
@@ -131,7 +132,7 @@ public class App extends CordovaPlugin {
      * @throws JSONException
      */
     public void loadUrl(String url, JSONObject props) throws JSONException {
-        LOG.d("App", "App.loadUrl("+url+","+props+")");
+        Log.d(TAG, "App.loadUrl("+url+","+props+")");
         int wait = 0;
         boolean openExternal = false;
         boolean clearHistory = false;
@@ -213,7 +214,7 @@ public class App extends CordovaPlugin {
      * @param override		T=override, F=cancel override
      */
     public void overrideBackbutton(boolean override) {
-        LOG.i("App", "WARNING: Back Button Default Behavior will be overridden.  The backbutton event will be fired!");
+        Log.i("App", "WARNING: Back Button Default Behavior will be overridden.  The backbutton event will be fired!");
         webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_BACK, override);
     }
 
@@ -225,7 +226,7 @@ public class App extends CordovaPlugin {
      * @param override      T=override, F=cancel override
      */
     public void overrideButton(String button, boolean override) {
-        LOG.i("App", "WARNING: Volume Button Default Behavior will be overridden.  The volume event will be fired!");
+        Log.i(TAG, "WARNING: Volume Button Default Behavior will be overridden.  The volume event will be fired!");
         if (button.equals("volumeup")) {
             webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_VOLUME_UP, override);
         }
@@ -270,15 +271,15 @@ public class App extends CordovaPlugin {
                     if (intent.hasExtra(TelephonyManager.EXTRA_STATE)) {
                         String extraData = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
                         if (extraData.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
-                            LOG.i(TAG, "Telephone RINGING");
+                            Log.i(TAG, "Telephone RINGING");
                             webView.postMessage("telephone", "ringing");
                         }
                         else if (extraData.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
-                            LOG.i(TAG, "Telephone OFFHOOK");
+                            Log.i(TAG, "Telephone OFFHOOK");
                             webView.postMessage("telephone", "offhook");
                         }
                         else if (extraData.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
-                            LOG.i(TAG, "Telephone IDLE");
+                            Log.i(TAG, "Telephone IDLE");
                             webView.postMessage("telephone", "idle");
                         }
                     }
@@ -296,6 +297,9 @@ public class App extends CordovaPlugin {
      */
     public void onDestroy()
     {
-        this.cordova.getActivity().unregisterReceiver(this.telephonyReceiver);
+        if (this.telephonyReceiver != null) {
+            this.cordova.getActivity().unregisterReceiver(this.telephonyReceiver);
+            this.telephonyReceiver = null;
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/5843c7e0/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 91c24d7..d3dc793 100755
--- a/framework/src/org/apache/cordova/CordovaActivity.java
+++ b/framework/src/org/apache/cordova/CordovaActivity.java
@@ -291,7 +291,9 @@ public class CordovaActivity extends Activity implements CordovaInterface {
      * require a more specialized web view.
      */
     protected CordovaWebView makeWebView() {
-        return new CordovaWebView(CordovaActivity.this);
+        CordovaWebView newWebView = new CordovaWebView(CordovaActivity.this);
+        this.getFactory().initializeWebView(newWebView, 0xFFFFFF, false, null);
+        return newWebView;
     }
 
     /**
@@ -318,7 +320,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
         return webView.makeWebChromeClient(this);
     }
 
-<<<<<<< HEAD
     /**
      * Construct the AmazonWebkitFactory
      * 
@@ -371,7 +372,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
             LOG.e(TAG, "WebKit factory initialization failed. Make sure you have android_interface.jar in libs folder.");
             displayError(ERROR_DIALOG_TITLE, ANDROID_WEBKIT_FACTORY_MISSING, ERROR_DIALOG_OK_BUTTON, true);
         } catch (Exception e) {
-            LOG.e(TAG, "WebKit factory initialization failed.");
+            LOG.e(TAG, "WebKit factory initialization failed. e - " + e.getMessage());
             displayError(ERROR_DIALOG_TITLE, ANDROID_WEBKIT_FACTORY_MISSING, ERROR_DIALOG_OK_BUTTON, true);
         }
         
@@ -380,14 +381,12 @@ public class CordovaActivity extends Activity implements CordovaInterface {
     /**
      * Create and initialize web container with default web view objects.
      */
-    @Deprecated // No need to call init() anymore.
-=======
->>>>>>> a14c794... Un-deprecate CordovaActivity.init() - it's needed to tweak prefs in onCreate
     public void init() {
     	if (factory != null) {
     		CordovaWebView webView = makeWebView();
     		this.init(webView, makeWebViewClient(webView), makeChromeClient(webView));
     	}
+    }
 
     @SuppressLint("NewApi")
     @Deprecated // Call init() instead and override makeWebView() to customize.
@@ -434,7 +433,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
      * Load the url into the webview.
      */
     public void loadUrl(String url) {
-<<<<<<< HEAD
         // Init web view if not already done
         if (this.appView == null) {
             this.init();
@@ -444,11 +442,9 @@ public class CordovaActivity extends Activity implements CordovaInterface {
             }
         }
 
-=======
         if (appView == null) {
             init();
         }
->>>>>>> a14c794... Un-deprecate CordovaActivity.init() - it's needed to tweak prefs in onCreate
         this.splashscreenTime = preferences.getInteger("SplashScreenDelay", this.splashscreenTime);
         String splash = preferences.getString("SplashScreen", null);
         if(this.splashscreenTime > 0 && splash != null)

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/5843c7e0/framework/src/org/apache/cordova/CordovaChromeClient.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/CordovaChromeClient.java b/framework/src/org/apache/cordova/CordovaChromeClient.java
index 24c1aa1..73a765f 100755
--- a/framework/src/org/apache/cordova/CordovaChromeClient.java
+++ b/framework/src/org/apache/cordova/CordovaChromeClient.java
@@ -39,7 +39,8 @@ import com.amazon.android.webkit.AmazonWebView;
 import com.amazon.android.webkit.AmazonGeolocationPermissions;
 import com.amazon.android.webkit.AmazonMediaDeviceSettings;
 
-
+import org.json.JSONObject;
+import org.json.JSONException;
 import android.widget.EditText;
 import android.widget.LinearLayout;
 import android.widget.ProgressBar;

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/5843c7e0/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 8171b18..fbc1932 100755
--- a/framework/src/org/apache/cordova/CordovaWebView.java
+++ b/framework/src/org/apache/cordova/CordovaWebView.java
@@ -62,7 +62,7 @@ public class CordovaWebView extends AmazonWebView {
 
 
     public static final String TAG = "CordovaWebView";
-    public static final String CORDOVA_VERSION = "3.4.0-dev";
+    public static final String CORDOVA_VERSION = "3.6.0-dev";
 
     private HashSet<Integer> boundKeyCodes = new HashSet<Integer>();
 
@@ -149,7 +149,7 @@ public class CordovaWebView extends AmazonWebView {
             Gravity.CENTER);
     
     public CordovaWebView(Context context) {
-        this(context, null);
+        this(context, (AttributeSet)null);
     }
 
 ////fireos_change ////
@@ -162,7 +162,7 @@ public class CordovaWebView extends AmazonWebView {
      * @param extraData 
      */
     public CordovaWebView(Context context, Bundle extraData) {
-        this(context, null);
+        this(context, (AttributeSet)null);
  
         if (CordovaInterface.class.isInstance(context))
         {
@@ -173,8 +173,6 @@ public class CordovaWebView extends AmazonWebView {
         {
             Log.d(TAG, "Your activity must implement CordovaInterface to work");
         }
-        this.loadConfiguration();
-        this.setup();
     }
 ////fireos_change ////
     
@@ -192,13 +190,13 @@ public class CordovaWebView extends AmazonWebView {
     public CordovaWebView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
     }
-
+/*
     @TargetApi(11)
     @Deprecated
     public CordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) {
         super(context, attrs, defStyle, privateBrowsing);
     }
-
+*/
     // Use two-phase init so that the control will work with XML layouts.
     public void init(CordovaInterface cordova, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient,
             List<PluginEntry> pluginEntries, Whitelist whitelist, CordovaPreferences preferences) {
@@ -206,6 +204,7 @@ public class CordovaWebView extends AmazonWebView {
             throw new IllegalStateException();
         }
         this.cordova = cordova;
+        //this.cordova.getFactory().initializeWebView(this, 0xFFFFFF, false, null);
         this.viewClient = webViewClient;
         this.chromeClient = webChromeClient;
         this.whitelist = whitelist;
@@ -279,7 +278,8 @@ public class CordovaWebView extends AmazonWebView {
         if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
             || (getWebViewBackend(this.cordova.getFactory()) == WebViewBackend.CHROMIUM))
             Level16Apis.enableUniversalAccess(settings);
-
+        String databasePath = getContext().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
+        
         if (getWebViewBackend(this.cordova.getFactory()) == WebViewBackend.ANDROID) {
         	File appCacheDir = this.cordova.getActivity().getDir(APPCACHE_DIR, Context.MODE_PRIVATE);
             if (appCacheDir.exists()) {
@@ -292,7 +292,6 @@ public class CordovaWebView extends AmazonWebView {
             }
         // Enable database
         // We keep this disabled because we use or shim to get around DOM_EXCEPTION_ERROR_16
-        String databasePath = getContext().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
         settings.setDatabaseEnabled(true);
         settings.setDatabasePath(databasePath);
         
@@ -331,12 +330,15 @@ public class CordovaWebView extends AmazonWebView {
         }
         userAgent = userAgent.concat(" " + CORDOVA_AMAZON_FIREOS_UA); 
         settings.setUserAgentString(userAgent);
-
+        //__FireOS__
+        settings.setUseWideViewPort(true);
+        //__FireOS__
+        
         // Enable AppCache
         // Fix for CB-2282
-        settings.setAppCacheMaxSize(5 * 1048576);
-        settings.setAppCachePath(databasePath);
-        settings.setAppCacheEnabled(true);
+        //settings.setAppCacheMaxSize(5 * 1048576);
+        //settings.setAppCachePath(databasePath);
+        //settings.setAppCacheEnabled(true);
         
         // Fix for CB-1405
         // Google issue 4641
@@ -355,25 +357,17 @@ public class CordovaWebView extends AmazonWebView {
         }
         // end CB-1405
     }
-
-        settings.setUseWideViewPort(true);
-
-        pluginManager = new PluginManager(this, this.cordova);
-        jsMessageQueue = new NativeToJsMessageQueue(this, cordova);
-        exposedJsApi = new ExposedJsApi(pluginManager, jsMessageQueue);
-        resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
-        exposeJsInterface();
-
+/*
     @TargetApi(Build.VERSION_CODES.KITKAT)
     private void enableRemoteDebugging() {
         try {
-            WebView.setWebContentsDebuggingEnabled(true);
+            AmazonWebView.setWebContentsDebuggingEnabled(true);
         } catch (IllegalArgumentException e) {
             Log.d(TAG, "You have one job! To turn on Remote Web Debugging! YOU HAVE FAILED! ");
             e.printStackTrace();
         }
     }
-
+*/
     public CordovaChromeClient makeWebChromeClient(CordovaInterface cordova) {
         return new CordovaChromeClient(cordova, this);
     }
@@ -425,12 +419,6 @@ public class CordovaWebView extends AmazonWebView {
     }
 
     @Override
-    public void setWebViewClient(WebViewClient client) {
-        this.viewClient = (CordovaWebViewClient)client;
-        super.setWebViewClient(client);
-    }
-
-    @Override
     public void setWebChromeClient(AmazonWebChromeClient client) {
         this.chromeClient = (CordovaChromeClient)client;
         super.setWebChromeClient(client);

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/5843c7e0/framework/src/org/apache/cordova/PluginManager.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/PluginManager.java b/framework/src/org/apache/cordova/PluginManager.java
index 97988d8..2af8f45 100755
--- a/framework/src/org/apache/cordova/PluginManager.java
+++ b/framework/src/org/apache/cordova/PluginManager.java
@@ -22,6 +22,8 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
 
 import org.apache.cordova.CordovaWebView;
 import org.apache.cordova.CallbackContext;
@@ -31,6 +33,7 @@ import org.apache.cordova.PluginEntry;
 import org.apache.cordova.PluginResult;
 import org.json.JSONException;
 
+
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Debug;
@@ -47,8 +50,8 @@ public class PluginManager {
     private static final int SLOW_EXEC_WARNING_THRESHOLD = Debug.isDebuggerConnected() ? 60 : 16;
 
     // List of service entries
-    private final HashMap<String, CordovaPlugin> pluginMap = new HashMap<String, CordovaPlugin>();
-    private final HashMap<String, PluginEntry> entryMap = new LinkedHashMap<String, PluginEntry>();
+    private HashMap<String, CordovaPlugin> pluginMap = new LinkedHashMap<String, CordovaPlugin>();
+    private HashMap<String, PluginEntry> entryMap = new LinkedHashMap<String, PluginEntry>();
 
     private final CordovaInterface ctx;
     private final CordovaWebView app;
@@ -90,7 +93,7 @@ public class PluginManager {
         LOG.d(TAG, "init()");
         this.onPause(false);
         this.onDestroy();
-        pluginMap.clear();
+        //pluginMap.clear();
         this.startupPlugins();
     }
 
@@ -179,6 +182,7 @@ public class PluginManager {
      * @return              CordovaPlugin or null
      */
     public CordovaPlugin getPlugin(String service) {
+        Log.d(TAG, "in getPlugin for service - " + service);
         CordovaPlugin ret = pluginMap.get(service);
         if (ret == null) {
             PluginEntry pe = entryMap.get(service);
@@ -188,10 +192,24 @@ public class PluginManager {
             if (pe.plugin != null) {
                 ret = pe.plugin;
             } else {
-                ret = instantiatePlugin(pe.pluginClass);
+                ret = instantiatePlugin(pe.pluginClass);   
             }
             ret.privateInitialize(ctx, app, app.getPreferences());
-            pluginMap.put(service, ret);
+            HashMap<String, CordovaPlugin> tmpPlugins = new LinkedHashMap<String, CordovaPlugin>();
+            List<PluginEntry> pluginEntries = new ArrayList<PluginEntry>(entryMap.values());
+            for (PluginEntry pluginEntry : pluginEntries) {
+                if (pluginEntry.plugin != null) {
+                    tmpPlugins.put(pluginEntry.service, pluginEntry.plugin);
+                } else {
+                    CordovaPlugin plugin = pluginMap.get(pluginEntry.service);
+                    if (plugin != null) {
+                        tmpPlugins.put(pluginEntry.service, plugin);
+                    } else if (pluginEntry.service.equals(service)) {
+                        tmpPlugins.put(service, ret);
+                    }
+                }
+            }
+            this.pluginMap = tmpPlugins;
         }
         return ret;
     }
@@ -232,11 +250,21 @@ public class PluginManager {
 		 */
 
 		// create list from existing set of plugin entries, then add new item to list
-		List<PluginEntry> pluginEntries = new ArrayList<PluginEntry>(entries.values());
+		List<PluginEntry> pluginEntries = new ArrayList<PluginEntry>(entryMap.values());
 		pluginEntries.add(entry);
 
+        //Update PluginMap as well
+        if (entry.plugin != null) {
+            entry.plugin.privateInitialize(ctx, app, app.getPreferences());
+            pluginMap.put(entry.service, entry.plugin);
+        }
 		// recreate final set entries in priority order
 		this.addServices(pluginEntries);
+        
+        List<String> urlFilters = entry.getUrlFilters();
+        if (urlFilters != null) {
+            urlMap.put(entry.service, urlFilters);
+        }
 	}
 
     /**
@@ -251,26 +279,27 @@ public class PluginManager {
         Collections.sort(services);
 
         // create a new map from the prioritized list, and use it as the primary set of entries
+        // update pluginMap as well
+        
+        HashMap<String, CordovaPlugin> tmpPlugins = new LinkedHashMap<String, CordovaPlugin>();
         HashMap<String, PluginEntry> tmpEntries = new LinkedHashMap<String, PluginEntry>();
         for (PluginEntry pluginEntry : services) {
             tmpEntries.put(pluginEntry.service, pluginEntry);
+            if (pluginEntry.plugin != null) {
+                tmpPlugins.put(pluginEntry.service, pluginEntry.plugin);
+            } else {
+                CordovaPlugin plugin = pluginMap.get(pluginEntry.service);
+                if (plugin != null) {
+                    tmpPlugins.put(pluginEntry.service, plugin);
+                }
+            }
         }
-        this.entries = tmpEntries;
+        
+        this.entryMap = tmpEntries;
+        this.pluginMap = tmpPlugins;
+        
     }
     
-    public void addService(PluginEntry entry) {
-        this.entryMap.put(entry.service, entry);
-        List<String> urlFilters = entry.getUrlFilters();
-        if (urlFilters != null) {
-            urlMap.put(entry.service, urlFilters);
-        }
-        if (entry.plugin != null) {
-            entry.plugin.privateInitialize(ctx, app, app.getPreferences());
-            pluginMap.put(entry.service, entry.plugin);
-        }
-
-    }
-
     /**
      * Called when the system is about to start resuming a previous activity.
      *
@@ -297,9 +326,15 @@ public class PluginManager {
      * The final call you receive before your activity is destroyed.
      */
     public void onDestroy() {
-        for (CordovaPlugin plugin : this.pluginMap.values()) {
-            plugin.onDestroy();
+        try {
+            for (CordovaPlugin plugin : this.pluginMap.values()) {
+                Log.d(TAG, "In destroy");
+                plugin.onDestroy();
+            }
+        } catch (Exception e) {
+            Log.e(TAG, e.getMessage());
         }
+
     }
 
     /**
@@ -314,6 +349,7 @@ public class PluginManager {
         if (obj != null) {
             return obj;
         }
+
         for (CordovaPlugin plugin : this.pluginMap.values()) {
             obj = plugin.onMessage(id, data);
             if (obj != null) {
@@ -348,6 +384,7 @@ public class PluginManager {
             if (urlFilters != null) {
                 for (String s : urlFilters) {
                     if (url.startsWith(s)) {
+                        Log.d(TAG,"onOverrideUrlLoading()");
                         return getPlugin(entry.service).onOverrideUrlLoading(url);
                     }
                 }

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/5843c7e0/test/assets/www/cordova.js
----------------------------------------------------------------------
diff --git a/test/assets/www/cordova.js b/test/assets/www/cordova.js
index 4fc9746..0a87e6c 100755
--- a/test/assets/www/cordova.js
+++ b/test/assets/www/cordova.js
@@ -1,5 +1,5 @@
 // Platform: android
-// 2.7.0rc1-169-g87cc336
+// 3.6.0-dev-70cdca3
 /*
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
@@ -19,8 +19,11 @@
  under the License.
 */
 ;(function() {
-var CORDOVA_JS_BUILD_LABEL = '2.7.0rc1-169-g87cc336';
-// file: lib/scripts/require.js
+var CORDOVA_JS_BUILD_LABEL = '3.6.0-dev-70cdca3';
+// file: src/scripts/require.js
+
+/*jshint -W079 */
+/*jshint -W020 */
 
 var require,
     define;
@@ -31,7 +34,7 @@ var require,
         requireStack = [],
     // Map of module ID -> index into requireStack of modules currently being built.
         inProgressModules = {},
-        SEPERATOR = ".";
+        SEPARATOR = ".";
 
 
 
@@ -41,7 +44,7 @@ var require,
                 var resultantId = id;
                 //Its a relative path, so lop off the last portion and add the id (minus "./")
                 if (id.charAt(0) === ".") {
-                    resultantId = module.id.slice(0, module.id.lastIndexOf(SEPERATOR)) + SEPERATOR + id.slice(2);
+                    resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
                 }
                 return require(resultantId);
             };
@@ -95,21 +98,12 @@ if (typeof module === "object" && typeof require === "function") {
     module.exports.define = define;
 }
 
-// file: lib/cordova.js
+// file: src/cordova.js
 define("cordova", function(require, exports, module) {
 
 
 var channel = require('cordova/channel');
-
-/**
- * Listen for DOMContentLoaded and notify our channel subscribers.
- */
-document.addEventListener('DOMContentLoaded', function() {
-    channel.onDOMContentLoaded.fire();
-}, false);
-if (document.readyState == 'complete' || document.readyState == 'interactive') {
-    channel.onDOMContentLoaded.fire();
-}
+var platform = require('cordova/platform');
 
 /**
  * Intercept calls to addEventListener + removeEventListener and handle deviceready,
@@ -177,21 +171,12 @@ function createEvent(type, data) {
     return event;
 }
 
-if(typeof window.console === "undefined") {
-    window.console = {
-        log:function(){}
-    };
-}
-// there are places in the framework where we call `warn` also, so we should make sure it exists
-if(typeof window.console.warn === "undefined") {
-    window.console.warn = function(msg) {
-        this.log("warn: " + msg);
-    }
-}
 
 var cordova = {
     define:define,
     require:require,
+    version:CORDOVA_JS_BUILD_LABEL,
+    platformId:platform.id,
     /**
      * Methods to add/remove your own addEventListener hijacking on document + window.
      */
@@ -227,16 +212,16 @@ var cordova = {
         var evt = createEvent(type, data);
         if (typeof documentEventHandlers[type] != 'undefined') {
             if( bNoDetach ) {
-              documentEventHandlers[type].fire(evt);
+                documentEventHandlers[type].fire(evt);
             }
             else {
-              setTimeout(function() {
-                  // Fire deviceready on listeners that were registered before cordova.js was loaded.
-                  if (type == 'deviceready') {
-                      document.dispatchEvent(evt);
-                  }
-                  documentEventHandlers[type].fire(evt);
-              }, 0);
+                setTimeout(function() {
+                    // Fire deviceready on listeners that were registered before cordova.js was loaded.
+                    if (type == 'deviceready') {
+                        document.dispatchEvent(evt);
+                    }
+                    documentEventHandlers[type].fire(evt);
+                }, 0);
             }
         } else {
             document.dispatchEvent(evt);
@@ -280,7 +265,7 @@ var cordova = {
         try {
             cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
         } catch (e) {
-            console.log("Error in error callback: " + callbackId + " = "+e);
+            console.log("Error in success callback: " + callbackId + " = "+e);
         }
     },
 
@@ -326,16 +311,57 @@ var cordova = {
     }
 };
 
-// Register pause, resume and deviceready channels as events on document.
-channel.onPause = cordova.addDocumentEventHandler('pause');
-channel.onResume = cordova.addDocumentEventHandler('resume');
-channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
 
 module.exports = cordova;
 
 });
 
-// file: lib/common/argscheck.js
+// file: src/android/android/nativeapiprovider.js
+define("cordova/android/nativeapiprovider", function(require, exports, module) {
+
+/**
+ * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
+ */
+
+var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
+var currentApi = nativeApi;
+
+module.exports = {
+    get: function() { return currentApi; },
+    setPreferPrompt: function(value) {
+        currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
+    },
+    // Used only by tests.
+    set: function(value) {
+        currentApi = value;
+    }
+};
+
+});
+
+// file: src/android/android/promptbasednativeapi.js
+define("cordova/android/promptbasednativeapi", function(require, exports, module) {
+
+/**
+ * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
+ * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
+ */
+
+module.exports = {
+    exec: function(bridgeSecret, service, action, callbackId, argsJson) {
+        return prompt(argsJson, 'gap:'+JSON.stringify([bridgeSecret, service, action, callbackId]));
+    },
+    setNativeToJsBridgeMode: function(bridgeSecret, value) {
+        prompt(value, 'gap_bridge_mode:' + bridgeSecret);
+    },
+    retrieveJsMessages: function(bridgeSecret, fromOnlineEvent) {
+        return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
+    }
+};
+
+});
+
+// file: src/common/argscheck.js
 define("cordova/argscheck", function(require, exports, module) {
 
 var exec = require('cordova/exec');
@@ -353,7 +379,7 @@ var typeMap = {
 };
 
 function extractParamName(callee, argIndex) {
-  return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
+    return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
 }
 
 function checkArgs(spec, functionName, args, opt_callee) {
@@ -401,14 +427,24 @@ moduleExports.enableChecks = true;
 
 });
 
-// file: lib/common/base64.js
+// file: src/common/base64.js
 define("cordova/base64", function(require, exports, module) {
 
 var base64 = exports;
 
 base64.fromArrayBuffer = function(arrayBuffer) {
-  var array = new Uint8Array(arrayBuffer);
-  return uint8ToBase64(array);
+    var array = new Uint8Array(arrayBuffer);
+    return uint8ToBase64(array);
+};
+
+base64.toArrayBuffer = function(str) {
+    var decodedStr = typeof atob != 'undefined' ? atob(str) : new Buffer(str,'base64').toString('binary');
+    var arrayBuffer = new ArrayBuffer(decodedStr.length);
+    var array = new Uint8Array(arrayBuffer);
+    for (var i=0, len=decodedStr.length; i < len; i++) {
+        array[i] = decodedStr.charCodeAt(i);
+    }
+    return arrayBuffer;
 };
 
 //------------------------------------------------------------------------------
@@ -430,7 +466,7 @@ var b64_12bitTable = function() {
     }
     b64_12bitTable = function() { return b64_12bit; };
     return b64_12bit;
-}
+};
 
 function uint8ToBase64(rawData) {
     var numBytes = rawData.byteLength;
@@ -457,7 +493,7 @@ function uint8ToBase64(rawData) {
 
 });
 
-// file: lib/common/builder.js
+// file: src/common/builder.js
 define("cordova/builder", function(require, exports, module) {
 
 var utils = require('cordova/utils');
@@ -497,36 +533,36 @@ function assignOrWrapInDeprecateGetter(obj, key, value, message) {
 function include(parent, objects, clobber, merge) {
     each(objects, function (obj, key) {
         try {
-          var result = obj.path ? require(obj.path) : {};
-
-          if (clobber) {
-              // Clobber if it doesn't exist.
-              if (typeof parent[key] === 'undefined') {
-                  assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
-              } else if (typeof obj.path !== 'undefined') {
-                  // If merging, merge properties onto parent, otherwise, clobber.
-                  if (merge) {
-                      recursiveMerge(parent[key], result);
-                  } else {
-                      assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
-                  }
-              }
-              result = parent[key];
-          } else {
-            // Overwrite if not currently defined.
-            if (typeof parent[key] == 'undefined') {
-              assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+            var result = obj.path ? require(obj.path) : {};
+
+            if (clobber) {
+                // Clobber if it doesn't exist.
+                if (typeof parent[key] === 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else if (typeof obj.path !== 'undefined') {
+                    // If merging, merge properties onto parent, otherwise, clobber.
+                    if (merge) {
+                        recursiveMerge(parent[key], result);
+                    } else {
+                        assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                    }
+                }
+                result = parent[key];
             } else {
-              // Set result to what already exists, so we can build children into it if they exist.
-              result = parent[key];
+                // Overwrite if not currently defined.
+                if (typeof parent[key] == 'undefined') {
+                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
+                } else {
+                    // Set result to what already exists, so we can build children into it if they exist.
+                    result = parent[key];
+                }
             }
-          }
 
-          if (obj.children) {
-            include(result, obj.children, clobber, merge);
-          }
+            if (obj.children) {
+                include(result, obj.children, clobber, merge);
+            }
         } catch(e) {
-          utils.alert('Exception building cordova JS globals: ' + e + ' for key "' + key + '"');
+            utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
         }
     });
 }
@@ -570,7 +606,7 @@ exports.replaceHookForTesting = function() {};
 
 });
 
-// file: lib/common/channel.js
+// file: src/common/channel.js
 define("cordova/channel", function(require, exports, module) {
 
 var utils = require('cordova/utils'),
@@ -789,6 +825,7 @@ channel.createSticky('onNativeReady');
 channel.createSticky('onCordovaReady');
 
 // Event to indicate that all automatically loaded JS plugins are loaded and ready.
+// FIXME remove this
 channel.createSticky('onPluginsReady');
 
 // Event to indicate that Cordova is ready
@@ -811,37 +848,7 @@ module.exports = channel;
 
 });
 
-// file: lib/common/commandProxy.js
-define("cordova/commandProxy", function(require, exports, module) {
-
-
-// internal map of proxy function
-var CommandProxyMap = {};
-
-module.exports = {
-
-    // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
-    add:function(id,proxyObj) {
-        console.log("adding proxy for " + id);
-        CommandProxyMap[id] = proxyObj;
-        return proxyObj;
-    },
-
-    // cordova.commandProxy.remove("Accelerometer");
-    remove:function(id) {
-        var proxy = CommandProxyMap[id];
-        delete CommandProxyMap[id];
-        CommandProxyMap[id] = null;
-        return proxy;
-    },
-
-    get:function(service,action) {
-        return ( CommandProxyMap[service] ? CommandProxyMap[service][action] : null );
-    }
-};
-});
-
-// file: lib/android/exec.js
+// file: src/android/exec.js
 define("cordova/exec", function(require, exports, module) {
 
 /**
@@ -859,16 +866,13 @@ define("cordova/exec", function(require, exports, module) {
  * @param {String[]} [args]     Zero or more arguments to pass to the method
  */
 var cordova = require('cordova'),
-    nativeApiProvider = require('cordova/plugin/android/nativeapiprovider'),
+    nativeApiProvider = require('cordova/android/nativeapiprovider'),
     utils = require('cordova/utils'),
     base64 = require('cordova/base64'),
+    channel = require('cordova/channel'),
     jsToNativeModes = {
         PROMPT: 0,
-        JS_OBJECT: 1,
-        // This mode is currently for benchmarking purposes only. It must be enabled
-        // on the native side through the ENABLE_LOCATION_CHANGE_EXEC_MODE
-        // constant within CordovaWebViewClient.java before it will work.
-        LOCATION_CHANGE: 2
+        JS_OBJECT: 1
     },
     nativeToJsModes = {
         // Polls for messages using the JS->Native bridge.
@@ -888,9 +892,17 @@ var cordova = require('cordova'),
     jsToNativeBridgeMode,  // Set lazily.
     nativeToJsBridgeMode = nativeToJsModes.ONLINE_EVENT,
     pollEnabled = false,
-    messagesFromNative = [];
+    messagesFromNative = [],
+    bridgeSecret = -1;
 
 function androidExec(success, fail, service, action, args) {
+    if (bridgeSecret < 0) {
+        // If we ever catch this firing, we'll need to queue up exec()s
+        // and fire them once we get a secret. For now, I don't think
+        // it's possible for exec() to be called since plugins are parsed but
+        // not run until until after onNativeReady.
+        throw new Error('exec() called without bridgeSecret');
+    }
     // Set default bridge modes if they have not already been set.
     // By default, we use the failsafe, since addJavascriptInterface breaks too often
     if (jsToNativeBridgeMode === undefined) {
@@ -900,7 +912,7 @@ function androidExec(success, fail, service, action, args) {
     // Process any ArrayBuffers in the args into a string.
     for (var i = 0; i < args.length; i++) {
         if (utils.typeName(args[i]) == 'ArrayBuffer') {
-            args[i] = utils.encodeBase64(args[i]);
+            args[i] = base64.fromArrayBuffer(args[i]);
         }
     }
 
@@ -911,25 +923,35 @@ function androidExec(success, fail, service, action, args) {
         cordova.callbacks[callbackId] = {success:success, fail:fail};
     }
 
-    if (jsToNativeBridgeMode == jsToNativeModes.LOCATION_CHANGE) {
-        window.location = 'http://cdv_exec/' + service + '#' + action + '#' + callbackId + '#' + argsJson;
+    var messages = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
+    // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
+    // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2.  See CB-2666.
+    if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && messages === "@Null arguments.") {
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
+        androidExec(success, fail, service, action, args);
+        androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
+        return;
     } else {
-        var messages = nativeApiProvider.get().exec(service, action, callbackId, argsJson);
-        // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
-        // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2.  See CB-2666.
-        if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && messages === "@Null arguments.") {
-            androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
-            androidExec(success, fail, service, action, args);
-            androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
-            return;
-        } else {
-            androidExec.processMessages(messages);
-        }
+        androidExec.processMessages(messages, true);
     }
 }
 
-function pollOnce() {
-    var msg = nativeApiProvider.get().retrieveJsMessages();
+androidExec.init = function() {
+    bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
+    channel.onNativeReady.fire();
+};
+
+function pollOnceFromOnlineEvent() {
+    pollOnce(true);
+}
+
+function pollOnce(opt_fromOnlineEvent) {
+    if (bridgeSecret < 0) {
+        // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
+        // We know there's nothing to retrieve, so no need to poll.
+        return;
+    }
+    var msg = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
     androidExec.processMessages(msg);
 }
 
@@ -948,8 +970,8 @@ function hookOnlineApis() {
     // It currently fires them only on document though, so we bridge them
     // to window here (while first listening for exec()-releated online/offline
     // events).
-    window.addEventListener('online', pollOnce, false);
-    window.addEventListener('offline', pollOnce, false);
+    window.addEventListener('online', pollOnceFromOnlineEvent, false);
+    window.addEventListener('offline', pollOnceFromOnlineEvent, false);
     cordova.addWindowEventHandler('online');
     cordova.addWindowEventHandler('offline');
     document.addEventListener('online', proxyEvent, false);
@@ -963,7 +985,6 @@ androidExec.nativeToJsModes = nativeToJsModes;
 
 androidExec.setJsToNativeBridgeMode = function(mode) {
     if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
-        console.log('Falling back on PROMPT mode since _cordovaNative is missing. Expected for Android 3.2 and lower only.');
         mode = jsToNativeModes.PROMPT;
     }
     nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT);
@@ -980,7 +1001,10 @@ androidExec.setNativeToJsBridgeMode = function(mode) {
 
     nativeToJsBridgeMode = mode;
     // Tell the native side to switch modes.
-    nativeApiProvider.get().setNativeToJsBridgeMode(mode);
+    // Otherwise, it will be set by androidExec.init()
+    if (bridgeSecret >= 0) {
+        nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
+    }
 
     if (mode == nativeToJsModes.POLLING) {
         pollEnabled = true;
@@ -1028,53 +1052,322 @@ function processMessage(message) {
             }
             cordova.callbackFromNative(callbackId, success, status, [payload], keepCallback);
         } else {
-            console.log("processMessage failed: invalid message:" + message);
+            console.log("processMessage failed: invalid message: " + JSON.stringify(message));
         }
     } catch (e) {
-        console.log("processMessage failed: Message: " + message);
         console.log("processMessage failed: Error: " + e);
         console.log("processMessage failed: Stack: " + e.stack);
+        console.log("processMessage failed: Message: " + message);
     }
 }
 
+var isProcessing = false;
+
 // This is called from the NativeToJsMessageQueue.java.
-androidExec.processMessages = function(messages) {
+androidExec.processMessages = function(messages, opt_useTimeout) {
     if (messages) {
         messagesFromNative.push(messages);
-        // Check for the reentrant case, and enqueue the message if that's the case.
-        if (messagesFromNative.length > 1) {
-            return;
-        }
+    }
+    // Check for the reentrant case.
+    if (isProcessing) {
+        return;
+    }
+    if (opt_useTimeout) {
+        window.setTimeout(androidExec.processMessages, 0);
+        return;
+    }
+    isProcessing = true;
+    try {
+        // TODO: add setImmediate polyfill and process only one message at a time.
         while (messagesFromNative.length) {
-            // Don't unshift until the end so that reentrancy can be detected.
-            messages = messagesFromNative[0];
+            var msg = popMessageFromQueue();
             // The Java side can send a * message to indicate that it
             // still has messages waiting to be retrieved.
-            if (messages == '*') {
-                messagesFromNative.shift();
-                window.setTimeout(pollOnce, 0);
+            if (msg == '*' && messagesFromNative.length === 0) {
+                setTimeout(pollOnce, 0);
                 return;
             }
-
-            var spaceIdx = messages.indexOf(' ');
-            var msgLen = +messages.slice(0, spaceIdx);
-            var message = messages.substr(spaceIdx + 1, msgLen);
-            messages = messages.slice(spaceIdx + msgLen + 1);
-            processMessage(message);
-            if (messages) {
-                messagesFromNative[0] = messages;
-            } else {
-                messagesFromNative.shift();
-            }
+            processMessage(msg);
         }
+    } finally {
+        isProcessing = false;
     }
 };
 
+function popMessageFromQueue() {
+    var messageBatch = messagesFromNative.shift();
+    if (messageBatch == '*') {
+        return '*';
+    }
+
+    var spaceIdx = messageBatch.indexOf(' ');
+    var msgLen = +messageBatch.slice(0, spaceIdx);
+    var message = messageBatch.substr(spaceIdx + 1, msgLen);
+    messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
+    if (messageBatch) {
+        messagesFromNative.unshift(messageBatch);
+    }
+    return message;
+}
+
 module.exports = androidExec;
 
 });
 
-// file: lib/common/modulemapper.js
+// file: src/common/exec/proxy.js
+define("cordova/exec/proxy", function(require, exports, module) {
+
+
+// internal map of proxy function
+var CommandProxyMap = {};
+
+module.exports = {
+
+    // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
+    add:function(id,proxyObj) {
+        console.log("adding proxy for " + id);
+        CommandProxyMap[id] = proxyObj;
+        return proxyObj;
+    },
+
+    // cordova.commandProxy.remove("Accelerometer");
+    remove:function(id) {
+        var proxy = CommandProxyMap[id];
+        delete CommandProxyMap[id];
+        CommandProxyMap[id] = null;
+        return proxy;
+    },
+
+    get:function(service,action) {
+        return ( CommandProxyMap[service] ? CommandProxyMap[service][action] : null );
+    }
+};
+});
+
+// file: src/common/init.js
+define("cordova/init", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var modulemapper = require('cordova/modulemapper');
+var platform = require('cordova/platform');
+var pluginloader = require('cordova/pluginloader');
+
+var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
+
+function logUnfiredChannels(arr) {
+    for (var i = 0; i < arr.length; ++i) {
+        if (arr[i].state != 2) {
+            console.log('Channel not fired: ' + arr[i].type);
+        }
+    }
+}
+
+window.setTimeout(function() {
+    if (channel.onDeviceReady.state != 2) {
+        console.log('deviceready has not fired after 5 seconds.');
+        logUnfiredChannels(platformInitChannelsArray);
+        logUnfiredChannels(channel.deviceReadyChannelsArray);
+    }
+}, 5000);
+
+// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
+// We replace it so that properties that can't be clobbered can instead be overridden.
+function replaceNavigator(origNavigator) {
+    var CordovaNavigator = function() {};
+    CordovaNavigator.prototype = origNavigator;
+    var newNavigator = new CordovaNavigator();
+    // This work-around really only applies to new APIs that are newer than Function.bind.
+    // Without it, APIs such as getGamepads() break.
+    if (CordovaNavigator.bind) {
+        for (var key in origNavigator) {
+            if (typeof origNavigator[key] == 'function') {
+                newNavigator[key] = origNavigator[key].bind(origNavigator);
+            }
+        }
+    }
+    return newNavigator;
+}
+if (window.navigator) {
+    window.navigator = replaceNavigator(window.navigator);
+}
+
+if (!window.console) {
+    window.console = {
+        log: function(){}
+    };
+}
+if (!window.console.warn) {
+    window.console.warn = function(msg) {
+        this.log("warn: " + msg);
+    };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState == 'complete' || document.readyState == 'interactive') {
+    channel.onDOMContentLoaded.fire();
+} else {
+    document.addEventListener('DOMContentLoaded', function() {
+        channel.onDOMContentLoaded.fire();
+    }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+    channel.onNativeReady.fire();
+}
+
+modulemapper.clobbers('cordova', 'cordova');
+modulemapper.clobbers('cordova/exec', 'cordova.exec');
+modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
+// The delay allows the attached modules to be defined before the plugin loader looks for them.
+setTimeout(function() {
+    pluginloader.load(function() {
+        channel.onPluginsReady.fire();
+    });
+}, 0);
+
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function() {
+    modulemapper.mapModules(window);
+
+    platform.initialize && platform.initialize();
+
+    // Fire event to notify that all objects are created
+    channel.onCordovaReady.fire();
+
+    // Fire onDeviceReady event once page has fully loaded, all
+    // constructors have run and cordova info has been received from native
+    // side.
+    channel.join(function() {
+        require('cordova').fireDocumentEvent('deviceready');
+    }, channel.deviceReadyChannelsArray);
+
+}, platformInitChannelsArray);
+
+
+});
+
+// file: src/common/init_b.js
+define("cordova/init_b", function(require, exports, module) {
+
+var channel = require('cordova/channel');
+var cordova = require('cordova');
+var platform = require('cordova/platform');
+
+var platformInitChannelsArray = [channel.onDOMContentLoaded, channel.onNativeReady];
+
+// setting exec
+cordova.exec = require('cordova/exec');
+
+function logUnfiredChannels(arr) {
+    for (var i = 0; i < arr.length; ++i) {
+        if (arr[i].state != 2) {
+            console.log('Channel not fired: ' + arr[i].type);
+        }
+    }
+}
+
+window.setTimeout(function() {
+    if (channel.onDeviceReady.state != 2) {
+        console.log('deviceready has not fired after 5 seconds.');
+        logUnfiredChannels(platformInitChannelsArray);
+        logUnfiredChannels(channel.deviceReadyChannelsArray);
+    }
+}, 5000);
+
+// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
+// We replace it so that properties that can't be clobbered can instead be overridden.
+function replaceNavigator(origNavigator) {
+    var CordovaNavigator = function() {};
+    CordovaNavigator.prototype = origNavigator;
+    var newNavigator = new CordovaNavigator();
+    // This work-around really only applies to new APIs that are newer than Function.bind.
+    // Without it, APIs such as getGamepads() break.
+    if (CordovaNavigator.bind) {
+        for (var key in origNavigator) {
+            if (typeof origNavigator[key] == 'function') {
+                newNavigator[key] = origNavigator[key].bind(origNavigator);
+            }
+        }
+    }
+    return newNavigator;
+}
+if (window.navigator) {
+    window.navigator = replaceNavigator(window.navigator);
+}
+
+if (!window.console) {
+    window.console = {
+        log: function(){}
+    };
+}
+if (!window.console.warn) {
+    window.console.warn = function(msg) {
+        this.log("warn: " + msg);
+    };
+}
+
+// Register pause, resume and deviceready channels as events on document.
+channel.onPause = cordova.addDocumentEventHandler('pause');
+channel.onResume = cordova.addDocumentEventHandler('resume');
+channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
+
+// Listen for DOMContentLoaded and notify our channel subscribers.
+if (document.readyState == 'complete' || document.readyState == 'interactive') {
+    channel.onDOMContentLoaded.fire();
+} else {
+    document.addEventListener('DOMContentLoaded', function() {
+        channel.onDOMContentLoaded.fire();
+    }, false);
+}
+
+// _nativeReady is global variable that the native side can set
+// to signify that the native code is ready. It is a global since
+// it may be called before any cordova JS is ready.
+if (window._nativeReady) {
+    channel.onNativeReady.fire();
+}
+
+// Call the platform-specific initialization.
+platform.bootstrap && platform.bootstrap();
+
+/**
+ * Create all cordova objects once native side is ready.
+ */
+channel.join(function() {
+    
+    platform.initialize && platform.initialize();
+
+    // Fire event to notify that all objects are created
+    channel.onCordovaReady.fire();
+
+    // Fire onDeviceReady event once page has fully loaded, all
+    // constructors have run and cordova info has been received from native
+    // side.
+    channel.join(function() {
+        require('cordova').fireDocumentEvent('deviceready');
+    }, channel.deviceReadyChannelsArray);
+
+}, platformInitChannelsArray);
+
+});
+
+// file: src/common/modulemapper.js
 define("cordova/modulemapper", function(require, exports, module) {
 
 var builder = require('cordova/builder'),
@@ -1170,34 +1463,27 @@ exports.getOriginalSymbol = function(context, symbolPath) {
     return obj;
 };
 
-exports.loadMatchingModules = function(matchingRegExp) {
-    for (var k in moduleMap) {
-        if (matchingRegExp.exec(k)) {
-            require(k);
-        }
-    }
-};
-
 exports.reset();
 
 
 });
 
-// file: lib/android/platform.js
+// file: src/android/platform.js
 define("cordova/platform", function(require, exports, module) {
 
 module.exports = {
-    id: "android",
-    initialize:function() {
-        var channel = require("cordova/channel"),
+    id: 'amazon-fireos',
+    bootstrap: function() {
+        var channel = require('cordova/channel'),
             cordova = require('cordova'),
             exec = require('cordova/exec'),
             modulemapper = require('cordova/modulemapper');
 
-        modulemapper.loadMatchingModules(/cordova.*\/symbols$/);
-        modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
+        // Get the shared secret needed to use the bridge.
+        exec.init();
 
-        modulemapper.mapModules(window);
+        // TODO: Extract this as a proper plugin.
+        modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
 
         // Inject a listener for the backbutton on the document.
         var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
@@ -1213,607 +1499,177 @@ module.exports = {
 
         // Let native code know we are all done on the JS side.
         // Native code will then un-hide the WebView.
-        channel.join(function() {
+        channel.onCordovaReady.subscribe(function() {
             exec(null, null, "App", "show", []);
-        }, [channel.onCordovaReady]);
+        });
     }
 };
 
 });
 
-// file: lib/android/plugin/android/app.js
+// file: src/android/plugin/android/app.js
 define("cordova/plugin/android/app", function(require, exports, module) {
 
 var exec = require('cordova/exec');
 
 module.exports = {
-  /**
-   * Clear the resource cache.
-   */
-  clearCache:function() {
-    exec(null, null, "App", "clearCache", []);
-  },
-
-  /**
-   * Load the url into the webview or into new browser instance.
-   *
-   * @param url           The URL to load
-   * @param props         Properties that can be passed in to the activity:
-   *      wait: int                           => wait msec before loading URL
-   *      loadingDialog: "Title,Message"      => display a native loading dialog
-   *      loadUrlTimeoutValue: int            => time in msec to wait before triggering a timeout error
-   *      clearHistory: boolean              => clear webview history (default=false)
-   *      openExternal: boolean              => open in a new browser (default=false)
-   *
-   * Example:
-   *      navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
-   */
-  loadUrl:function(url, props) {
-    exec(null, null, "App", "loadUrl", [url, props]);
-  },
-
-  /**
-   * Cancel loadUrl that is waiting to be loaded.
-   */
-  cancelLoadUrl:function() {
-    exec(null, null, "App", "cancelLoadUrl", []);
-  },
-
-  /**
-   * Clear web history in this web view.
-   * Instead of BACK button loading the previous web page, it will exit the app.
-   */
-  clearHistory:function() {
-    exec(null, null, "App", "clearHistory", []);
-  },
-
-  /**
-   * Go to previous page displayed.
-   * This is the same as pressing the backbutton on Android device.
-   */
-  backHistory:function() {
-    exec(null, null, "App", "backHistory", []);
-  },
-
-  /**
-   * Override the default behavior of the Android back button.
-   * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
-   *
-   * Note: The user should not have to call this method.  Instead, when the user
-   *       registers for the "backbutton" event, this is automatically done.
-   *
-   * @param override        T=override, F=cancel override
-   */
-  overrideBackbutton:function(override) {
-    exec(null, null, "App", "overrideBackbutton", [override]);
-  },
-
-  /**
-   * Exit and terminate the application.
-   */
-  exitApp:function() {
-    return exec(null, null, "App", "exitApp", []);
-  }
-};
-
-});
-
-// file: lib/android/plugin/android/nativeapiprovider.js
-define("cordova/plugin/android/nativeapiprovider", function(require, exports, module) {
-
-/**
- * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
- */
-
-var nativeApi = this._cordovaNative || require('cordova/plugin/android/promptbasednativeapi');
-var currentApi = nativeApi;
-
-module.exports = {
-    get: function() { return currentApi; },
-    setPreferPrompt: function(value) {
-        currentApi = value ? require('cordova/plugin/android/promptbasednativeapi') : nativeApi;
+    /**
+    * Clear the resource cache.
+    */
+    clearCache:function() {
+        exec(null, null, "App", "clearCache", []);
     },
-    // Used only by tests.
-    set: function(value) {
-        currentApi = value;
-    }
-};
 
-});
-
-// file: lib/android/plugin/android/promptbasednativeapi.js
-define("cordova/plugin/android/promptbasednativeapi", function(require, exports, module) {
-
-/**
- * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
- * This is used only on the 2.3 simulator, where addJavascriptInterface() is broken.
- */
-
-module.exports = {
-    exec: function(service, action, callbackId, argsJson) {
-        return prompt(argsJson, 'gap:'+JSON.stringify([service, action, callbackId]));
-    },
-    setNativeToJsBridgeMode: function(value) {
-        prompt(value, 'gap_bridge_mode:');
+    /**
+    * Load the url into the webview or into new browser instance.
+    *
+    * @param url           The URL to load
+    * @param props         Properties that can be passed in to the activity:
+    *      wait: int                           => wait msec before loading URL
+    *      loadingDialog: "Title,Message"      => display a native loading dialog
+    *      loadUrlTimeoutValue: int            => time in msec to wait before triggering a timeout error
+    *      clearHistory: boolean              => clear webview history (default=false)
+    *      openExternal: boolean              => open in a new browser (default=false)
+    *
+    * Example:
+    *      navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
+    */
+    loadUrl:function(url, props) {
+        exec(null, null, "App", "loadUrl", [url, props]);
     },
-    retrieveJsMessages: function() {
-        return prompt('', 'gap_poll:');
-    }
-};
-
-});
-
-// file: lib/android/plugin/android/storage.js
-define("cordova/plugin/android/storage", function(require, exports, module) {
-
-var utils = require('cordova/utils'),
-    exec = require('cordova/exec'),
-    channel = require('cordova/channel');
-
-var queryQueue = {};
-
-/**
- * SQL result set object
- * PRIVATE METHOD
- * @constructor
- */
-var DroidDB_Rows = function() {
-    this.resultSet = [];    // results array
-    this.length = 0;        // number of rows
-};
-
-/**
- * Get item from SQL result set
- *
- * @param row           The row number to return
- * @return              The row object
- */
-DroidDB_Rows.prototype.item = function(row) {
-    return this.resultSet[row];
-};
-
-/**
- * SQL result set that is returned to user.
- * PRIVATE METHOD
- * @constructor
- */
-var DroidDB_Result = function() {
-    this.rows = new DroidDB_Rows();
-};
-
-/**
- * Callback from native code when query is complete.
- * PRIVATE METHOD
- *
- * @param id   Query id
- */
-function completeQuery(id, data) {
-    var query = queryQueue[id];
-    if (query) {
-        try {
-            delete queryQueue[id];
-
-            // Get transaction
-            var tx = query.tx;
-
-            // If transaction hasn't failed
-            // Note: We ignore all query results if previous query
-            //       in the same transaction failed.
-            if (tx && tx.queryList[id]) {
-
-                // Save query results
-                var r = new DroidDB_Result();
-                r.rows.resultSet = data;
-                r.rows.length = data.length;
-                try {
-                    if (typeof query.successCallback === 'function') {
-                        query.successCallback(query.tx, r);
-                    }
-                } catch (ex) {
-                    console.log("executeSql error calling user success callback: "+ex);
-                }
-
-                tx.queryComplete(id);
-            }
-        } catch (e) {
-            console.log("executeSql error: "+e);
-        }
-    }
-}
-
-/**
- * Callback from native code when query fails
- * PRIVATE METHOD
- *
- * @param reason            Error message
- * @param id                Query id
- */
-function failQuery(reason, id) {
-    var query = queryQueue[id];
-    if (query) {
-        try {
-            delete queryQueue[id];
-
-            // Get transaction
-            var tx = query.tx;
-
-            // If transaction hasn't failed
-            // Note: We ignore all query results if previous query
-            //       in the same transaction failed.
-            if (tx && tx.queryList[id]) {
-                tx.queryList = {};
-
-                try {
-                    if (typeof query.errorCallback === 'function') {
-                        query.errorCallback(query.tx, reason);
-                    }
-                } catch (ex) {
-                    console.log("executeSql error calling user error callback: "+ex);
-                }
-
-                tx.queryFailed(id, reason);
-            }
-
-        } catch (e) {
-            console.log("executeSql error: "+e);
-        }
-    }
-}
-
-/**
- * SQL query object
- * PRIVATE METHOD
- *
- * @constructor
- * @param tx                The transaction object that this query belongs to
- */
-var DroidDB_Query = function(tx) {
-
-    // Set the id of the query
-    this.id = utils.createUUID();
-
-    // Add this query to the queue
-    queryQueue[this.id] = this;
-
-    // Init result
-    this.resultSet = [];
-
-    // Set transaction that this query belongs to
-    this.tx = tx;
-
-    // Add this query to transaction list
-    this.tx.queryList[this.id] = this;
-
-    // Callbacks
-    this.successCallback = null;
-    this.errorCallback = null;
-
-};
-
-/**
- * Transaction object
- * PRIVATE METHOD
- * @constructor
- */
-var DroidDB_Tx = function() {
-
-    // Set the id of the transaction
-    this.id = utils.createUUID();
-
-    // Callbacks
-    this.successCallback = null;
-    this.errorCallback = null;
-
-    // Query list
-    this.queryList = {};
-};
-
-/**
- * Mark query in transaction as complete.
- * If all queries are complete, call the user's transaction success callback.
- *
- * @param id                Query id
- */
-DroidDB_Tx.prototype.queryComplete = function(id) {
-    delete this.queryList[id];
-
-    // If no more outstanding queries, then fire transaction success
-    if (this.successCallback) {
-        var count = 0;
-        var i;
-        for (i in this.queryList) {
-            if (this.queryList.hasOwnProperty(i)) {
-                count++;
-            }
-        }
-        if (count === 0) {
-            try {
-                this.successCallback();
-            } catch(e) {
-                console.log("Transaction error calling user success callback: " + e);
-            }
-        }
-    }
-};
-
-/**
- * Mark query in transaction as failed.
- *
- * @param id                Query id
- * @param reason            Error message
- */
-DroidDB_Tx.prototype.queryFailed = function(id, reason) {
-
-    // The sql queries in this transaction have already been run, since
-    // we really don't have a real transaction implemented in native code.
-    // However, the user callbacks for the remaining sql queries in transaction
-    // will not be called.
-    this.queryList = {};
-
-    if (this.errorCallback) {
-        try {
-            this.errorCallback(reason);
-        } catch(e) {
-            console.log("Transaction error calling user error callback: " + e);
-        }
-    }
-};
-
-/**
- * Execute SQL statement
- *
- * @param sql                   SQL statement to execute
- * @param params                Statement parameters
- * @param successCallback       Success callback
- * @param errorCallback         Error callback
- */
-DroidDB_Tx.prototype.executeSql = function(sql, params, successCallback, errorCallback) {
-
-    // Init params array
-    if (typeof params === 'undefined') {
-        params = [];
-    }
-
-    // Create query and add to queue
-    var query = new DroidDB_Query(this);
-    queryQueue[query.id] = query;
-
-    // Save callbacks
-    query.successCallback = successCallback;
-    query.errorCallback = errorCallback;
-
-    // Call native code
-    exec(null, null, "Storage", "executeSql", [sql, params, query.id]);
-};
-
-var DatabaseShell = function() {
-};
-
-/**
- * Start a transaction.
- * Does not support rollback in event of failure.
- *
- * @param process {Function}            The transaction function
- * @param successCallback {Function}
- * @param errorCallback {Function}
- */
-DatabaseShell.prototype.transaction = function(process, errorCallback, successCallback) {
-    var tx = new DroidDB_Tx();
-    tx.successCallback = successCallback;
-    tx.errorCallback = errorCallback;
-    try {
-        process(tx);
-    } catch (e) {
-        console.log("Transaction error: "+e);
-        if (tx.errorCallback) {
-            try {
-                tx.errorCallback(e);
-            } catch (ex) {
-                console.log("Transaction error calling user error callback: "+e);
-            }
-        }
-    }
-};
-
-/**
- * Open database
- *
- * @param name              Database name
- * @param version           Database version
- * @param display_name      Database display name
- * @param size              Database size in bytes
- * @return                  Database object
- */
-var DroidDB_openDatabase = function(name, version, display_name, size) {
-    exec(null, null, "Storage", "openDatabase", [name, version, display_name, size]);
-    var db = new DatabaseShell();
-    return db;
-};
-
-
-module.exports = {
-  openDatabase:DroidDB_openDatabase,
-  failQuery:failQuery,
-  completeQuery:completeQuery
-};
-
-});
-
-// file: lib/android/plugin/android/storage/openDatabase.js
-define("cordova/plugin/android/storage/openDatabase", function(require, exports, module) {
-
-
-var modulemapper = require('cordova/modulemapper'),
-    storage = require('cordova/plugin/android/storage');
-
-var originalOpenDatabase = modulemapper.getOriginalSymbol(window, 'openDatabase');
-
-module.exports = function(name, version, desc, size) {
-    // First patch WebSQL if necessary
-    if (!originalOpenDatabase) {
-        // Not defined, create an openDatabase function for all to use!
-        return storage.openDatabase.apply(this, arguments);
-    }
-
-    // Defined, but some Android devices will throw a SECURITY_ERR -
-    // so we wrap the whole thing in a try-catch and shim in our own
-    // if the device has Android bug 16175.
-    try {
-        return originalOpenDatabase(name, version, desc, size);
-    } catch (ex) {
-        if (ex.code !== 18) {
-            throw ex;
-        }
-    }
-    return storage.openDatabase(name, version, desc, size);
-};
-
-
-
-});
-
-// file: lib/android/plugin/android/storage/symbols.js
-define("cordova/plugin/android/storage/symbols", function(require, exports, module) {
-
-
-var modulemapper = require('cordova/modulemapper');
-
-modulemapper.clobbers('cordova/plugin/android/storage/openDatabase', 'openDatabase');
 
+    /**
+    * Cancel loadUrl that is waiting to be loaded.
+    */
+    cancelLoadUrl:function() {
+        exec(null, null, "App", "cancelLoadUrl", []);
+    },
 
-});
+    /**
+    * Clear web history in this web view.
+    * Instead of BACK button loading the previous web page, it will exit the app.
+    */
+    clearHistory:function() {
+        exec(null, null, "App", "clearHistory", []);
+    },
 
-// file: lib/common/plugin/echo.js
-define("cordova/plugin/echo", function(require, exports, module) {
+    /**
+    * Go to previous page displayed.
+    * This is the same as pressing the backbutton on Android device.
+    */
+    backHistory:function() {
+        exec(null, null, "App", "backHistory", []);
+    },
 
-var exec = require('cordova/exec'),
-    utils = require('cordova/utils');
+    /**
+    * Override the default behavior of the Android back button.
+    * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
+    *
+    * Note: The user should not have to call this method.  Instead, when the user
+    *       registers for the "backbutton" event, this is automatically done.
+    *
+    * @param override        T=override, F=cancel override
+    */
+    overrideBackbutton:function(override) {
+        exec(null, null, "App", "overrideBackbutton", [override]);
+    },
 
-/**
- * Sends the given message through exec() to the Echo plugin, which sends it back to the successCallback.
- * @param successCallback  invoked with a FileSystem object
- * @param errorCallback  invoked if error occurs retrieving file system
- * @param message  The string to be echoed.
- * @param forceAsync  Whether to force an async return value (for testing native->js bridge).
- */
-module.exports = function(successCallback, errorCallback, message, forceAsync) {
-    var action = 'echo';
-    var messageIsMultipart = (utils.typeName(message) == "Array");
-    var args = messageIsMultipart ? message : [message];
-
-    if (utils.typeName(message) == 'ArrayBuffer') {
-        if (forceAsync) {
-            console.warn('Cannot echo ArrayBuffer with forced async, falling back to sync.');
-        }
-        action += 'ArrayBuffer';
-    } else if (messageIsMultipart) {
-        if (forceAsync) {
-            console.warn('Cannot echo MultiPart Array with forced async, falling back to sync.');
-        }
-        action += 'MultiPart';
-    } else if (forceAsync) {
-        action += 'Async';
+    /**
+    * Exit and terminate the application.
+    */
+    exitApp:function() {
+        return exec(null, null, "App", "exitApp", []);
     }
-
-    exec(successCallback, errorCallback, "Echo", action, args);
 };
 
-
 });
 
-// file: lib/common/pluginloader.js
+// file: src/common/pluginloader.js
 define("cordova/pluginloader", function(require, exports, module) {
 
-var channel = require('cordova/channel');
 var modulemapper = require('cordova/modulemapper');
+var urlutil = require('cordova/urlutil');
 
 // Helper function to inject a <script> tag.
-function injectScript(url, onload, onerror) {
+// Exported for testing.
+exports.injectScript = function(url, onload, onerror) {
     var script = document.createElement("script");
     // onload fires even when script fails loads with an error.
     script.onload = onload;
-    script.onerror = onerror || onload;
+    // onerror fires for malformed URLs.
+    script.onerror = onerror;
     script.src = url;
     document.head.appendChild(script);
+};
+
+function injectIfNecessary(id, url, onload, onerror) {
+    onerror = onerror || onload;
+    if (id in define.moduleMap) {
+        onload();
+    } else {
+        exports.injectScript(url, function() {
+            if (id in define.moduleMap) {
+                onload();
+            } else {
+                onerror();
+            }
+        }, onerror);
+    }
 }
 
-function onScriptLoadingComplete(moduleList) {
+function onScriptLoadingComplete(moduleList, finishPluginLoading) {
     // Loop through all the plugins and then through their clobbers and merges.
     for (var i = 0, module; module = moduleList[i]; i++) {
-        if (module) {
-            try {
-                if (module.clobbers && module.clobbers.length) {
-                    for (var j = 0; j < module.clobbers.length; j++) {
-                        modulemapper.clobbers(module.id, module.clobbers[j]);
-                    }
-                }
-
-                if (module.merges && module.merges.length) {
-                    for (var k = 0; k < module.merges.length; k++) {
-                        modulemapper.merges(module.id, module.merges[k]);
-                    }
-                }
-
-                // Finally, if runs is truthy we want to simply require() the module.
-                // This can be skipped if it had any merges or clobbers, though,
-                // since the mapper will already have required the module.
-                if (module.runs && !(module.clobbers && module.clobbers.length) && !(module.merges && module.merges.length)) {
-                    modulemapper.runs(module.id);
-                }
+        if (module.clobbers && module.clobbers.length) {
+            for (var j = 0; j < module.clobbers.length; j++) {
+                modulemapper.clobbers(module.id, module.clobbers[j]);
             }
-            catch(err) {
-                // error with module, most likely clobbers, should we continue?
+        }
+
+        if (module.merges && module.merges.length) {
+            for (var k = 0; k < module.merges.length; k++) {
+                modulemapper.merges(module.id, module.merges[k]);
             }
         }
+
+        // Finally, if runs is truthy we want to simply require() the module.
+        if (module.runs) {
+            modulemapper.runs(module.id);
+        }
     }
 
     finishPluginLoading();
 }
 
-// Called when:
-// * There are plugins defined and all plugins are finished loading.
-// * There are no plugins to load.
-function finishPluginLoading() {
-    channel.onPluginsReady.fire();
-}
-
 // Handler for the cordova_plugins.js content.
 // See plugman's plugin_loader.js for the details of this object.
 // This function is only called if the really is a plugins array that isn't empty.
 // Otherwise the onerror response handler will just call finishPluginLoading().
-function handlePluginsObject(path, moduleList) {
+function handlePluginsObject(path, moduleList, finishPluginLoading) {
     // Now inject the scripts.
     var scriptCounter = moduleList.length;
+
+    if (!scriptCounter) {
+        finishPluginLoading();
+        return;
+    }
     function scriptLoadedCallback() {
         if (!--scriptCounter) {
-            onScriptLoadingComplete(moduleList);
+            onScriptLoadingComplete(moduleList, finishPluginLoading);
         }
     }
 
     for (var i = 0; i < moduleList.length; i++) {
-        injectScript(path + moduleList[i].file, scriptLoadedCallback);
+        injectIfNecessary(moduleList[i].id, path + moduleList[i].file, scriptLoadedCallback);
     }
 }
 
-function injectPluginScript(pathPrefix) {
-    injectScript(pathPrefix + 'cordova_plugins.js', function(){
-        try {
-            var moduleList = require("cordova/plugin_list");
-            handlePluginsObject(pathPrefix, moduleList);
-        } catch (e) {
-            // Error loading cordova_plugins.js, file not found or something
-            // this is an acceptable error, pre-3.0.0, so we just move on.
-            finishPluginLoading();
-        }
-    },finishPluginLoading); // also, add script load error handler for file not found
-}
-
 function findCordovaPath() {
     var path = null;
     var scripts = document.getElementsByTagName('script');
     var term = 'cordova.js';
     for (var n = scripts.length-1; n>-1; n--) {
-        var src = scripts[n].src;
+        var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
         if (src.indexOf(term) == (src.length - term.length)) {
             path = src.substring(0, src.length - term.length);
             break;
@@ -1825,32 +1681,39 @@ function findCordovaPath() {
 // Tries to load all plugins' js-modules.
 // This is an async process, but onDeviceReady is blocked on onPluginsReady.
 // onPluginsReady is fired when there are no plugins to load, or they are all done.
-exports.load = function() {
+exports.load = function(callback) {
     var pathPrefix = findCordovaPath();
     if (pathPrefix === null) {
         console.log('Could not find cordova.js script tag. Plugin loading may fail.');
         pathPrefix = '';
     }
-    injectPluginScript(pathPrefix);
+    injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function() {
+        var moduleList = require("cordova/plugin_list");
+        handlePluginsObject(pathPrefix, moduleList, callback);
+    }, callback);
 };
 
 
 });
 
-// file: lib/common/symbols.js
-define("cordova/symbols", function(require, exports, module) {
+// file: src/common/urlutil.js
+define("cordova/urlutil", function(require, exports, module) {
 
-var modulemapper = require('cordova/modulemapper');
 
-// Use merges here in case others symbols files depend on this running first,
-// but fail to declare the dependency with a require().
-modulemapper.merges('cordova', 'cordova');
-modulemapper.clobbers('cordova/exec', 'cordova.exec');
-modulemapper.clobbers('cordova/exec', 'Cordova.exec');
+/**
+ * For already absolute URLs, returns what is passed in.
+ * For relative URLs, converts them to absolute ones.
+ */
+exports.makeAbsolute = function makeAbsolute(url) {
+    var anchorEl = document.createElement('a');
+    anchorEl.href = url;
+    return anchorEl.href;
+};
+
 
 });
 
-// file: lib/common/utils.js
+// file: src/common/utils.js
 define("cordova/utils", function(require, exports, module) {
 
 var utils = exports;
@@ -2021,95 +1884,8 @@ function UUIDcreatePart(length) {
 });
 
 window.cordova = require('cordova');
-// file: lib/scripts/bootstrap.js
-
-(function (context) {
-    if (context._cordovaJsLoaded) {
-        throw new Error('cordova.js included multiple times.');
-    }
-    context._cordovaJsLoaded = true;
-
-    var channel = require('cordova/channel');
-    var pluginloader = require('cordova/pluginloader');
-
-    var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
-
-    function logUnfiredChannels(arr) {
-        for (var i = 0; i < arr.length; ++i) {
-            if (arr[i].state != 2) {
-                console.log('Channel not fired: ' + arr[i].type);
-            }
-        }
-    }
-
-    window.setTimeout(function() {
-        if (channel.onDeviceReady.state != 2) {
-            console.log('deviceready has not fired after 5 seconds.');
-            logUnfiredChannels(platformInitChannelsArray);
-            logUnfiredChannels(channel.deviceReadyChannelsArray);
-        }
-    }, 5000);
-
-    // Replace navigator before any modules are required(), to ensure it happens as soon as possible.
-    // We replace it so that properties that can't be clobbered can instead be overridden.
-    function replaceNavigator(origNavigator) {
-        var CordovaNavigator = function() {};
-        CordovaNavigator.prototype = origNavigator;
-        var newNavigator = new CordovaNavigator();
-        // This work-around really only applies to new APIs that are newer than Function.bind.
-        // Without it, APIs such as getGamepads() break.
-        if (CordovaNavigator.bind) {
-            for (var key in origNavigator) {
-                if (typeof origNavigator[key] == 'function') {
-                    newNavigator[key] = origNavigator[key].bind(origNavigator);
-                }
-            }
-        }
-        return newNavigator;
-    }
-    if (context.navigator) {
-        context.navigator = replaceNavigator(context.navigator);
-    }
-
-    // _nativeReady is global variable that the native side can set
-    // to signify that the native code is ready. It is a global since
-    // it may be called before any cordova JS is ready.
-    if (window._nativeReady) {
-        channel.onNativeReady.fire();
-    }
-
-    /**
-     * Create all cordova objects once native side is ready.
-     */
-    channel.join(function() {
-        // Call the platform-specific initialization
-        require('cordova/platform').initialize();
-
-        // Fire event to notify that all objects are created
-        channel.onCordovaReady.fire();
-
-        // Fire onDeviceReady event once page has fully loaded, all
-        // constructors have run and cordova info has been received from native
-        // side.
-        // This join call is deliberately made after platform.initialize() in
-        // order that plugins may manipulate channel.deviceReadyChannelsArray
-        // if necessary.
-        channel.join(function() {
-            require('cordova').fireDocumentEvent('deviceready');
-        }, channel.deviceReadyChannelsArray);
-
-    }, platformInitChannelsArray);
-
-    // Don't attempt to load when running unit tests.
-    if (typeof XMLHttpRequest != 'undefined') {
-        pluginloader.load();
-    }
-}(window));
-
-// file: lib/scripts/bootstrap-android.js
+// file: src/scripts/bootstrap.js
 
-// Tell the native code that a page change has occurred.
-require('cordova/exec')(null, null, 'PluginManager', 'startup', []);
-require('cordova/channel').onNativeReady.fire();
+require('cordova/init');
 
 })();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/5843c7e0/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java
----------------------------------------------------------------------
diff --git a/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java b/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java
index 0dd1c20..6ec1edf 100644
--- a/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java
+++ b/test/src/org/apache/cordova/test/CordovaWebViewTestActivity.java
@@ -45,7 +45,7 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter
     private final ExecutorService threadPool = Executors.newCachedThreadPool();
     private static boolean sFactoryInit = false;
     private AmazonWebKitFactory factory = null;
-    
+      
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -57,7 +57,7 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter
            if (factory.isRenderProcess(this)) {
                return; // Do nothing if this is on render process
            }
-           factory.initialize(this);
+          factory.initialize(this);
            
            sFactoryInit = true;
        } else {
@@ -70,6 +70,7 @@ public class CordovaWebViewTestActivity extends Activity implements CordovaInter
         Config.init(this);
         
         cordovaWebView = (CordovaWebView) findViewById(R.id.cordovaWebView);
+        factory.initializeWebView(cordovaWebView, 0xFFFFFF, false, null);
         cordovaWebView.init(this, new CordovaWebViewClient(this, cordovaWebView), new CordovaChromeClient(this, cordovaWebView),
                 Config.getPluginEntries(), Config.getWhitelist(), Config.getPreferences());
 

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/5843c7e0/test/src/org/apache/cordova/test/junit/BackButtonMultiPageTest.java
----------------------------------------------------------------------
diff --git a/test/src/org/apache/cordova/test/junit/BackButtonMultiPageTest.java b/test/src/org/apache/cordova/test/junit/BackButtonMultiPageTest.java
index f481e6b..1e56894 100644
--- a/test/src/org/apache/cordova/test/junit/BackButtonMultiPageTest.java
+++ b/test/src/org/apache/cordova/test/junit/BackButtonMultiPageTest.java
@@ -21,11 +21,13 @@ package org.apache.cordova.test.junit;
  *
  */
 
+import org.apache.cordova.Config;
+import org.apache.cordova.CordovaChromeClient;
 import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.CordovaWebViewClient;
 import org.apache.cordova.test.backbuttonmultipage;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
 import android.test.UiThreadTest;
 import android.view.KeyEvent;
 import android.view.inputmethod.BaseInputConnection;
@@ -207,7 +209,7 @@ public class BackButtonMultiPageTest extends
       });
       
   }
-  
+
   public void testViaBackButtonOnLayout() throws Throwable {
       runTestOnUiThread(new Runnable() {
           public void run()

http://git-wip-us.apache.org/repos/asf/cordova-amazon-fireos/blob/5843c7e0/test/src/org/apache/cordova/test/junit/PluginManagerTest.java
----------------------------------------------------------------------
diff --git a/test/src/org/apache/cordova/test/junit/PluginManagerTest.java b/test/src/org/apache/cordova/test/junit/PluginManagerTest.java
index 721487b..cf6ed0d 100644
--- a/test/src/org/apache/cordova/test/junit/PluginManagerTest.java
+++ b/test/src/org/apache/cordova/test/junit/PluginManagerTest.java
@@ -26,7 +26,6 @@ import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.FutureTask;
 
-import org.apache.cordova.CordovaInterface;
 import org.apache.cordova.CordovaWebView;
 import org.apache.cordova.PluginEntry;
 import org.apache.cordova.PluginManager;
@@ -50,12 +49,9 @@ public class PluginManagerTest extends ActivityInstrumentationTestCase2<CordovaW
     private static final String PLUGIN4_CLASS = PLUGIN_PACKAGE + PLUGIN4_SERVICE;
     private static final String PLUGIN5_SERVICE = "Plugin5";
     private static final String PLUGIN5_CLASS = PLUGIN_PACKAGE + PLUGIN5_SERVICE;
-    private static final String TAG = "PluginManagerTest";
     private static final String TEST_URL = "file:///android_asset/www/plugins/%s.html";
     private static final String PLUGIN1_URL = String.format(TEST_URL, PLUGIN1_SERVICE);
-    private static final String PLUGIN2_URL = String.format(TEST_URL, PLUGIN2_SERVICE);
     private static final String PLUGIN3_URL = String.format(TEST_URL, PLUGIN3_SERVICE);
-    private static final String PLUGIN4_URL = String.format(TEST_URL, PLUGIN4_SERVICE);
     private static final String PLUGIN5_URL = String.format(TEST_URL, PLUGIN5_SERVICE);
 
     private CordovaWebViewTestActivity testActivity;
@@ -65,8 +61,6 @@ public class PluginManagerTest extends ActivityInstrumentationTestCase2<CordovaW
     private PluginManager pluginMgr;
     private CordovaWebView mWebView;
 
-    private CordovaInterface cordova;
-    private PluginManager testPluginManager;
 
     public PluginManagerTest() {
         super("org.apache.cordova.test.activities", CordovaWebViewTestActivity.class);
@@ -167,8 +161,9 @@ public class PluginManagerTest extends ActivityInstrumentationTestCase2<CordovaW
         addTestPlugin(PLUGIN2_SERVICE, PLUGIN2_CLASS, true, -99f);
         addTestPlugin(PLUGIN3_SERVICE, PLUGIN3_CLASS, true, -98f);
         
-        Field entries = pluginMgr.getClass().getDeclaredField("entries");
+        Field entries = pluginMgr.getClass().getDeclaredField("entryMap");
         entries.setAccessible(true);
+        @SuppressWarnings("unchecked")
         LinkedHashMap<String, PluginEntry> testEntries = (LinkedHashMap<String, PluginEntry>) entries.get(pluginMgr);
         List<PluginEntry> pluginList = new ArrayList<PluginEntry>();
         for (PluginEntry entry : testEntries.values())
@@ -193,8 +188,8 @@ public class PluginManagerTest extends ActivityInstrumentationTestCase2<CordovaW
      */
     private void addTestPlugin(String service, String cls, boolean onload, final float priority) {
         PluginEntry pEntry = new PluginEntry(service, cls, onload, priority);
-        pEntry.createPlugin(mWebView, testActivity);
         pluginMgr.addService(pEntry);
+        pluginMgr.getPlugin(service);
     }
 
     /**


Mime
View raw message