diff --git a/mobile/res/layout/js_prompt.xml b/mobile/res/layout/js_prompt.xml new file mode 100644 index 00000000..6014282d --- /dev/null +++ b/mobile/res/layout/js_prompt.xml @@ -0,0 +1,43 @@ + + + + + + + + + + \ No newline at end of file diff --git a/mobile/res/values/strings_js.xml b/mobile/res/values/strings_js.xml new file mode 100644 index 00000000..6bf67186 --- /dev/null +++ b/mobile/res/values/strings_js.xml @@ -0,0 +1,17 @@ + + + + + The page at \"%s\" says: + + JavaScript + + Confirm Navigation + + Leave this Page + + Stay on this Page + + %s\n\nAre you sure you want to navigate away from this page? + + \ No newline at end of file diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_JsDialogHelper.java b/mobile/src/com/cradle/iitc_mobile/IITC_JsDialogHelper.java new file mode 100644 index 00000000..cd7a5d18 --- /dev/null +++ b/mobile/src/com/cradle/iitc_mobile/IITC_JsDialogHelper.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed 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 android.webkit; +package com.cradle.iitc_mobile; + +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.view.LayoutInflater; +import android.view.View; +import android.webkit.JsPromptResult; +import android.webkit.JsResult; +import android.webkit.URLUtil; +import android.webkit.WebView; +import android.widget.EditText; +import android.widget.TextView; + +import java.net.MalformedURLException; +import java.net.URL; + +/** + * Helper class to create JavaScript dialogs. It is used by + * different WebView implementations. + * + * @hide Helper class for internal use + */ +public class IITC_JsDialogHelper { + // Dialog types + public static final int ALERT = 1; + public static final int CONFIRM = 2; + public static final int PROMPT = 3; + public static final int UNLOAD = 4; + + private final String mDefaultValue; + private final JsResult mResult; + private final String mMessage; + private final int mType; + private final String mUrl; + + public IITC_JsDialogHelper(final int type, final WebView view, final String url, + final String message, final String defaultValue, final JsResult result) { + mResult = result; + mDefaultValue = defaultValue; + mMessage = message; + mType = type; + mUrl = url; + + showDialog(view.getContext()); + } + + @SuppressLint("InflateParams") + private void showDialog(final Context context) { + String title, displayMessage; + int positiveTextId, negativeTextId; + if (mType == UNLOAD) { + title = context.getString(R.string.js_dialog_before_unload_title); + displayMessage = context.getString( + R.string.js_dialog_before_unload, mMessage); + positiveTextId = R.string.js_dialog_before_unload_positive_button; + negativeTextId = R.string.js_dialog_before_unload_negative_button; + } else { + title = getJsDialogTitle(context); + displayMessage = mMessage; + positiveTextId = android.R.string.ok; + negativeTextId = android.R.string.cancel; + } + final AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(title); + builder.setOnCancelListener(new CancelListener()); + if (mType != PROMPT) { + builder.setMessage(displayMessage); + builder.setPositiveButton(positiveTextId, new PositiveListener(null)); + } else { + final View view = LayoutInflater.from(context).inflate( + R.layout.js_prompt, null); + final EditText edit = ((EditText) view.findViewById(R.id.value)); + edit.setText(mDefaultValue); + builder.setPositiveButton(positiveTextId, new PositiveListener(edit)); + ((TextView) view.findViewById(R.id.message)).setText(mMessage); + builder.setView(view); + } + if (mType != ALERT) { + builder.setNegativeButton(negativeTextId, new CancelListener()); + } + builder.show(); + } + + private class CancelListener implements DialogInterface.OnCancelListener, + DialogInterface.OnClickListener { + @Override + public void onCancel(final DialogInterface dialog) { + mResult.cancel(); + } + + @Override + public void onClick(final DialogInterface dialog, final int which) { + mResult.cancel(); + } + } + + private class PositiveListener implements DialogInterface.OnClickListener { + private final EditText mEdit; + + public PositiveListener(final EditText edit) { + mEdit = edit; + } + + @Override + public void onClick(final DialogInterface dialog, final int which) { + if (mEdit == null) { + mResult.confirm(); + } else { + ((JsPromptResult) mResult).confirm(mEdit.getText().toString()); + } + } + } + + private String getJsDialogTitle(final Context context) { + String title = mUrl; + if (URLUtil.isDataUrl(mUrl)) { + // For data: urls, we just display 'JavaScript' similar to Chrome. + title = context.getString(R.string.js_dialog_title_default); + } else { + try { + final URL alertUrl = new URL(mUrl); + // For example: "The page at 'http://www.mit.edu' says:" + title = context.getString(R.string.js_dialog_title, + alertUrl.getProtocol() + "://" + alertUrl.getHost()); + } catch (final MalformedURLException ex) { + // do nothing. just use the url as the title + } + } + return title; + } + + public boolean shouldInterrupt() { + return true; + } +} \ No newline at end of file diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java index 4e6e2965..9e6bb6d7 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_Mobile.java @@ -837,7 +837,7 @@ public class IITC_Mobile extends Activity final String js = "(function(obj){var result;" + "console.log('>>> ' + obj.code);" + "try{result=eval(obj.code);}catch(e){if(e.stack) console.error(e.stack);throw e;}" + - "if(result!==undefined) console.log(result.toString());" + + "if(result!==undefined) console.log(result===null?null:result.toString());" + "})(" + obj.toString() + ");"; mIitcWebView.loadJS(js); diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeLollipop.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeLollipop.java new file mode 100644 index 00000000..1a615ddb --- /dev/null +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeLollipop.java @@ -0,0 +1,31 @@ +package com.cradle.iitc_mobile; + +import android.webkit.JsPromptResult; +import android.webkit.JsResult; +import android.webkit.WebView; + +public class IITC_WebChromeLollipop extends IITC_WebChromeClient { + public IITC_WebChromeLollipop(final IITC_Mobile iitc) { + super(iitc); + } + + @Override + public boolean onJsAlert(final WebView view, final String url, final String message, final JsResult result) { + return new IITC_JsDialogHelper(IITC_JsDialogHelper.ALERT, view, url, message, null, result).shouldInterrupt(); + } + + @Override + public boolean onJsBeforeUnload(final WebView view, final String url, final String message, final JsResult result) { + return new IITC_JsDialogHelper(IITC_JsDialogHelper.UNLOAD, view, url, message, null, result).shouldInterrupt(); + } + + @Override + public boolean onJsConfirm(final WebView view, final String url, final String message, final JsResult result) { + return new IITC_JsDialogHelper(IITC_JsDialogHelper.CONFIRM, view, url, message, null, result).shouldInterrupt(); + } + + @Override + public boolean onJsPrompt(final WebView view, final String url, final String message, final String defaultValue, final JsPromptResult result) { + return new IITC_JsDialogHelper(IITC_JsDialogHelper.PROMPT, view, url, message, defaultValue, result).shouldInterrupt(); + } +} diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java index e64b4ad6..08cd4c2d 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java @@ -86,7 +86,11 @@ public class IITC_WebView extends WebView { } }; - mIitcWebChromeClient = new IITC_WebChromeClient(mIitc); + // if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { + mIitcWebChromeClient = new IITC_WebChromeLollipop(mIitc); + // } else { + // mIitcWebChromeClient = new IITC_WebChromeClient(mIitc); + // } setWebChromeClient(mIitcWebChromeClient); mIitcWebViewClient = new IITC_WebViewClient(mIitc); setWebViewClient(mIitcWebViewClient); @@ -168,6 +172,7 @@ public class IITC_WebView extends WebView { } } + @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(final MotionEvent event) { getHandler().removeCallbacks(mNavHider);