From bd806a34d83ac086c3854ee7d0f74da534125a77 Mon Sep 17 00:00:00 2001 From: Joe Bowser Date: Wed, 12 Mar 2014 15:04:28 -0700 Subject: [PATCH] Removing XWalkWebView and making it a plugin component --- .../engine/crosswalk/XWalkCordovaWebView.java | 1147 ----------------- .../crosswalk/XWalkCordovaWebViewClient.java | 636 --------- .../crosswalk/XwalkCordovaChromeClient.java | 428 ------ .../CordovaXWalkCoreExtensionBridge.java | 17 - 4 files changed, 2228 deletions(-) delete mode 100755 framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java delete mode 100755 framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebViewClient.java delete mode 100755 framework/src/org/apache/cordova/engine/crosswalk/XwalkCordovaChromeClient.java delete mode 100644 framework/src/org/xwalk/runtime/extension/CordovaXWalkCoreExtensionBridge.java diff --git a/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java b/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java deleted file mode 100755 index 682e28b1..00000000 --- a/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebView.java +++ /dev/null @@ -1,1147 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ - -package org.apache.cordova.engine.crosswalk; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Locale; - -import org.apache.cordova.Config; -import org.apache.cordova.CordovaChromeClient; -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.CordovaResourceApi; -import org.apache.cordova.CordovaWebView; -import org.apache.cordova.CordovaWebViewClient; -import org.apache.cordova.LOG; -import org.apache.cordova.NativeToJsMessageQueue; -import org.apache.cordova.ExposedJsApi; -import org.apache.cordova.PluginManager; -import org.apache.cordova.PluginResult; -import org.apache.cordova.ScrollEvent; -import org.json.JSONException; -import org.xwalk.core.WebBackForwardList; -import org.xwalk.core.WebHistoryItem; -import org.xwalk.core.XWalkSettings; -import org.xwalk.core.XWalkView; -import org.xwalk.core.XWalkWebChromeClient; -import org.xwalk.runtime.extension.XWalkExtensionManager; - -import android.app.Activity; -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.util.AttributeSet; -import android.util.Log; -import android.view.Gravity; -import android.view.KeyEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; -import android.view.inputmethod.InputMethodManager; -import android.webkit.WebChromeClient.CustomViewCallback; -//import android.webkit.WebBackForwardList; -//import android.webkit.WebHistoryItem; -//import android.webkit.WebChromeClient; -//import android.webkit.WebSettings; -//import android.webkit.WebView; -//import android.webkit.WebSettings.LayoutAlgorithm; -import android.widget.FrameLayout; -import android.widget.LinearLayout.LayoutParams; - -/* - * This class is our web view. - * - * @see WebView guide - * @see WebView - */ -public class XWalkCordovaWebView extends XWalkView implements CordovaWebView { - - public static final String TAG = "CordovaWebView"; - public static final String CORDOVA_VERSION = "3.3.0"; - - private ArrayList keyDownCodes = new ArrayList(); - private ArrayList keyUpCodes = new ArrayList(); - - public PluginManager pluginManager; - private boolean paused; - - private XWalkExtensionManager extensionManager; - - private BroadcastReceiver receiver; - - - /** Activities and other important classes **/ - private CordovaInterface cordova; - XWalkCordovaWebViewClient viewClient; - @SuppressWarnings("unused") - private XwalkCordovaChromeClient chromeClient; - - private String url; - - // Flag to track that a loadUrl timeout occurred - int loadUrlTimeout = 0; - - private boolean bound; - - private boolean handleButton = false; - - private long lastMenuEventTime = 0; - - NativeToJsMessageQueue jsMessageQueue; - XwalkExposedJsApi exposedJsApi; - - /** custom view created by the browser (a video player for example) */ - private View mCustomView; - private XWalkWebChromeClient.CustomViewCallback mCustomViewCallback; - - private ActivityResult mResult = null; - - private CordovaResourceApi resourceApi; - - class ActivityResult { - - int request; - int result; - Intent incoming; - - public ActivityResult(int req, int res, Intent intent) { - request = req; - result = res; - incoming = intent; - } - - - } - - static final FrameLayout.LayoutParams COVER_SCREEN_GRAVITY_CENTER = - new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT, - Gravity.CENTER); - - /** - * Constructor. - * - * @param context - */ - public XWalkCordovaWebView(Context context) { - super(context, (Activity)null); - if (CordovaInterface.class.isInstance(context)) - { - this.cordova = (CordovaInterface) context; - } - else - { - Log.d(TAG, "Your activity must implement CordovaInterface to work"); - } - this.loadConfiguration(); - this.setup(); - } - - /** - * Constructor. - * - * @param context - * @param attrs - */ - public XWalkCordovaWebView(Context context, AttributeSet attrs) { - super(context, attrs); - if (CordovaInterface.class.isInstance(context)) - { - this.cordova = (CordovaInterface) context; - } - else - { - Log.d(TAG, "Your activity must implement CordovaInterface to work"); - } - this.setWebChromeClient(new XwalkCordovaChromeClient(this.cordova, this)); - this.initWebViewClient(this.cordova); - this.loadConfiguration(); - this.setup(); - } - - /** - * Constructor. - * - * @param context - * @param attrs - * @param defStyle - * - */ - public XWalkCordovaWebView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs); - if (CordovaInterface.class.isInstance(context)) - { - this.cordova = (CordovaInterface) context; - } - else - { - Log.d(TAG, "Your activity must implement CordovaInterface to work"); - } - this.setWebChromeClient(new XwalkCordovaChromeClient(this.cordova, this)); - this.loadConfiguration(); - this.setup(); - } - - /** - * Constructor. - * - * @param context - * @param attrs - * @param defStyle - * @param privateBrowsing - */ - @TargetApi(11) - public XWalkCordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) { - super(context, attrs); - if (CordovaInterface.class.isInstance(context)) - { - this.cordova = (CordovaInterface) context; - } - else - { - Log.d(TAG, "Your activity must implement CordovaInterface to work"); - } - this.setWebChromeClient(new XwalkCordovaChromeClient(this.cordova)); - this.initWebViewClient(this.cordova); - this.loadConfiguration(); - this.setup(); - } - - - private void initWebViewClient(CordovaInterface cordova) { - this.setWebViewClient(new XWalkCordovaWebViewClient(this.cordova, this)); - } - - /** - * Initialize webview. - */ - @SuppressWarnings("deprecation") - @SuppressLint("NewApi") - private void setup() { - this.setInitialScale(0); - this.setVerticalScrollBarEnabled(false); - if (shouldRequestFocusOnInit()) { - this.requestFocusFromTouch(); - } - // Enable JavaScript - XWalkSettings settings = this.getSettings(); - settings.setJavaScriptEnabled(true); - settings.setJavaScriptCanOpenWindowsAutomatically(true); - // nhu: N/A - //settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL); - - //We don't save any form data in the application - // nhu: N/A - //settings.setSaveFormData(false); - //settings.setSavePassword(false); - - // Jellybean rightfully tried to lock this down. Too bad they didn't give us a whitelist - // while we do this - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) - Level16Apis.enableUniversalAccess(settings); - // Enable database - // We keep this disabled because we use or shim to get around DOM_EXCEPTION_ERROR_16 - String databasePath = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); - //settings.setDatabaseEnabled(true); - //TODO: bring it back when it's ready in the XWalk. - //settings.setDatabasePath(databasePath); - - - //Determine whether we're in debug or release mode, and turn on Debugging! - try { - final String packageName = this.cordova.getActivity().getPackageName(); - final PackageManager pm = this.cordova.getActivity().getPackageManager(); - ApplicationInfo appInfo; - - appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA); - - if((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0 && - android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) - { - //TODO: bring it back when it's ready in the XWalk. - //setWebContentsDebuggingEnabled(true); - } - } catch (IllegalArgumentException e) { - Log.d(TAG, "You have one job! To turn on Remote Web Debugging! YOU HAVE FAILED! "); - e.printStackTrace(); - } catch (NameNotFoundException e) { - Log.d(TAG, "This should never happen: Your application's package can't be found."); - e.printStackTrace(); - } - - //settings.setGeolocationDatabasePath(databasePath); - - // Enable DOM storage - settings.setDomStorageEnabled(true); - - // Enable built-in geolocation - settings.setGeolocationEnabled(true); - - // Enable AppCache - // Fix for CB-2282 - // nhu: N/A - //settings.setAppCacheMaxSize(5 * 1048576); - String pathToCache = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); - settings.setAppCachePath(pathToCache); - settings.setAppCacheEnabled(true); - - pluginManager = new PluginManager(this, this.cordova); - extensionManager = new XWalkExtensionManager(this.cordova.getActivity(), this.cordova.getActivity()); - extensionManager.loadExtensions(); - jsMessageQueue = new NativeToJsMessageQueue(this, cordova); - exposedJsApi = new XwalkExposedJsApi(pluginManager, jsMessageQueue); - resourceApi = new CordovaResourceApi(this.getContext(), pluginManager); - exposeJsInterface(); - } - - /** - * Override this method to decide whether or not you need to request the - * focus when your application start - * - * @return true unless this method is overriden to return a different value - */ - protected boolean shouldRequestFocusOnInit() { - return true; - } - - private void exposeJsInterface() { - int SDK_INT = Build.VERSION.SDK_INT; - boolean isHoneycomb = (SDK_INT >= Build.VERSION_CODES.HONEYCOMB && SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2); - if (isHoneycomb || (SDK_INT < Build.VERSION_CODES.GINGERBREAD)) { - Log.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old."); - // Bug being that Java Strings do not get converted to JS strings automatically. - // This isn't hard to work-around on the JS side, but it's easier to just - // use the prompt bridge instead. - return; - } else if (SDK_INT < Build.VERSION_CODES.HONEYCOMB && Build.MANUFACTURER.equals("unknown")) { - // addJavascriptInterface crashes on the 2.3 emulator. - Log.i(TAG, "Disabled addJavascriptInterface() bridge callback due to a bug on the 2.3 emulator"); - return; - } - this.addJavascriptInterface(exposedJsApi, "_cordovaNative"); - } - - /** - * Set the WebViewClient. - * - * @param client - */ - public void setWebViewClient(XWalkCordovaWebViewClient client) { - this.viewClient = client; - super.setXWalkClient(client); - } - - /** - * Set the WebChromeClient. - * - * @param client - */ - public void setWebChromeClient(XwalkCordovaChromeClient client) { - this.chromeClient = client; - super.setXWalkWebChromeClient(client); - } - - public XwalkCordovaChromeClient getWebChromeClient() { - return this.chromeClient; - } - - /** - * Load the url into the webview. - * - * @param url - */ - @Override - public void loadUrl(String url) { - if (url.equals("about:blank") || url.startsWith("javascript:")) { - this.loadUrlNow(url); - } - else { - - String initUrl = this.getProperty("url", null); - - // If first page of app, then set URL to load to be the one passed in - if (initUrl == null) { - this.loadUrlIntoView(url); - } - // Otherwise use the URL specified in the activity's extras bundle - else { - this.loadUrlIntoView(initUrl); - } - } - } - - /** - * Load the url into the webview after waiting for period of time. - * This is used to display the splashscreen for certain amount of time. - * - * @param url - * @param time The number of ms to wait before loading webview - */ - public void loadUrl(final String url, int time) { - String initUrl = this.getProperty("url", null); - - // If first page of app, then set URL to load to be the one passed in - if (initUrl == null) { - this.loadUrlIntoView(url, time); - } - // Otherwise use the URL specified in the activity's extras bundle - else { - this.loadUrlIntoView(initUrl); - } - } - - /** - * Load the url into the webview. - * - * @param url - */ - public void loadUrlIntoView(final String url) { - LOG.d(TAG, ">>> loadUrl(" + url + ")"); - - this.url = url; - this.pluginManager.init(); - - - // Create a timeout timer for loadUrl - final XWalkCordovaWebView me = this; - final int currentLoadUrlTimeout = me.loadUrlTimeout; - final int loadUrlTimeoutValue = Integer.parseInt(this.getProperty("LoadUrlTimeoutValue", "20000")); - - // Timeout error method - final Runnable loadError = new Runnable() { - public void run() { - me.stopLoading(); - LOG.e(TAG, "CordovaWebView: TIMEOUT ERROR!"); - if (viewClient != null) { - viewClient.onReceivedError((CordovaWebView) me, -6, "The connection to the server was unsuccessful.", url); - } - } - }; - - // Timeout timer method - final Runnable timeoutCheck = new Runnable() { - public void run() { - try { - synchronized (this) { - wait(loadUrlTimeoutValue); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - - // If timeout, then stop loading and handle error - if (me.loadUrlTimeout == currentLoadUrlTimeout) { - me.cordova.getActivity().runOnUiThread(loadError); - } - } - }; - - // Load url - this.cordova.getActivity().runOnUiThread(new Runnable() { - public void run() { - Thread thread = new Thread(timeoutCheck); - thread.start(); - me.loadUrlNow(url); - } - }); - } - - /** - * Load URL in webview. - * - * @param url - */ - public void loadUrlNow(String url) { - if (LOG.isLoggable(LOG.DEBUG) && !url.startsWith("javascript:")) { - LOG.d(TAG, ">>> loadUrlNow()"); - } - if (url.startsWith("file://") || url.startsWith("javascript:") || Config.isUrlWhiteListed(url)) { - super.loadUrl(url); - } - } - - /** - * Load the url into the webview after waiting for period of time. - * This is used to display the splashscreen for certain amount of time. - * - * @param url - * @param time The number of ms to wait before loading webview - */ - public void loadUrlIntoView(final String url, final int time) { - - // If not first page of app, then load immediately - // Add support for browser history if we use it. - if ((url.startsWith("javascript:")) || this.canGoBack()) { - } - - // If first page, then show splashscreen - else { - - LOG.d(TAG, "loadUrlIntoView(%s, %d)", url, time); - - // Send message to show splashscreen now if desired - this.postMessage("splashscreen", "show"); - } - - // Load url - this.loadUrlIntoView(url); - } - - - public void onScrollChanged(int l, int t, int oldl, int oldt) - { - super.onScrollChanged(l, t, oldl, oldt); - //We should post a message that the scroll changed - ScrollEvent myEvent = new ScrollEvent(l, t, oldl, oldt, this); - this.postMessage("onScrollChanged", myEvent); - } - - /** - * Send JavaScript statement back to JavaScript. - * (This is a convenience method) - * - * @param statement - */ - public void sendJavascript(String statement) { - this.jsMessageQueue.addJavaScript(statement); - } - - /** - * Send a plugin result back to JavaScript. - * (This is a convenience method) - * - * @param result - * @param callbackId - */ - public void sendPluginResult(PluginResult result, String callbackId) { - this.jsMessageQueue.addPluginResult(result, callbackId); - } - - /** - * Send a message to all plugins. - * - * @param id The message id - * @param data The message data - */ - public void postMessage(String id, Object data) { - if (this.pluginManager != null) { - this.pluginManager.postMessage(id, data); - } - } - - - /** - * Go to previous page in history. (We manage our own history) - * - * @return true if we went back, false if we are already at top - */ - public boolean backHistory() { - - // Check webview first to see if there is a history - // This is needed to support curPage#diffLink, since they are added to appView's history, but not our history url array (JQMobile behavior) - if (super.canGoBack()) { - printBackForwardList(); - super.goBack(); - - return true; - } - return false; - } - - - /** - * Load the specified URL in the Cordova webview or a new browser instance. - * - * NOTE: If openExternal is false, only URLs listed in whitelist can be loaded. - * - * @param url The url to load. - * @param openExternal Load url in browser instead of Cordova webview. - * @param clearHistory Clear the history stack, so new page becomes top of history - * @param params Parameters for new app - */ - public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap params) { - LOG.d(TAG, "showWebPage(%s, %b, %b, HashMap", url, openExternal, clearHistory); - - // If clearing history - if (clearHistory) { - this.clearHistory(); - } - - // If loading into our webview - if (!openExternal) { - - // Make sure url is in whitelist - if (url.startsWith("file://") || Config.isUrlWhiteListed(url)) { - // TODO: What about params? - // Load new URL - this.loadUrl(url); - } - // Load in default viewer if not - else { - LOG.w(TAG, "showWebPage: Cannot load URL into webview since it is not in white list. Loading into browser instead. (URL=" + url + ")"); - try { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(url)); - cordova.getActivity().startActivity(intent); - } catch (android.content.ActivityNotFoundException e) { - LOG.e(TAG, "Error loading url " + url, e); - } - } - } - - // Load in default view intent - else { - try { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(url)); - cordova.getActivity().startActivity(intent); - } catch (android.content.ActivityNotFoundException e) { - LOG.e(TAG, "Error loading url " + url, e); - } - } - } - - /** - * Check configuration parameters from Config. - * Approved list of URLs that can be loaded into Cordova - * - * Log level: ERROR, WARN, INFO, DEBUG, VERBOSE (default=ERROR) - * - */ - private void loadConfiguration() { - - if ("true".equals(this.getProperty("Fullscreen", "false"))) { - this.cordova.getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); - this.cordova.getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - } - - /** - * Get string property for activity. - * - * @param name - * @param defaultValue - * @return the String value for the named property - */ - public String getProperty(String name, String defaultValue) { - Bundle bundle = this.cordova.getActivity().getIntent().getExtras(); - if (bundle == null) { - return defaultValue; - } - name = name.toLowerCase(Locale.getDefault()); - Object p = bundle.get(name); - if (p == null) { - return defaultValue; - } - return p.toString(); - } - - /* - * onKeyDown - */ - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) - { - if(keyDownCodes.contains(keyCode)) - { - if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { - // only override default behavior is event bound - LOG.d(TAG, "Down Key Hit"); - this.loadUrl("javascript:cordova.fireDocumentEvent('volumedownbutton');"); - return true; - } - // If volumeup key - else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { - LOG.d(TAG, "Up Key Hit"); - this.loadUrl("javascript:cordova.fireDocumentEvent('volumeupbutton');"); - return true; - } - else - { - return super.onKeyDown(keyCode, event); - } - } - else if(keyCode == KeyEvent.KEYCODE_BACK) - { - return !(this.startOfHistory()) || this.bound; - } - else if(keyCode == KeyEvent.KEYCODE_MENU) - { - //How did we get here? Is there a childView? - View childView = (View) this.getFocusedChild(); - if(childView != null) - { - //Make sure we close the keyboard if it's present - InputMethodManager imm = (InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(childView.getWindowToken(), 0); - cordova.getActivity().openOptionsMenu(); - return true; - } else { - return super.onKeyDown(keyCode, event); - } - } - - return super.onKeyDown(keyCode, event); - } - - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) - { - // If back key - if (keyCode == KeyEvent.KEYCODE_BACK) { - // A custom view is currently displayed (e.g. playing a video) - if (this.isFullscreen()) { - this.exitFullscreen(); - return true; - } else if (mCustomView != null) { - this.hideCustomView(); - return true; - } else { - // The webview is currently displayed - // If back key is bound, then send event to JavaScript - if (this.bound) { - this.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');"); - return true; - } else { - // If not bound - // Go to previous page in webview if it is possible to go back - if (this.backHistory()) { - return true; - } - // If not, then invoke default behaviour - else { - //this.activityState = ACTIVITY_EXITING; - //return false; - // If they hit back button when app is initializing, app should exit instead of hang until initilazation (CB2-458) - this.cordova.getActivity().finish(); - return false; - } - } - } - } - // Legacy - else if (keyCode == KeyEvent.KEYCODE_MENU) { - if (this.lastMenuEventTime < event.getEventTime()) { - this.loadUrl("javascript:cordova.fireDocumentEvent('menubutton');"); - } - this.lastMenuEventTime = event.getEventTime(); - return super.onKeyUp(keyCode, event); - } - // If search key - else if (keyCode == KeyEvent.KEYCODE_SEARCH) { - this.loadUrl("javascript:cordova.fireDocumentEvent('searchbutton');"); - return true; - } - else if(keyUpCodes.contains(keyCode)) - { - //What the hell should this do? - return super.onKeyUp(keyCode, event); - } - - //Does webkit change this behavior? - return super.onKeyUp(keyCode, event); - } - - - public void bindButton(boolean override) - { - this.bound = override; - } - - public void bindButton(String button, boolean override) { - // TODO Auto-generated method stub - if (button.compareTo("volumeup")==0) { - keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_UP); - } - else if (button.compareTo("volumedown")==0) { - keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_DOWN); - } - } - - public void bindButton(int keyCode, boolean keyDown, boolean override) { - if(keyDown) - { - keyDownCodes.add(keyCode); - } - else - { - keyUpCodes.add(keyCode); - } - } - - public boolean isBackButtonBound() - { - return this.bound; - } - - public void handlePause(boolean keepRunning) - { - LOG.d(TAG, "Handle the pause"); - // Send pause event to JavaScript - this.loadUrl("javascript:try{cordova.fireDocumentEvent('pause');}catch(e){console.log('exception firing pause event from native');};"); - - // Forward to plugins - if (this.pluginManager != null) { - this.pluginManager.onPause(keepRunning); - } - - if (this.extensionManager != null) { - this.extensionManager.onPause(); - } - - // If app doesn't want to run in background - if (!keepRunning) { - // Pause JavaScript timers (including setInterval) - this.pauseTimers(); - } - paused = true; - - } - - public void handleResume(boolean keepRunning, boolean activityResultKeepRunning) - { - - this.loadUrl("javascript:try{cordova.fireDocumentEvent('resume');}catch(e){console.log('exception firing resume event from native');};"); - - // Forward to plugins - if (this.pluginManager != null) { - this.pluginManager.onResume(keepRunning); - } - - if (this.extensionManager != null) { - this.extensionManager.onResume(); - } - - // Resume JavaScript timers (including setInterval) - this.resumeTimers(); - paused = false; - } - - public void handleDestroy() - { - // Send destroy event to JavaScript - this.loadUrl("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};"); - - // Load blank page so that JavaScript onunload is called - this.loadUrl("about:blank"); - - // Forward to plugins - if (this.pluginManager != null) { - this.pluginManager.onDestroy(); - } - - if (this.extensionManager != null) { - this.extensionManager.onDestroy(); - } - - // unregister the receiver - if (this.receiver != null) { - try { - this.cordova.getActivity().unregisterReceiver(this.receiver); - } catch (Exception e) { - Log.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e); - } - } - } - - public void onNewIntent(Intent intent) - { - //Forward to plugins - if (this.pluginManager != null) { - this.pluginManager.onNewIntent(intent); - } - } - - public boolean isPaused() - { - return paused; - } - - public boolean hadKeyEvent() { - return handleButton; - } - - // Wrapping these functions in their own class prevents warnings in adb like: - // VFY: unable to resolve virtual method 285: Landroid/webkit/WebSettings;.setAllowUniversalAccessFromFileURLs - @TargetApi(16) - private static class Level16Apis { - static void enableUniversalAccess(XWalkSettings settings) { - settings.setAllowUniversalAccessFromFileURLs(true); - } - } - - public void printBackForwardList() { - WebBackForwardList currentList = this.copyBackForwardList(); - int currentSize = currentList.getSize(); - for(int i = 0; i < currentSize; ++i) - { - WebHistoryItem item = currentList.getItemAtIndex(i); - String url = item.getUrl(); - LOG.d(TAG, "The URL at index: " + Integer.toString(i) + " is " + url ); - } - } - - - //Can Go Back is BROKEN! - public boolean startOfHistory() - { - WebBackForwardList currentList = this.copyBackForwardList(); - WebHistoryItem item = currentList.getItemAtIndex(0); - if( item!=null){ // Null-fence in case they haven't called loadUrl yet (CB-2458) - String url = item.getUrl(); - String currentUrl = this.getUrl(); - LOG.d(TAG, "The current URL is: " + currentUrl); - LOG.d(TAG, "The URL at item 0 is: " + url); - return currentUrl.equals(url); - } - return false; - } - - public void showCustomView(View view, XWalkWebChromeClient.CustomViewCallback callback) { - // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0 - Log.d(TAG, "showing Custom View"); - // if a view already exists then immediately terminate the new one - if (mCustomView != null) { - callback.onCustomViewHidden(); - return; - } - - // Store the view and its callback for later (to kill it properly) - mCustomView = view; - mCustomViewCallback = callback; - - // Add the custom view to its container. - ViewGroup parent = (ViewGroup) this.getParent(); - parent.addView(view, COVER_SCREEN_GRAVITY_CENTER); - - // Hide the content view. - this.setVisibility(View.GONE); - - // Finally show the custom view container. - parent.setVisibility(View.VISIBLE); - parent.bringToFront(); - } - - public void hideCustomView() { - // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0 - Log.d(TAG, "Hidding Custom View"); - if (mCustomView == null) return; - - // Hide the custom view. - mCustomView.setVisibility(View.GONE); - - // Remove the custom view from its container. - ViewGroup parent = (ViewGroup) this.getParent(); - parent.removeView(mCustomView); - mCustomView = null; - mCustomViewCallback.onCustomViewHidden(); - - // Show the content view. - this.setVisibility(View.VISIBLE); - } - - /** - * if the video overlay is showing then we need to know - * as it effects back button handling - * - * @return true if custom view is showing - */ - public boolean isCustomViewShowing() { - return mCustomView != null; - } - - public WebBackForwardList restoreState(Bundle savedInstanceState) - { - WebBackForwardList myList = super.restoreState(savedInstanceState); - Log.d(TAG, "WebView restoration crew now restoring!"); - //Initialize the plugin manager once more - this.pluginManager.init(); - return myList; - } - - public void storeResult(int requestCode, int resultCode, Intent intent) { - mResult = new ActivityResult(requestCode, resultCode, intent); - } - - public CordovaResourceApi getResourceApi() { - return resourceApi; - } - - @Override - public void setWebViewClient(CordovaWebViewClient webViewClient) { - // TODO Auto-generated method stub - - } - - @Override - public void setWebChromeClient(CordovaChromeClient webChromeClient) { - // TODO Auto-generated method stub - - } - - @Override - public void setId(int i) { - // TODO Auto-generated method stub - - } - - @Override - public void setLayoutParams(LayoutParams layoutParams) { - // TODO Figure out how the XWalk gets laid out. This is goofy! - } - - @Override - public void setVisibility(int invisible) { - // TODO Auto-generated method stub - - } - - @Override - public boolean canGoBack() { - // TODO Auto-generated method stub - return false; - } - - @Override - public void clearCache(boolean b) { - // TODO Auto-generated method stub - - } - - @Override - public void clearHistory() { - // TODO Auto-generated method stub - - } - - @Override - public void addJavascript(String statement) { - // TODO Auto-generated method stub - - } - - @Override - public CordovaPlugin getPlugin(String initCallbackClass) { - // TODO Auto-generated method stub - return null; - } - - @Override - public View getFocusedChild() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String exec(String service, String action, String callbackId, - String message) throws JSONException { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setNativeToJsBridgeMode(int parseInt) { - // TODO Auto-generated method stub - - } - - @Override - public String retrieveJsMessages(boolean equals) { - // TODO Auto-generated method stub - return null; - } - - @Override - public void showCustomView(View view, CustomViewCallback callback) { - // TODO Auto-generated method stub - - } - - - - @Override - public boolean onOverrideUrlLoading(String url) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void resetJsMessageQueue() { - // TODO Auto-generated method stub - - } - - @Override - public void onReset() { - // TODO Auto-generated method stub - - } - - @Override - public int getVisibility() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public void incUrlTimeout() { - // TODO Auto-generated method stub - - } - - @Override - public void setOverScrollMode(int overScrollNever) { - // TODO Auto-generated method stub - - } - - @Override - public void setNetworkAvailable(boolean online) { - // TODO Auto-generated method stub - - } - - @Override - public PluginManager getPluginManager() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setLayoutParams( - android.widget.LinearLayout.LayoutParams layoutParams) { - // TODO Auto-generated method stub - - } -} diff --git a/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebViewClient.java b/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebViewClient.java deleted file mode 100755 index 262ae91e..00000000 --- a/framework/src/org/apache/cordova/engine/crosswalk/XWalkCordovaWebViewClient.java +++ /dev/null @@ -1,636 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ -package org.apache.cordova.engine.crosswalk; - -import java.io.ByteArrayInputStream; -import java.util.Hashtable; - -import org.apache.cordova.AuthenticationToken; -import org.apache.cordova.Config; -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.CordovaWebView; -import org.apache.cordova.CordovaWebViewClient; -import org.apache.cordova.LOG; -import org.apache.cordova.NativeToJsMessageQueue; -import org.json.JSONException; -import org.json.JSONObject; - -import android.annotation.TargetApi; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.graphics.Bitmap; -import android.net.Uri; -import android.net.http.SslError; -import android.util.Log; -import android.view.View; -//import android.webkit.HttpAuthHandler; -//import android.webkit.SslErrorHandler; -import android.webkit.WebResourceResponse; - - - - - -//import android.webkit.WebView; -//import android.webkit.WebViewClient; -import org.chromium.net.NetError; -import org.xwalk.core.XWalkView; -import org.xwalk.core.XWalkClient; -import org.xwalk.core.XWalkHttpAuthHandler; -import org.xwalk.core.SslErrorHandler; - -/** - * This class is the WebViewClient that implements callbacks for our web view. - * The kind of callbacks that happen here are regarding the rendering of the - * document instead of the chrome surrounding it, such as onPageStarted(), - * shouldOverrideUrlLoading(), etc. Related to but different than - * CordovaChromeClient. - * - * @see WebViewClient - * @see WebView guide - * @see XwalkCordovaChromeClient - * @see XWalkCordovaWebView - */ -public class XWalkCordovaWebViewClient extends XWalkClient implements CordovaWebViewClient { - - private static final String TAG = "CordovaWebViewClient"; - private static final String CORDOVA_EXEC_URL_PREFIX = "http://cdv_exec/"; - CordovaInterface cordova; - XWalkCordovaWebView appView; - private boolean doClearHistory = false; - - // Success - public static final int ERROR_OK = 0; - // Generic error - public static final int ERROR_UNKNOWN = -1; - // Server or proxy hostname lookup failed - public static final int ERROR_HOST_LOOKUP = -2; - // Unsupported authentication scheme (not basic or digest) - public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3; - // User authentication failed on server - public static final int ERROR_AUTHENTICATION = -4; - // User authentication failed on proxy - public static final int ERROR_PROXY_AUTHENTICATION = -5; - // Failed to connect to the server - public static final int ERROR_CONNECT = -6; - // Failed to read or write to the server - public static final int ERROR_IO = -7; - // Connection timed out - public static final int ERROR_TIMEOUT = -8; - // Too many redirects - public static final int ERROR_REDIRECT_LOOP = -9; - // Unsupported URI scheme - public static final int ERROR_UNSUPPORTED_SCHEME = -10; - // Failed to perform SSL handshake - public static final int ERROR_FAILED_SSL_HANDSHAKE = -11; - // Malformed URL - public static final int ERROR_BAD_URL = -12; - // Generic file error - public static final int ERROR_FILE = -13; - // File not found - public static final int ERROR_FILE_NOT_FOUND = -14; - // Too many requests during this load - public static final int ERROR_TOO_MANY_REQUESTS = -15; - - /** The authorization tokens. */ - private Hashtable authenticationTokens = new Hashtable(); - - /** - * Constructor. - * - * @param cordova - */ - public XWalkCordovaWebViewClient(CordovaInterface cordova) { - this.cordova = cordova; - } - - /** - * Constructor. - * - * @param cordova - * @param view - */ - public XWalkCordovaWebViewClient(CordovaInterface cordova, XWalkCordovaWebView view) { - this.cordova = cordova; - this.appView = view; - } - - /** - * Constructor. - * - * @param view - */ - public void setWebView(XWalkCordovaWebView view) { - this.appView = view; - } - - - // Parses commands sent by setting the webView's URL to: - // cdvbrg:service/action/callbackId#jsonArgs - private void handleExecUrl(String url) { - int idx1 = CORDOVA_EXEC_URL_PREFIX.length(); - int idx2 = url.indexOf('#', idx1 + 1); - int idx3 = url.indexOf('#', idx2 + 1); - int idx4 = url.indexOf('#', idx3 + 1); - if (idx1 == -1 || idx2 == -1 || idx3 == -1 || idx4 == -1) { - Log.e(TAG, "Could not decode URL command: " + url); - return; - } - String service = url.substring(idx1, idx2); - String action = url.substring(idx2 + 1, idx3); - String callbackId = url.substring(idx3 + 1, idx4); - String jsonArgs = url.substring(idx4 + 1); - appView.pluginManager.exec(service, action, callbackId, jsonArgs); - } - - // Map XWalk error code about loading a page to Android specific ones. - // XWalk shares the error code with chromium currently. - private int convertErrorCode(int netError) { - // Note: many NetError.Error constants don't have an obvious mapping. - // These will be handled by the default case, ERROR_UNKNOWN. - switch (netError) { - case NetError.ERR_UNSUPPORTED_AUTH_SCHEME: - return ERROR_UNSUPPORTED_AUTH_SCHEME; - - case NetError.ERR_INVALID_AUTH_CREDENTIALS: - case NetError.ERR_MISSING_AUTH_CREDENTIALS: - case NetError.ERR_MISCONFIGURED_AUTH_ENVIRONMENT: - return ERROR_AUTHENTICATION; - - case NetError.ERR_TOO_MANY_REDIRECTS: - return ERROR_REDIRECT_LOOP; - - case NetError.ERR_UPLOAD_FILE_CHANGED: - return ERROR_FILE_NOT_FOUND; - - case NetError.ERR_INVALID_URL: - return ERROR_BAD_URL; - - case NetError.ERR_DISALLOWED_URL_SCHEME: - case NetError.ERR_UNKNOWN_URL_SCHEME: - return ERROR_UNSUPPORTED_SCHEME; - - case NetError.ERR_IO_PENDING: - case NetError.ERR_NETWORK_IO_SUSPENDED: - return ERROR_IO; - - case NetError.ERR_CONNECTION_TIMED_OUT: - case NetError.ERR_TIMED_OUT: - return ERROR_TIMEOUT; - - case NetError.ERR_FILE_TOO_BIG: - return ERROR_FILE; - - case NetError.ERR_HOST_RESOLVER_QUEUE_TOO_LARGE: - case NetError.ERR_INSUFFICIENT_RESOURCES: - case NetError.ERR_OUT_OF_MEMORY: - return ERROR_TOO_MANY_REQUESTS; - - case NetError.ERR_CONNECTION_CLOSED: - case NetError.ERR_CONNECTION_RESET: - case NetError.ERR_CONNECTION_REFUSED: - case NetError.ERR_CONNECTION_ABORTED: - case NetError.ERR_CONNECTION_FAILED: - case NetError.ERR_SOCKET_NOT_CONNECTED: - return ERROR_CONNECT; - - case NetError.ERR_INTERNET_DISCONNECTED: - case NetError.ERR_ADDRESS_INVALID: - case NetError.ERR_ADDRESS_UNREACHABLE: - case NetError.ERR_NAME_NOT_RESOLVED: - case NetError.ERR_NAME_RESOLUTION_FAILED: - return ERROR_HOST_LOOKUP; - - case NetError.ERR_SSL_PROTOCOL_ERROR: - case NetError.ERR_SSL_CLIENT_AUTH_CERT_NEEDED: - case NetError.ERR_TUNNEL_CONNECTION_FAILED: - case NetError.ERR_NO_SSL_VERSIONS_ENABLED: - case NetError.ERR_SSL_VERSION_OR_CIPHER_MISMATCH: - case NetError.ERR_SSL_RENEGOTIATION_REQUESTED: - case NetError.ERR_CERT_ERROR_IN_SSL_RENEGOTIATION: - case NetError.ERR_BAD_SSL_CLIENT_AUTH_CERT: - case NetError.ERR_SSL_NO_RENEGOTIATION: - case NetError.ERR_SSL_DECOMPRESSION_FAILURE_ALERT: - case NetError.ERR_SSL_BAD_RECORD_MAC_ALERT: - case NetError.ERR_SSL_UNSAFE_NEGOTIATION: - case NetError.ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY: - case NetError.ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED: - case NetError.ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY: - return ERROR_FAILED_SSL_HANDSHAKE; - - case NetError.ERR_PROXY_AUTH_UNSUPPORTED: - case NetError.ERR_PROXY_AUTH_REQUESTED: - case NetError.ERR_PROXY_CONNECTION_FAILED: - case NetError.ERR_UNEXPECTED_PROXY_AUTH: - return ERROR_PROXY_AUTHENTICATION; - - // The certificate errors are handled by onReceivedSslError - // and don't need to be reported here. - case NetError.ERR_CERT_COMMON_NAME_INVALID: - case NetError.ERR_CERT_DATE_INVALID: - case NetError.ERR_CERT_AUTHORITY_INVALID: - case NetError.ERR_CERT_CONTAINS_ERRORS: - case NetError.ERR_CERT_NO_REVOCATION_MECHANISM: - case NetError.ERR_CERT_UNABLE_TO_CHECK_REVOCATION: - case NetError.ERR_CERT_REVOKED: - case NetError.ERR_CERT_INVALID: - case NetError.ERR_CERT_WEAK_SIGNATURE_ALGORITHM: - case NetError.ERR_CERT_NON_UNIQUE_NAME: - return ERROR_OK; - - default: - return ERROR_UNKNOWN; - } - } - - /** - * Give the host application a chance to take over the control when a new url - * is about to be loaded in the current WebView. - * - * @param view The WebView that is initiating the callback. - * @param url The url to be loaded. - * @return true to override, false for default behavior - */ - @Override - public boolean shouldOverrideUrlLoading(XWalkView view, String url) { - // Check if it's an exec() bridge command message. - if (NativeToJsMessageQueue.ENABLE_LOCATION_CHANGE_EXEC_MODE && url.startsWith(CORDOVA_EXEC_URL_PREFIX)) { - handleExecUrl(url); - } - - // Give plugins the chance to handle the url - else if ((this.appView.pluginManager != null) && this.appView.pluginManager.onOverrideUrlLoading(url)) { - } - - // If dialing phone (tel:5551212) - else if (url.startsWith("tel:")) { - try { - Intent intent = new Intent(Intent.ACTION_DIAL); - intent.setData(Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - } catch (android.content.ActivityNotFoundException e) { - LOG.e(TAG, "Error dialing " + url + ": " + e.toString()); - } - } - - // If displaying map (geo:0,0?q=address) - else if (url.startsWith("geo:")) { - try { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - } catch (android.content.ActivityNotFoundException e) { - LOG.e(TAG, "Error showing map " + url + ": " + e.toString()); - } - } - - // If sending email (mailto:abc@corp.com) - else if (url.startsWith("mailto:")) { - try { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - } catch (android.content.ActivityNotFoundException e) { - LOG.e(TAG, "Error sending email " + url + ": " + e.toString()); - } - } - - // If sms:5551212?body=This is the message - else if (url.startsWith("sms:")) { - try { - Intent intent = new Intent(Intent.ACTION_VIEW); - - // Get address - String address = null; - int parmIndex = url.indexOf('?'); - if (parmIndex == -1) { - address = url.substring(4); - } - else { - address = url.substring(4, parmIndex); - - // If body, then set sms body - Uri uri = Uri.parse(url); - String query = uri.getQuery(); - if (query != null) { - if (query.startsWith("body=")) { - intent.putExtra("sms_body", query.substring(5)); - } - } - } - intent.setData(Uri.parse("sms:" + address)); - intent.putExtra("address", address); - intent.setType("vnd.android-dir/mms-sms"); - this.cordova.getActivity().startActivity(intent); - } catch (android.content.ActivityNotFoundException e) { - LOG.e(TAG, "Error sending sms " + url + ":" + e.toString()); - } - } - - //Android Market - else if(url.startsWith("market:")) { - try { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - } catch (android.content.ActivityNotFoundException e) { - LOG.e(TAG, "Error loading Google Play Store: " + url, e); - } - } - - // All else - else { - - // If our app or file:, then load into a new Cordova webview container by starting a new instance of our activity. - // Our app continues to run. When BACK is pressed, our app is redisplayed. - if (url.startsWith("file://") || url.startsWith("data:") || Config.isUrlWhiteListed(url)) { - return false; - } - - // If not our application, let default viewer handle - else { - try { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(url)); - this.cordova.getActivity().startActivity(intent); - } catch (android.content.ActivityNotFoundException e) { - LOG.e(TAG, "Error loading url " + url, e); - } - } - } - return true; - } - - /** - * On received http auth request. - * The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination - * - * @param view - * @param handler - * @param host - * @param realm - */ - @Override - public void onReceivedHttpAuthRequest(XWalkView view, XWalkHttpAuthHandler handler, String host, String realm) { - - // Get the authentication token - AuthenticationToken token = this.getAuthenticationToken(host, realm); - if (token != null) { - handler.proceed(token.getUserName(), token.getPassword()); - } - else { - // Handle 401 like we'd normally do! - super.onReceivedHttpAuthRequest(view, handler, host, realm); - } - } - - /** - * Notify the host application that a page has started loading. - * This method is called once for each main frame load so a page with iframes or framesets will call onPageStarted - * one time for the main frame. This also means that onPageStarted will not be called when the contents of an - * embedded frame changes, i.e. clicking a link whose target is an iframe. - * - * @param view The webview initiating the callback. - * @param url The url of the page. - */ - @Override - public void onPageStarted(XWalkView view, String url, Bitmap favicon) { - - // Flush stale messages. - this.appView.resetJsMessageQueue(); - - // Broadcast message that page has loaded - this.appView.postMessage("onPageStarted", url); - - // Notify all plugins of the navigation, so they can clean up if necessary. - if (this.appView.pluginManager != null) { - this.appView.pluginManager.onReset(); - } - } - - /** - * Notify the host application that a page has finished loading. - * This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet. - * - * - * @param view The webview initiating the callback. - * @param url The url of the page. - */ - @Override - public void onPageFinished(XWalkView view, String url) { - super.onPageFinished(view, url); - LOG.d(TAG, "onPageFinished(" + url + ")"); - - /** - * Because of a timing issue we need to clear this history in onPageFinished as well as - * onPageStarted. However we only want to do this if the doClearHistory boolean is set to - * true. You see when you load a url with a # in it which is common in jQuery applications - * onPageStared is not called. Clearing the history at that point would break jQuery apps. - */ - if (this.doClearHistory) { - view.clearHistory(); - this.doClearHistory = false; - } - - // Clear timeout flag - this.appView.loadUrlTimeout++; - - // Broadcast message that page has loaded - this.appView.postMessage("onPageFinished", url); - - // Make app visible after 2 sec in case there was a JS error and Cordova JS never initialized correctly - if (this.appView.getVisibility() == View.INVISIBLE) { - Thread t = new Thread(new Runnable() { - public void run() { - try { - Thread.sleep(2000); - cordova.getActivity().runOnUiThread(new Runnable() { - public void run() { - appView.postMessage("spinner", "stop"); - } - }); - } catch (InterruptedException e) { - } - } - }); - t.start(); - } - - // Shutdown if blank loaded - if (url.equals("about:blank")) { - appView.postMessage("exit", null); - } - } - - /** - * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable). - * The errorCode parameter corresponds to one of the ERROR_* constants. - * - * @param view The WebView that is initiating the callback. - * @param errorCode The error code corresponding to an ERROR_* value. - * @param description A String describing the error. - * @param failingUrl The url that failed to load. - */ - @Override - public void onReceivedError(XWalkView view, int errorCode, String description, String failingUrl) { - LOG.d(TAG, "CordovaWebViewClient.onReceivedError: Error code=%s Description=%s URL=%s", errorCode, description, failingUrl); - - // Clear timeout flag - this.appView.loadUrlTimeout++; - - // Convert the XWalk error code to Cordova error code, which follows the Android spec, - // http://developer.android.com/reference/android/webkit/WebViewClient.html. - errorCode = convertErrorCode(errorCode); - - // Handle error - JSONObject data = new JSONObject(); - try { - data.put("errorCode", errorCode); - data.put("description", description); - data.put("url", failingUrl); - } catch (JSONException e) { - e.printStackTrace(); - } - this.appView.postMessage("onReceivedError", data); - } - - /** - * Notify the host application that an SSL error occurred while loading a resource. - * The host application must call either handler.cancel() or handler.proceed(). - * Note that the decision may be retained for use in response to future SSL errors. - * The default behavior is to cancel the load. - * - * @param view The WebView that is initiating the callback. - * @param handler An SslErrorHandler object that will handle the user's response. - * @param error The SSL error object. - */ - @TargetApi(8) - @Override - public void onReceivedSslError(XWalkView view, SslErrorHandler handler, SslError error) { - - final String packageName = this.cordova.getActivity().getPackageName(); - final PackageManager pm = this.cordova.getActivity().getPackageManager(); - - ApplicationInfo appInfo; - try { - appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA); - if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { - // debug = true - handler.proceed(); - return; - } else { - // debug = false - super.onReceivedSslError(view, handler, error); - } - } catch (NameNotFoundException e) { - // When it doubt, lock it out! - super.onReceivedSslError(view, handler, error); - } - } - - - /** - * Sets the authentication token. - * - * @param authenticationToken - * @param host - * @param realm - */ - public void setAuthenticationToken(AuthenticationToken authenticationToken, String host, String realm) { - if (host == null) { - host = ""; - } - if (realm == null) { - realm = ""; - } - this.authenticationTokens.put(host.concat(realm), authenticationToken); - } - - /** - * Removes the authentication token. - * - * @param host - * @param realm - * - * @return the authentication token or null if did not exist - */ - public AuthenticationToken removeAuthenticationToken(String host, String realm) { - return this.authenticationTokens.remove(host.concat(realm)); - } - - /** - * Gets the authentication token. - * - * In order it tries: - * 1- host + realm - * 2- host - * 3- realm - * 4- no host, no realm - * - * @param host - * @param realm - * - * @return the authentication token - */ - public AuthenticationToken getAuthenticationToken(String host, String realm) { - AuthenticationToken token = null; - token = this.authenticationTokens.get(host.concat(realm)); - - if (token == null) { - // try with just the host - token = this.authenticationTokens.get(host); - - // Try the realm - if (token == null) { - token = this.authenticationTokens.get(realm); - } - - // if no host found, just query for default - if (token == null) { - token = this.authenticationTokens.get(""); - } - } - - return token; - } - - /** - * Clear all authentication tokens. - */ - public void clearAuthenticationTokens() { - this.authenticationTokens.clear(); - } - - @Override - public void setWebView(CordovaWebView appView) { - // TODO Auto-generated method stub - - } - - @Override - public void onReceivedError(CordovaWebView me, int i, String string, - String url) { - //This should work, but may run into casting errors! - this.onReceivedError((XWalkView) me, i, string, url); - - } - -} diff --git a/framework/src/org/apache/cordova/engine/crosswalk/XwalkCordovaChromeClient.java b/framework/src/org/apache/cordova/engine/crosswalk/XwalkCordovaChromeClient.java deleted file mode 100755 index 342011e2..00000000 --- a/framework/src/org/apache/cordova/engine/crosswalk/XwalkCordovaChromeClient.java +++ /dev/null @@ -1,428 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*/ -package org.apache.cordova.engine.crosswalk; - -import org.apache.cordova.Config; -import org.apache.cordova.CordovaChromeClient; -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.CordovaWebView; -import org.apache.cordova.CordovaWebViewClient; -import org.apache.cordova.LOG; -import org.json.JSONArray; -import org.json.JSONException; - -import android.annotation.TargetApi; -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.net.Uri; -import android.view.Gravity; -import android.view.KeyEvent; -import android.view.View; -import android.view.ViewGroup.LayoutParams; -import android.webkit.ConsoleMessage; - - - - -//import android.webkit.JsPromptResult; -//import android.webkit.JsResult; -import org.xwalk.core.JsPromptResult; -import org.xwalk.core.JsResult; - -import android.webkit.ValueCallback; - - - - -//import android.webkit.WebChromeClient; -import org.xwalk.core.XWalkWebChromeClient; -import org.xwalk.core.client.XWalkDefaultWebChromeClient; - -import android.webkit.WebStorage; - - - - -//import android.webkit.WebView; -import org.xwalk.core.XWalkView; -import org.xwalk.core.XWalkGeolocationPermissions; - -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.RelativeLayout; - -/** - * This class is the WebChromeClient that implements callbacks for our web view. - * The kind of callbacks that happen here are on the chrome outside the document, - * such as onCreateWindow(), onConsoleMessage(), onProgressChanged(), etc. Related - * to but different than CordovaWebViewClient. - * - * @see WebChromeClient - * @see WebView guide - * @see XWalkCordovaWebViewClient - * @see XWalkCordovaWebView - */ -public class XwalkCordovaChromeClient extends XWalkDefaultWebChromeClient implements CordovaChromeClient { - - public static final int FILECHOOSER_RESULTCODE = 5173; - private static final String LOG_TAG = "CordovaChromeClient"; - private String TAG = "CordovaLog"; - private long MAX_QUOTA = 100 * 1024 * 1024; - protected CordovaInterface cordova; - protected XWalkCordovaWebView appView; - - // the video progress view - private View mVideoProgressView; - - // File Chooser - public ValueCallback mUploadMessage; - - /** - * Constructor. - * - * @param cordova - */ - public XwalkCordovaChromeClient(CordovaInterface cordova) { - super(cordova.getActivity(), null); - this.cordova = cordova; - } - - /** - * Constructor. - * - * @param ctx - * @param app - */ - public XwalkCordovaChromeClient(CordovaInterface ctx, XWalkCordovaWebView app) { - super(ctx.getActivity(), app); - this.cordova = ctx; - this.appView = app; - } - - /** - * Constructor. - * - * @param view - */ - public void setWebView(XWalkCordovaWebView view) { - this.appView = view; - } - - /** - * Tell the client to display a javascript alert dialog. - * - * @param view - * @param url - * @param message - * @param result - */ - @Override - public boolean onJsAlert(XWalkView view, String url, String message, final JsResult result) { - AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity()); - dlg.setMessage(message); - dlg.setTitle("Alert"); - //Don't let alerts break the back button - dlg.setCancelable(true); - dlg.setPositiveButton(android.R.string.ok, - new AlertDialog.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - result.confirm(); - } - }); - dlg.setOnCancelListener( - new DialogInterface.OnCancelListener() { - public void onCancel(DialogInterface dialog) { - result.cancel(); - } - }); - dlg.setOnKeyListener(new DialogInterface.OnKeyListener() { - //DO NOTHING - public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) - { - result.confirm(); - return false; - } - else - return true; - } - }); - dlg.create(); - dlg.show(); - return true; - } - - /** - * Tell the client to display a confirm dialog to the user. - * - * @param view - * @param url - * @param message - * @param result - */ - @Override - public boolean onJsConfirm(XWalkView view, String url, String message, final JsResult result) { - AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity()); - dlg.setMessage(message); - dlg.setTitle("Confirm"); - dlg.setCancelable(true); - dlg.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - result.confirm(); - } - }); - dlg.setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - result.cancel(); - } - }); - dlg.setOnCancelListener( - new DialogInterface.OnCancelListener() { - public void onCancel(DialogInterface dialog) { - result.cancel(); - } - }); - dlg.setOnKeyListener(new DialogInterface.OnKeyListener() { - //DO NOTHING - public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) - { - result.cancel(); - return false; - } - else - return true; - } - }); - dlg.create(); - dlg.show(); - return true; - } - - /** - * Tell the client to display a prompt dialog to the user. - * If the client returns true, WebView will assume that the client will - * handle the prompt dialog and call the appropriate JsPromptResult method. - * - * Since we are hacking prompts for our own purposes, we should not be using them for - * this purpose, perhaps we should hack console.log to do this instead! - * - * @param view - * @param url - * @param message - * @param defaultValue - * @param result - */ - @Override - public boolean onJsPrompt(XWalkView view, String url, String message, String defaultValue, JsPromptResult result) { - - // Security check to make sure any requests are coming from the page initially - // loaded in webview and not another loaded in an iframe. - boolean reqOk = false; - if (url.startsWith("file://") || Config.isUrlWhiteListed(url)) { - reqOk = true; - } - - // Calling PluginManager.exec() to call a native service using - // prompt(this.stringify(args), "gap:"+this.stringify([service, action, callbackId, true])); - if (reqOk && defaultValue != null && defaultValue.length() > 3 && defaultValue.substring(0, 4).equals("gap:")) { - JSONArray array; - try { - array = new JSONArray(defaultValue.substring(4)); - String service = array.getString(0); - String action = array.getString(1); - String callbackId = array.getString(2); - String r = this.appView.exec(service, action, callbackId, message); - result.confirm(r == null ? "" : r); - } catch (JSONException e) { - e.printStackTrace(); - return false; - } - } - - // Sets the native->JS bridge mode. - else if (reqOk && defaultValue != null && defaultValue.equals("gap_bridge_mode:")) { - try { - this.appView.setNativeToJsBridgeMode(Integer.parseInt(message)); - result.confirm(""); - } catch (NumberFormatException e){ - result.confirm(""); - e.printStackTrace(); - } - } - - // Polling for JavaScript messages - else if (reqOk && defaultValue != null && defaultValue.equals("gap_poll:")) { - String r = this.appView.retrieveJsMessages("1".equals(message)); - result.confirm(r == null ? "" : r); - } - - // Do NO-OP so older code doesn't display dialog - else if (defaultValue != null && defaultValue.equals("gap_init:")) { - result.confirm("OK"); - } - - // Show dialog - else { - final JsPromptResult res = result; - AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity()); - dlg.setMessage(message); - final EditText input = new EditText(this.cordova.getActivity()); - if (defaultValue != null) { - input.setText(defaultValue); - } - dlg.setView(input); - dlg.setCancelable(false); - dlg.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - String usertext = input.getText().toString(); - res.confirm(usertext); - } - }); - dlg.setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - res.cancel(); - } - }); - dlg.create(); - dlg.show(); - } - return true; - } - - /** - * Handle database quota exceeded notification. - */ - @Override - public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize, - long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) - { - LOG.d(TAG, "onExceededDatabaseQuota estimatedSize: %d currentQuota: %d totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota); - quotaUpdater.updateQuota(MAX_QUOTA); - } - - // console.log in api level 7: http://developer.android.com/guide/developing/debug-tasks.html - // Expect this to not compile in a future Android release! - @SuppressWarnings("deprecation") - @Override - public void onConsoleMessage(String message, int lineNumber, String sourceID) - { - //This is only for Android 2.1 - if(android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.ECLAIR_MR1) - { - LOG.d(TAG, "%s: Line %d : %s", sourceID, lineNumber, message); - super.onConsoleMessage(message, lineNumber, sourceID); - } - } - - @TargetApi(8) - @Override - public boolean onConsoleMessage(ConsoleMessage consoleMessage) - { - if (consoleMessage.message() != null) - LOG.d(TAG, "%s: Line %d : %s" , consoleMessage.sourceId() , consoleMessage.lineNumber(), consoleMessage.message()); - return super.onConsoleMessage(consoleMessage); - } - - @Override - /** - * Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin. - * - * @param origin - * @param callback - */ - public void onGeolocationPermissionsShowPrompt(String origin, XWalkGeolocationPermissions.Callback callback) { - super.onGeolocationPermissionsShowPrompt(origin, callback); - callback.invoke(origin, true, false); - } - - // API level 7 is required for this, see if we could lower this using something else - @Override - public void onShowCustomView(View view, XWalkWebChromeClient.CustomViewCallback callback) { - this.appView.showCustomView(view, callback); - } - - @Override - public void onHideCustomView() { - this.appView.hideCustomView(); - } - - @Override - /** - * Ask the host application for a custom progress view to show while - * a