18233facddcc51865d612a919d450db6954aa48e3Michael Kolb/*
28233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Copyright (C) 2010 The Android Open Source Project
38233facddcc51865d612a919d450db6954aa48e3Michael Kolb *
48233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Licensed under the Apache License, Version 2.0 (the "License");
58233facddcc51865d612a919d450db6954aa48e3Michael Kolb * you may not use this file except in compliance with the License.
68233facddcc51865d612a919d450db6954aa48e3Michael Kolb * You may obtain a copy of the License at
78233facddcc51865d612a919d450db6954aa48e3Michael Kolb *
88233facddcc51865d612a919d450db6954aa48e3Michael Kolb *      http://www.apache.org/licenses/LICENSE-2.0
98233facddcc51865d612a919d450db6954aa48e3Michael Kolb *
108233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Unless required by applicable law or agreed to in writing, software
118233facddcc51865d612a919d450db6954aa48e3Michael Kolb * distributed under the License is distributed on an "AS IS" BASIS,
128233facddcc51865d612a919d450db6954aa48e3Michael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138233facddcc51865d612a919d450db6954aa48e3Michael Kolb * See the License for the specific language governing permissions and
148233facddcc51865d612a919d450db6954aa48e3Michael Kolb * limitations under the License.
158233facddcc51865d612a919d450db6954aa48e3Michael Kolb */
168233facddcc51865d612a919d450db6954aa48e3Michael Kolb
178233facddcc51865d612a919d450db6954aa48e3Michael Kolbpackage com.android.browser;
188233facddcc51865d612a919d450db6954aa48e3Michael Kolb
198233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.app.AlertDialog;
208233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.Context;
218233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.DialogInterface;
228233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.res.Configuration;
238233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.net.http.SslCertificate;
248233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.net.http.SslError;
258233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.view.LayoutInflater;
268233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.view.View;
278233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.HttpAuthHandler;
288233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.SslErrorHandler;
298233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.WebView;
308233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.widget.LinearLayout;
318233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.widget.TextView;
328233facddcc51865d612a919d450db6954aa48e3Michael Kolb
338233facddcc51865d612a919d450db6954aa48e3Michael Kolb/**
348233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Displays page info
358233facddcc51865d612a919d450db6954aa48e3Michael Kolb *
368233facddcc51865d612a919d450db6954aa48e3Michael Kolb */
378233facddcc51865d612a919d450db6954aa48e3Michael Kolbpublic class PageDialogsHandler {
388233facddcc51865d612a919d450db6954aa48e3Michael Kolb
398233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private Context mContext;
408233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private Controller mController;
418233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private boolean mPageInfoFromShowSSLCertificateOnError;
42ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu    private String mUrlCertificateOnError;
438233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private Tab mPageInfoView;
448233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private AlertDialog mPageInfoDialog;
458233facddcc51865d612a919d450db6954aa48e3Michael Kolb
468233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // as SSLCertificateOnError has different style for landscape / portrait,
478233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // we have to re-open it when configuration changed
488233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private AlertDialog mSSLCertificateOnErrorDialog;
498233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private WebView mSSLCertificateOnErrorView;
508233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private SslErrorHandler mSSLCertificateOnErrorHandler;
518233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private SslError mSSLCertificateOnErrorError;
528233facddcc51865d612a919d450db6954aa48e3Michael Kolb
538233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // as SSLCertificate has different style for landscape / portrait, we
548233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // have to re-open it when configuration changed
558233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private AlertDialog mSSLCertificateDialog;
568233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private Tab mSSLCertificateView;
578233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private HttpAuthenticationDialog mHttpAuthenticationDialog;
588233facddcc51865d612a919d450db6954aa48e3Michael Kolb
598233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public PageDialogsHandler(Context context, Controller controller) {
608233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mContext = context;
618233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mController = controller;
628233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
638233facddcc51865d612a919d450db6954aa48e3Michael Kolb
648233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void onConfigurationChanged(Configuration config) {
658233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mPageInfoDialog != null) {
668233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mPageInfoDialog.dismiss();
67ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu            showPageInfo(mPageInfoView,
68ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu                         mPageInfoFromShowSSLCertificateOnError,
69ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu                         mUrlCertificateOnError);
708233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
718233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mSSLCertificateDialog != null) {
728233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mSSLCertificateDialog.dismiss();
738233facddcc51865d612a919d450db6954aa48e3Michael Kolb            showSSLCertificate(mSSLCertificateView);
748233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
758233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mSSLCertificateOnErrorDialog != null) {
768233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mSSLCertificateOnErrorDialog.dismiss();
77ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu            showSSLCertificateOnError(mSSLCertificateOnErrorView,
78ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu                                      mSSLCertificateOnErrorHandler,
79ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu                                      mSSLCertificateOnErrorError);
808233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
818233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mHttpAuthenticationDialog != null) {
828233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mHttpAuthenticationDialog.reshow();
838233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
848233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
858233facddcc51865d612a919d450db6954aa48e3Michael Kolb
868233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
878233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Displays an http-authentication dialog.
888233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
898233facddcc51865d612a919d450db6954aa48e3Michael Kolb    void showHttpAuthentication(final Tab tab, final HttpAuthHandler handler, String host, String realm) {
908233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mHttpAuthenticationDialog = new HttpAuthenticationDialog(mContext, host, realm);
918233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mHttpAuthenticationDialog.setOkListener(new HttpAuthenticationDialog.OkListener() {
928233facddcc51865d612a919d450db6954aa48e3Michael Kolb            public void onOk(String host, String realm, String username, String password) {
938233facddcc51865d612a919d450db6954aa48e3Michael Kolb                setHttpAuthUsernamePassword(host, realm, username, password);
948233facddcc51865d612a919d450db6954aa48e3Michael Kolb                handler.proceed(username, password);
958233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mHttpAuthenticationDialog = null;
968233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
978233facddcc51865d612a919d450db6954aa48e3Michael Kolb        });
988233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mHttpAuthenticationDialog.setCancelListener(new HttpAuthenticationDialog.CancelListener() {
998233facddcc51865d612a919d450db6954aa48e3Michael Kolb            public void onCancel() {
1008233facddcc51865d612a919d450db6954aa48e3Michael Kolb                handler.cancel();
1012466effd6ef97aa17396c214d51f9f19a4760260Steve Block                mController.onUpdatedSecurityState(tab);
1028233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mHttpAuthenticationDialog = null;
1038233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
1048233facddcc51865d612a919d450db6954aa48e3Michael Kolb        });
1058233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mHttpAuthenticationDialog.show();
1068233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
1078233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1088233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
1098233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Set HTTP authentication password.
1108233facddcc51865d612a919d450db6954aa48e3Michael Kolb     *
1118233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param host The host for the password
1128233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param realm The realm for the password
1138233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param username The username for the password. If it is null, it means
1148233facddcc51865d612a919d450db6954aa48e3Michael Kolb     *            password can't be saved.
1158233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param password The password
1168233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
1178233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public void setHttpAuthUsernamePassword(String host, String realm,
1188233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                            String username,
1198233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                            String password) {
1208233facddcc51865d612a919d450db6954aa48e3Michael Kolb        WebView w = mController.getCurrentTopWebView();
1218233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (w != null) {
1228233facddcc51865d612a919d450db6954aa48e3Michael Kolb            w.setHttpAuthUsernamePassword(host, realm, username, password);
1238233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
1248233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
1258233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1268233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
1278233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Displays a page-info dialog.
1288233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param tab The tab to show info about
1298233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param fromShowSSLCertificateOnError The flag that indicates whether
1308233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * this dialog was opened from the SSL-certificate-on-error dialog or
1318233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * not. This is important, since we need to know whether to return to
1328233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * the parent dialog or simply dismiss.
133ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu     * @param urlCertificateOnError The URL that invokes SSLCertificateError.
134ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu     * Null when fromShowSSLCertificateOnError is false.
1358233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
1368233facddcc51865d612a919d450db6954aa48e3Michael Kolb    void showPageInfo(final Tab tab,
137ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu            final boolean fromShowSSLCertificateOnError,
138ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu            final String urlCertificateOnError) {
139d5cb4fa9f12b690dffdac98f17f0679b81571f07Michael Kolb        if (tab == null) return;
1408233facddcc51865d612a919d450db6954aa48e3Michael Kolb        final LayoutInflater factory = LayoutInflater.from(mContext);
1418233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1428233facddcc51865d612a919d450db6954aa48e3Michael Kolb        final View pageInfoView = factory.inflate(R.layout.page_info, null);
1438233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1448233facddcc51865d612a919d450db6954aa48e3Michael Kolb        final WebView view = tab.getWebView();
1458233facddcc51865d612a919d450db6954aa48e3Michael Kolb
146ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu        String url = fromShowSSLCertificateOnError ? urlCertificateOnError : tab.getUrl();
14730c714c853a4239e72ab1e238ce2a92472d06ab0John Reck        String title = tab.getTitle();
1488233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1498233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (url == null) {
1508233facddcc51865d612a919d450db6954aa48e3Michael Kolb            url = "";
1518233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
1528233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (title == null) {
1538233facddcc51865d612a919d450db6954aa48e3Michael Kolb            title = "";
1548233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
1558233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1568233facddcc51865d612a919d450db6954aa48e3Michael Kolb        ((TextView) pageInfoView.findViewById(R.id.address)).setText(url);
1578233facddcc51865d612a919d450db6954aa48e3Michael Kolb        ((TextView) pageInfoView.findViewById(R.id.title)).setText(title);
1588233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1598233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mPageInfoView = tab;
1608233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mPageInfoFromShowSSLCertificateOnError = fromShowSSLCertificateOnError;
161ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu        mUrlCertificateOnError = urlCertificateOnError;
1628233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1638233facddcc51865d612a919d450db6954aa48e3Michael Kolb        AlertDialog.Builder alertDialogBuilder =
1648233facddcc51865d612a919d450db6954aa48e3Michael Kolb            new AlertDialog.Builder(mContext)
1658233facddcc51865d612a919d450db6954aa48e3Michael Kolb            .setTitle(R.string.page_info)
1668233facddcc51865d612a919d450db6954aa48e3Michael Kolb            .setIcon(android.R.drawable.ic_dialog_info)
1678233facddcc51865d612a919d450db6954aa48e3Michael Kolb            .setView(pageInfoView)
1688233facddcc51865d612a919d450db6954aa48e3Michael Kolb            .setPositiveButton(
1698233facddcc51865d612a919d450db6954aa48e3Michael Kolb                R.string.ok,
1708233facddcc51865d612a919d450db6954aa48e3Michael Kolb                new DialogInterface.OnClickListener() {
1718233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    public void onClick(DialogInterface dialog,
1728233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                        int whichButton) {
1738233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        mPageInfoDialog = null;
1748233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        mPageInfoView = null;
1758233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1768233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        // if we came here from the SSL error dialog
1778233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        if (fromShowSSLCertificateOnError) {
1788233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            // go back to the SSL error dialog
1798233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            showSSLCertificateOnError(
1808233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorView,
1818233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorHandler,
1828233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorError);
1838233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        }
1848233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    }
1858233facddcc51865d612a919d450db6954aa48e3Michael Kolb                })
1868233facddcc51865d612a919d450db6954aa48e3Michael Kolb            .setOnCancelListener(
1878233facddcc51865d612a919d450db6954aa48e3Michael Kolb                new DialogInterface.OnCancelListener() {
1888233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    public void onCancel(DialogInterface dialog) {
1898233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        mPageInfoDialog = null;
1908233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        mPageInfoView = null;
1918233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1928233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        // if we came here from the SSL error dialog
1938233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        if (fromShowSSLCertificateOnError) {
1948233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            // go back to the SSL error dialog
1958233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            showSSLCertificateOnError(
1968233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorView,
1978233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorHandler,
1988233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorError);
1998233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        }
2008233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    }
2018233facddcc51865d612a919d450db6954aa48e3Michael Kolb                });
2028233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2038233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // if we have a main top-level page SSL certificate set or a certificate
2048233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // error
2058233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (fromShowSSLCertificateOnError ||
2068233facddcc51865d612a919d450db6954aa48e3Michael Kolb                (view != null && view.getCertificate() != null)) {
2078233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // add a 'View Certificate' button
2088233facddcc51865d612a919d450db6954aa48e3Michael Kolb            alertDialogBuilder.setNeutralButton(
2098233facddcc51865d612a919d450db6954aa48e3Michael Kolb                R.string.view_certificate,
2108233facddcc51865d612a919d450db6954aa48e3Michael Kolb                new DialogInterface.OnClickListener() {
2118233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    public void onClick(DialogInterface dialog,
2128233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                        int whichButton) {
2138233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        mPageInfoDialog = null;
2148233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        mPageInfoView = null;
2158233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2168233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        // if we came here from the SSL error dialog
2178233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        if (fromShowSSLCertificateOnError) {
2188233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            // go back to the SSL error dialog
2198233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            showSSLCertificateOnError(
2208233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorView,
2218233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorHandler,
2228233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorError);
2238233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        } else {
2248233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            // otherwise, display the top-most certificate from
2258233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            // the chain
226cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block                            showSSLCertificate(tab);
2278233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        }
2288233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    }
2298233facddcc51865d612a919d450db6954aa48e3Michael Kolb                });
2308233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
2318233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2328233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mPageInfoDialog = alertDialogBuilder.show();
2338233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
2348233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2358233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
2368233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Displays the main top-level page SSL certificate dialog
2378233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * (accessible from the Page-Info dialog).
2388233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param tab The tab to show certificate for.
2398233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
2408233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private void showSSLCertificate(final Tab tab) {
241873034cdbf67b7f0b555d7e15490d7466d49dd60Brian Carlstrom
242873034cdbf67b7f0b555d7e15490d7466d49dd60Brian Carlstrom        SslCertificate cert = tab.getWebView().getCertificate();
243873034cdbf67b7f0b555d7e15490d7466d49dd60Brian Carlstrom        if (cert == null) {
2448233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
2458233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
2468233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2478233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mSSLCertificateView = tab;
24808a6f0ce422a7cc35a9a27a0823b1ad604d70f48Steve Block        mSSLCertificateDialog = createSslCertificateDialog(cert, tab.getSslCertificateError())
2498233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .setPositiveButton(R.string.ok,
2508233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        new DialogInterface.OnClickListener() {
2518233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            public void onClick(DialogInterface dialog,
2528233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                    int whichButton) {
2538233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateDialog = null;
2548233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateView = null;
2558233facddcc51865d612a919d450db6954aa48e3Michael Kolb
256ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu                                showPageInfo(tab, false, null);
2578233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            }
2588233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        })
2598233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .setOnCancelListener(
2608233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        new DialogInterface.OnCancelListener() {
2618233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            public void onCancel(DialogInterface dialog) {
2628233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateDialog = null;
2638233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateView = null;
2648233facddcc51865d612a919d450db6954aa48e3Michael Kolb
265ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu                                showPageInfo(tab, false, null);
2668233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            }
2678233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        })
2688233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .show();
2698233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
2708233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2718233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
2728233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Displays the SSL error certificate dialog.
2738233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param view The target web-view.
2748233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param handler The SSL error handler responsible for cancelling the
2758233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * connection that resulted in an SSL error or proceeding per user request.
2768233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param error The SSL error object.
2778233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
2788233facddcc51865d612a919d450db6954aa48e3Michael Kolb    void showSSLCertificateOnError(
2798233facddcc51865d612a919d450db6954aa48e3Michael Kolb            final WebView view, final SslErrorHandler handler,
2808233facddcc51865d612a919d450db6954aa48e3Michael Kolb            final SslError error) {
2818233facddcc51865d612a919d450db6954aa48e3Michael Kolb
282873034cdbf67b7f0b555d7e15490d7466d49dd60Brian Carlstrom        SslCertificate cert = error.getCertificate();
283873034cdbf67b7f0b555d7e15490d7466d49dd60Brian Carlstrom        if (cert == null) {
2848233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
2858233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
2868233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2878233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mSSLCertificateOnErrorHandler = handler;
2888233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mSSLCertificateOnErrorView = view;
2898233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mSSLCertificateOnErrorError = error;
290cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block        mSSLCertificateOnErrorDialog = createSslCertificateDialog(cert, error)
2918233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .setPositiveButton(R.string.ok,
2928233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        new DialogInterface.OnClickListener() {
2938233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            public void onClick(DialogInterface dialog,
2948233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                    int whichButton) {
2958233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorDialog = null;
2968233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorView = null;
2978233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorHandler = null;
2988233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorError = null;
2998233facddcc51865d612a919d450db6954aa48e3Michael Kolb
300e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon                                ((BrowserWebView) view).getWebViewClient().
3014d2fcaba7fb8eb1723943ac9a10e76d509330bd1Jonathan Dixon                                        onReceivedSslError(view, handler, error);
3028233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            }
3038233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        })
3048233facddcc51865d612a919d450db6954aa48e3Michael Kolb                 .setNeutralButton(R.string.page_info_view,
3058233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        new DialogInterface.OnClickListener() {
3068233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            public void onClick(DialogInterface dialog,
3078233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                    int whichButton) {
3088233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorDialog = null;
3098233facddcc51865d612a919d450db6954aa48e3Michael Kolb
3108233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                // do not clear the dialog state: we will
3118233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                // need to show the dialog again once the
3128233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                // user is done exploring the page-info details
3138233facddcc51865d612a919d450db6954aa48e3Michael Kolb
3148233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                showPageInfo(mController.getTabControl()
3158233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                        .getTabFromView(view),
316ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu                                        true,
317ae0c0411bb502976c6374e30c5d1aa4271a64dafHuahui Wu                                        error.getUrl());
3188233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            }
3198233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        })
3208233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .setOnCancelListener(
3218233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        new DialogInterface.OnCancelListener() {
3228233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            public void onCancel(DialogInterface dialog) {
3238233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorDialog = null;
3248233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorView = null;
3258233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorHandler = null;
3268233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                mSSLCertificateOnErrorError = null;
3278233facddcc51865d612a919d450db6954aa48e3Michael Kolb
328e1d6dfca80e4627a0c7fe46e38f904179c3edab3Jonathan Dixon                                ((BrowserWebView) view).getWebViewClient().
3294d2fcaba7fb8eb1723943ac9a10e76d509330bd1Jonathan Dixon                                        onReceivedSslError(view, handler, error);
3308233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            }
3318233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        })
3328233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .show();
3338233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
334cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block
335cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block    /*
336cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block     * Creates an AlertDialog to display the given certificate. If error is
337cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block     * null, text is added to state that the certificae is valid and the icon
338cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block     * is set accordingly. If error is non-null, it must relate to the supplied
339cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block     * certificate. In this case, error is used to add text describing the
340cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block     * problems with the certificate and a different icon is used.
341cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block     */
342cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block    private AlertDialog.Builder createSslCertificateDialog(SslCertificate certificate,
343cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            SslError error) {
344cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block        View certificateView = certificate.inflateCertificateView(mContext);
345cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block        final LinearLayout placeholder =
346cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block                (LinearLayout)certificateView.findViewById(com.android.internal.R.id.placeholder);
347cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block
348cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block        LayoutInflater factory = LayoutInflater.from(mContext);
349cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block        int iconId;
350cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block
351cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block        if (error == null) {
352cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            iconId = R.drawable.ic_dialog_browser_certificate_secure;
353cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            LinearLayout table = (LinearLayout)factory.inflate(R.layout.ssl_success, placeholder);
354cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            TextView successString = (TextView)table.findViewById(R.id.success);
355cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            successString.setText(com.android.internal.R.string.ssl_certificate_is_valid);
356cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block        } else {
357cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            iconId = R.drawable.ic_dialog_browser_certificate_partially_secure;
358cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            if (error.hasError(SslError.SSL_UNTRUSTED)) {
359cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block                addError(factory, placeholder, R.string.ssl_untrusted);
360cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            }
361cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            if (error.hasError(SslError.SSL_IDMISMATCH)) {
362cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block                addError(factory, placeholder, R.string.ssl_mismatch);
363cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            }
364cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            if (error.hasError(SslError.SSL_EXPIRED)) {
365cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block                addError(factory, placeholder, R.string.ssl_expired);
366cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            }
367cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            if (error.hasError(SslError.SSL_NOTYETVALID)) {
368cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block                addError(factory, placeholder, R.string.ssl_not_yet_valid);
369cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            }
370cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            if (error.hasError(SslError.SSL_DATE_INVALID)) {
371cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block                addError(factory, placeholder, R.string.ssl_date_invalid);
372cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            }
373cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            if (error.hasError(SslError.SSL_INVALID)) {
374cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block                addError(factory, placeholder, R.string.ssl_invalid);
375cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            }
376cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            // The SslError should always have at least one type of error and we
377cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            // should explicitly handle every type of error it supports. We
378cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            // therefore expect the condition below to never be hit. We use it
379cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            // as as safety net in case a new error type is added to SslError
380cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            // without the logic above being updated accordingly.
381cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            if (placeholder.getChildCount() == 0) {
382cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block                addError(factory, placeholder, R.string.ssl_unknown);
383cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block            }
384cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block        }
385cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block
386cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block        return new AlertDialog.Builder(mContext)
387cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block                .setTitle(com.android.internal.R.string.ssl_certificate)
388cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block                .setIcon(iconId)
389cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block                .setView(certificateView);
390cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block    }
391cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block
392cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block    private void addError(LayoutInflater inflater, LinearLayout parent, int error) {
393cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block        TextView textView = (TextView) inflater.inflate(R.layout.ssl_warning,
394cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block                parent, false);
395cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block        textView.setText(error);
396cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block        parent.addView(textView);
397cbc67a01ccfe9cc5ce441f02a8c0dc475340830eSteve Block    }
3988233facddcc51865d612a919d450db6954aa48e3Michael Kolb}
399