blob: cc475c3299b3340b337bec1f892296ec156ec700 [file] [log] [blame]
/*
* 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;
}
}