blob: cc475c3299b3340b337bec1f892296ec156ec700 [file] [log] [blame]
Kristian Monsen98dedf72013-04-10 19:01:50 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.webkit;
18
Ignacio Solla451e3382014-11-10 10:35:54 +000019import android.annotation.SystemApi;
Kristian Monsen98dedf72013-04-10 19:01:50 -070020import android.app.Activity;
21import android.app.AlertDialog;
22import android.content.Context;
23import android.content.DialogInterface;
24import android.os.Message;
25import android.util.Log;
26import android.view.LayoutInflater;
27import android.view.View;
28import android.widget.EditText;
29import android.widget.TextView;
30
31import java.net.MalformedURLException;
32import java.net.URL;
33
34/**
35 * Helper class to create JavaScript dialogs. It is used by
36 * different WebView implementations.
37 *
Ignacio Solla451e3382014-11-10 10:35:54 +000038 * @hide
Kristian Monsen98dedf72013-04-10 19:01:50 -070039 */
Ignacio Solla451e3382014-11-10 10:35:54 +000040@SystemApi
Kristian Monsen98dedf72013-04-10 19:01:50 -070041public class JsDialogHelper {
42
43 private static final String TAG = "JsDialogHelper";
44
45 // Dialog types
46 public static final int ALERT = 1;
47 public static final int CONFIRM = 2;
48 public static final int PROMPT = 3;
49 public static final int UNLOAD = 4;
50
51 private final String mDefaultValue;
52 private final JsPromptResult mResult;
53 private final String mMessage;
54 private final int mType;
55 private final String mUrl;
56
57 public JsDialogHelper(JsPromptResult result, int type, String defaultValue, String message,
58 String url) {
59 mResult = result;
60 mDefaultValue = defaultValue;
61 mMessage = message;
62 mType = type;
63 mUrl = url;
64 }
65
66 public JsDialogHelper(JsPromptResult result, Message msg) {
67 mResult = result;
68 mDefaultValue = msg.getData().getString("default");
69 mMessage = msg.getData().getString("message");
70 mType = msg.getData().getInt("type");
71 mUrl = msg.getData().getString("url");
72 }
73
74 public boolean invokeCallback(WebChromeClient client, WebView webView) {
75 switch (mType) {
76 case ALERT:
77 return client.onJsAlert(webView, mUrl, mMessage, mResult);
78 case CONFIRM:
79 return client.onJsConfirm(webView, mUrl, mMessage, mResult);
80 case UNLOAD:
81 return client.onJsBeforeUnload(webView, mUrl, mMessage, mResult);
82 case PROMPT:
83 return client.onJsPrompt(webView, mUrl, mMessage, mDefaultValue, mResult);
84 default:
85 throw new IllegalArgumentException("Unexpected type: " + mType);
86 }
87 }
88
89 public void showDialog(Context context) {
90 if (!canShowAlertDialog(context)) {
91 Log.w(TAG, "Cannot create a dialog, the WebView context is not an Activity");
92 mResult.cancel();
93 return;
94 }
95
96 String title, displayMessage;
97 int positiveTextId, negativeTextId;
98 if (mType == UNLOAD) {
99 title = context.getString(com.android.internal.R.string.js_dialog_before_unload_title);
100 displayMessage = context.getString(
101 com.android.internal.R.string.js_dialog_before_unload, mMessage);
102 positiveTextId = com.android.internal.R.string.js_dialog_before_unload_positive_button;
103 negativeTextId = com.android.internal.R.string.js_dialog_before_unload_negative_button;
104 } else {
105 title = getJsDialogTitle(context);
106 displayMessage = mMessage;
107 positiveTextId = com.android.internal.R.string.ok;
108 negativeTextId = com.android.internal.R.string.cancel;
109 }
110 AlertDialog.Builder builder = new AlertDialog.Builder(context);
111 builder.setTitle(title);
112 builder.setOnCancelListener(new CancelListener());
113 if (mType != PROMPT) {
114 builder.setMessage(displayMessage);
115 builder.setPositiveButton(positiveTextId, new PositiveListener(null));
116 } else {
117 final View view = LayoutInflater.from(context).inflate(
118 com.android.internal.R.layout.js_prompt, null);
119 EditText edit = ((EditText) view.findViewById(com.android.internal.R.id.value));
120 edit.setText(mDefaultValue);
121 builder.setPositiveButton(positiveTextId, new PositiveListener(edit));
122 ((TextView) view.findViewById(com.android.internal.R.id.message)).setText(mMessage);
123 builder.setView(view);
124 }
125 if (mType != ALERT) {
126 builder.setNegativeButton(negativeTextId, new CancelListener());
127 }
128 builder.show();
129 }
130
131 private class CancelListener implements DialogInterface.OnCancelListener,
132 DialogInterface.OnClickListener {
133 @Override
134 public void onCancel(DialogInterface dialog) {
135 mResult.cancel();
136 }
137 @Override
138 public void onClick(DialogInterface dialog, int which) {
139 mResult.cancel();
140 }
141 }
142
143 private class PositiveListener implements DialogInterface.OnClickListener {
144 private final EditText mEdit;
145
146 public PositiveListener(EditText edit) {
147 mEdit = edit;
148 }
149
150 @Override
151 public void onClick(DialogInterface dialog, int which) {
152 if (mEdit == null) {
153 mResult.confirm();
154 } else {
155 mResult.confirm(mEdit.getText().toString());
156 }
157 }
158 }
159
160 private String getJsDialogTitle(Context context) {
161 String title = mUrl;
162 if (URLUtil.isDataUrl(mUrl)) {
163 // For data: urls, we just display 'JavaScript' similar to Chrome.
164 title = context.getString(com.android.internal.R.string.js_dialog_title_default);
165 } else {
166 try {
167 URL alertUrl = new URL(mUrl);
168 // For example: "The page at 'http://www.mit.edu' says:"
169 title = context.getString(com.android.internal.R.string.js_dialog_title,
170 alertUrl.getProtocol() + "://" + alertUrl.getHost());
171 } catch (MalformedURLException ex) {
172 // do nothing. just use the url as the title
173 }
174 }
175 return title;
176 }
177
178 private static boolean canShowAlertDialog(Context context) {
179 // We can only display the alert dialog if mContext is
180 // an Activity context.
181 // FIXME: Should we display dialogs if mContext does
182 // not have the window focus (e.g. if the user is viewing
183 // another Activity when the alert should be displayed) ?
184 // See bug 3166409
185 return context instanceof Activity;
186 }
187}