198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen/* 298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * Copyright (C) 2013 The Android Open Source Project 398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * 498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * Licensed under the Apache License, Version 2.0 (the "License"); 598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * you may not use this file except in compliance with the License. 698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * You may obtain a copy of the License at 798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * 898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * http://www.apache.org/licenses/LICENSE-2.0 998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * 1098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * Unless required by applicable law or agreed to in writing, software 1198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * distributed under the License is distributed on an "AS IS" BASIS, 1298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * See the License for the specific language governing permissions and 1498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * limitations under the License. 1598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen */ 1698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 1798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenpackage android.webkit; 1898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 19451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Sollaimport android.annotation.SystemApi; 2098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenimport android.app.Activity; 2198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenimport android.app.AlertDialog; 2298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenimport android.content.Context; 2398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenimport android.content.DialogInterface; 2498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenimport android.os.Message; 2598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenimport android.util.Log; 2698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenimport android.view.LayoutInflater; 2798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenimport android.view.View; 2898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenimport android.widget.EditText; 2998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenimport android.widget.TextView; 3098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 3198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenimport java.net.MalformedURLException; 3298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenimport java.net.URL; 3398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 3498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen/** 3598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * Helper class to create JavaScript dialogs. It is used by 3698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * different WebView implementations. 3798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen * 38451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla * @hide 3998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen */ 40451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla@SystemApi 4198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsenpublic class JsDialogHelper { 4298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 4398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen private static final String TAG = "JsDialogHelper"; 4498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 4598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen // Dialog types 4698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen public static final int ALERT = 1; 4798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen public static final int CONFIRM = 2; 4898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen public static final int PROMPT = 3; 4998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen public static final int UNLOAD = 4; 5098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 5198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen private final String mDefaultValue; 5298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen private final JsPromptResult mResult; 5398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen private final String mMessage; 5498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen private final int mType; 5598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen private final String mUrl; 5698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 5798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen public JsDialogHelper(JsPromptResult result, int type, String defaultValue, String message, 5898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen String url) { 5998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mResult = result; 6098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mDefaultValue = defaultValue; 6198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mMessage = message; 6298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mType = type; 6398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mUrl = url; 6498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 6598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 6698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen public JsDialogHelper(JsPromptResult result, Message msg) { 6798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mResult = result; 6898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mDefaultValue = msg.getData().getString("default"); 6998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mMessage = msg.getData().getString("message"); 7098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mType = msg.getData().getInt("type"); 7198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mUrl = msg.getData().getString("url"); 7298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 7398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 7498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen public boolean invokeCallback(WebChromeClient client, WebView webView) { 7598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen switch (mType) { 7698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen case ALERT: 7798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen return client.onJsAlert(webView, mUrl, mMessage, mResult); 7898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen case CONFIRM: 7998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen return client.onJsConfirm(webView, mUrl, mMessage, mResult); 8098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen case UNLOAD: 8198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen return client.onJsBeforeUnload(webView, mUrl, mMessage, mResult); 8298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen case PROMPT: 8398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen return client.onJsPrompt(webView, mUrl, mMessage, mDefaultValue, mResult); 8498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen default: 8598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen throw new IllegalArgumentException("Unexpected type: " + mType); 8698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 8798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 8898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 8998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen public void showDialog(Context context) { 9098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen if (!canShowAlertDialog(context)) { 9198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen Log.w(TAG, "Cannot create a dialog, the WebView context is not an Activity"); 9298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mResult.cancel(); 9398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen return; 9498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 9598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 9698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen String title, displayMessage; 9798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen int positiveTextId, negativeTextId; 9898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen if (mType == UNLOAD) { 9998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen title = context.getString(com.android.internal.R.string.js_dialog_before_unload_title); 10098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen displayMessage = context.getString( 10198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen com.android.internal.R.string.js_dialog_before_unload, mMessage); 10298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen positiveTextId = com.android.internal.R.string.js_dialog_before_unload_positive_button; 10398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen negativeTextId = com.android.internal.R.string.js_dialog_before_unload_negative_button; 10498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } else { 10598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen title = getJsDialogTitle(context); 10698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen displayMessage = mMessage; 10798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen positiveTextId = com.android.internal.R.string.ok; 10898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen negativeTextId = com.android.internal.R.string.cancel; 10998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 11098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen AlertDialog.Builder builder = new AlertDialog.Builder(context); 11198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen builder.setTitle(title); 11298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen builder.setOnCancelListener(new CancelListener()); 11398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen if (mType != PROMPT) { 11498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen builder.setMessage(displayMessage); 11598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen builder.setPositiveButton(positiveTextId, new PositiveListener(null)); 11698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } else { 11798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen final View view = LayoutInflater.from(context).inflate( 11898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen com.android.internal.R.layout.js_prompt, null); 11998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen EditText edit = ((EditText) view.findViewById(com.android.internal.R.id.value)); 12098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen edit.setText(mDefaultValue); 12198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen builder.setPositiveButton(positiveTextId, new PositiveListener(edit)); 12298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen ((TextView) view.findViewById(com.android.internal.R.id.message)).setText(mMessage); 12398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen builder.setView(view); 12498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 12598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen if (mType != ALERT) { 12698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen builder.setNegativeButton(negativeTextId, new CancelListener()); 12798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 12898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen builder.show(); 12998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 13098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 13198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen private class CancelListener implements DialogInterface.OnCancelListener, 13298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen DialogInterface.OnClickListener { 13398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen @Override 13498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen public void onCancel(DialogInterface dialog) { 13598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mResult.cancel(); 13698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 13798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen @Override 13898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen public void onClick(DialogInterface dialog, int which) { 13998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mResult.cancel(); 14098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 14198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 14298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 14398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen private class PositiveListener implements DialogInterface.OnClickListener { 14498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen private final EditText mEdit; 14598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 14698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen public PositiveListener(EditText edit) { 14798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mEdit = edit; 14898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 14998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 15098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen @Override 15198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen public void onClick(DialogInterface dialog, int which) { 15298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen if (mEdit == null) { 15398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mResult.confirm(); 15498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } else { 15598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen mResult.confirm(mEdit.getText().toString()); 15698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 15798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 15898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 15998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 16098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen private String getJsDialogTitle(Context context) { 16198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen String title = mUrl; 16298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen if (URLUtil.isDataUrl(mUrl)) { 16398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen // For data: urls, we just display 'JavaScript' similar to Chrome. 16498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen title = context.getString(com.android.internal.R.string.js_dialog_title_default); 16598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } else { 16698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen try { 16798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen URL alertUrl = new URL(mUrl); 16898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen // For example: "The page at 'http://www.mit.edu' says:" 16998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen title = context.getString(com.android.internal.R.string.js_dialog_title, 17098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen alertUrl.getProtocol() + "://" + alertUrl.getHost()); 17198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } catch (MalformedURLException ex) { 17298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen // do nothing. just use the url as the title 17398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 17498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 17598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen return title; 17698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 17798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen 17898dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen private static boolean canShowAlertDialog(Context context) { 17998dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen // We can only display the alert dialog if mContext is 18098dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen // an Activity context. 18198dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen // FIXME: Should we display dialogs if mContext does 18298dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen // not have the window focus (e.g. if the user is viewing 18398dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen // another Activity when the alert should be displayed) ? 18498dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen // See bug 3166409 18598dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen return context instanceof Activity; 18698dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen } 18798dedf7ccc9841c19d2213d25e09e962014a02ecKristian Monsen} 188