| /* |
| * 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; |
| |
| import android.annotation.SystemApi; |
| import android.app.Activity; |
| import android.app.AlertDialog; |
| import android.content.Context; |
| import android.content.DialogInterface; |
| import android.os.Message; |
| import android.util.Log; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| 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 |
| */ |
| @SystemApi |
| public class JsDialogHelper { |
| |
| private static final String TAG = "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 JsPromptResult mResult; |
| private final String mMessage; |
| private final int mType; |
| private final String mUrl; |
| |
| public JsDialogHelper(JsPromptResult result, int type, String defaultValue, String message, |
| String url) { |
| mResult = result; |
| mDefaultValue = defaultValue; |
| mMessage = message; |
| mType = type; |
| mUrl = url; |
| } |
| |
| public JsDialogHelper(JsPromptResult result, Message msg) { |
| mResult = result; |
| mDefaultValue = msg.getData().getString("default"); |
| mMessage = msg.getData().getString("message"); |
| mType = msg.getData().getInt("type"); |
| mUrl = msg.getData().getString("url"); |
| } |
| |
| public boolean invokeCallback(WebChromeClient client, WebView webView) { |
| switch (mType) { |
| case ALERT: |
| return client.onJsAlert(webView, mUrl, mMessage, mResult); |
| case CONFIRM: |
| return client.onJsConfirm(webView, mUrl, mMessage, mResult); |
| case UNLOAD: |
| return client.onJsBeforeUnload(webView, mUrl, mMessage, mResult); |
| case PROMPT: |
| return client.onJsPrompt(webView, mUrl, mMessage, mDefaultValue, mResult); |
| default: |
| throw new IllegalArgumentException("Unexpected type: " + mType); |
| } |
| } |
| |
| public void showDialog(Context context) { |
| if (!canShowAlertDialog(context)) { |
| Log.w(TAG, "Cannot create a dialog, the WebView context is not an Activity"); |
| mResult.cancel(); |
| return; |
| } |
| |
| String title, displayMessage; |
| int positiveTextId, negativeTextId; |
| if (mType == UNLOAD) { |
| title = context.getString(com.android.internal.R.string.js_dialog_before_unload_title); |
| displayMessage = context.getString( |
| com.android.internal.R.string.js_dialog_before_unload, mMessage); |
| positiveTextId = com.android.internal.R.string.js_dialog_before_unload_positive_button; |
| negativeTextId = com.android.internal.R.string.js_dialog_before_unload_negative_button; |
| } else { |
| title = getJsDialogTitle(context); |
| displayMessage = mMessage; |
| positiveTextId = com.android.internal.R.string.ok; |
| negativeTextId = com.android.internal.R.string.cancel; |
| } |
| 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( |
| com.android.internal.R.layout.js_prompt, null); |
| EditText edit = ((EditText) view.findViewById(com.android.internal.R.id.value)); |
| edit.setText(mDefaultValue); |
| builder.setPositiveButton(positiveTextId, new PositiveListener(edit)); |
| ((TextView) view.findViewById(com.android.internal.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(DialogInterface dialog) { |
| mResult.cancel(); |
| } |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| mResult.cancel(); |
| } |
| } |
| |
| private class PositiveListener implements DialogInterface.OnClickListener { |
| private final EditText mEdit; |
| |
| public PositiveListener(EditText edit) { |
| mEdit = edit; |
| } |
| |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| if (mEdit == null) { |
| mResult.confirm(); |
| } else { |
| mResult.confirm(mEdit.getText().toString()); |
| } |
| } |
| } |
| |
| private String getJsDialogTitle(Context context) { |
| String title = mUrl; |
| if (URLUtil.isDataUrl(mUrl)) { |
| // For data: urls, we just display 'JavaScript' similar to Chrome. |
| title = context.getString(com.android.internal.R.string.js_dialog_title_default); |
| } else { |
| try { |
| URL alertUrl = new URL(mUrl); |
| // For example: "The page at 'http://www.mit.edu' says:" |
| title = context.getString(com.android.internal.R.string.js_dialog_title, |
| alertUrl.getProtocol() + "://" + alertUrl.getHost()); |
| } catch (MalformedURLException ex) { |
| // do nothing. just use the url as the title |
| } |
| } |
| return title; |
| } |
| |
| private static boolean canShowAlertDialog(Context context) { |
| // We can only display the alert dialog if mContext is |
| // an Activity context. |
| // FIXME: Should we display dialogs if mContext does |
| // not have the window focus (e.g. if the user is viewing |
| // another Activity when the alert should be displayed) ? |
| // See bug 3166409 |
| return context instanceof Activity; |
| } |
| } |