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 <[email protected]> Authored: Thu Aug 14 11:16:40 2014 -0700 Committer: Archana Naik <[email protected]> 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); } /**
