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_WebChromeClient.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeClient.java index 4cf7e581..2ec6cd37 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeClient.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebChromeClient.java @@ -2,6 +2,8 @@ package com.cradle.iitc_mobile; import android.webkit.ConsoleMessage; import android.webkit.GeolocationPermissions; +import android.webkit.JsPromptResult; +import android.webkit.JsResult; import android.webkit.WebChromeClient; import android.webkit.WebView; @@ -52,4 +54,26 @@ public class IITC_WebChromeClient extends WebChromeClient { return super.onConsoleMessage(message); } + + @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..76deb275 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java @@ -168,6 +168,7 @@ public class IITC_WebView extends WebView { } } + @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(final MotionEvent event) { getHandler().removeCallbacks(mNavHider);