1 /* ownCloud Android client application
2 * Copyright (C) 2012-2014 ownCloud Inc.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2,
6 * as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 package com
.owncloud
.android
.ui
.dialog
;
19 import java
.io
.IOException
;
20 import java
.security
.GeneralSecurityException
;
21 import java
.security
.cert
.X509Certificate
;
23 import android
.app
.Activity
;
24 import android
.app
.Dialog
;
25 import android
.net
.http
.SslError
;
26 import android
.os
.Bundle
;
27 import android
.view
.LayoutInflater
;
28 import android
.view
.View
;
29 import android
.view
.ViewGroup
;
30 import android
.view
.Window
;
31 import android
.view
.View
.OnClickListener
;
32 import android
.webkit
.SslErrorHandler
;
33 import android
.widget
.Button
;
35 import com
.actionbarsherlock
.app
.SherlockDialogFragment
;
36 import com
.owncloud
.android
.R
;
37 import com
.owncloud
.android
.lib
.common
.network
.CertificateCombinedException
;
38 import com
.owncloud
.android
.lib
.common
.network
.NetworkUtils
;
39 import com
.owncloud
.android
.ui
.adapter
.CertificateCombinedExceptionViewAdapter
;
40 import com
.owncloud
.android
.ui
.adapter
.SslCertificateViewAdapter
;
41 import com
.owncloud
.android
.ui
.adapter
.SslErrorViewAdapter
;
42 import com
.owncloud
.android
.ui
.adapter
.X509CertificateViewAdapter
;
43 import com
.owncloud
.android
.utils
.Log_OC
;
46 * Dialog to show information about an untrusted certificate and allow the user
47 * to decide trust on it or not.
49 * Abstract implementation of common functionality for different dialogs that
50 * get the information about the error and the certificate from different classes.
53 * @author David A. Velasco
55 public class SslUntrustedCertDialog
extends SherlockDialogFragment
{
57 private final static String TAG
= SslUntrustedCertDialog
.class.getSimpleName();
59 protected View mView
= null
;
60 protected SslErrorHandler mHandler
= null
;
61 protected X509Certificate m509Certificate
= null
;
63 private ErrorViewAdapter mErrorViewAdapter
= null
;
64 private CertificateViewAdapter mCertificateViewAdapter
= null
;
66 public static SslUntrustedCertDialog
newInstanceForEmptySslError(SslError error
, SslErrorHandler handler
) {
68 throw new IllegalArgumentException("Trying to create instance with parameter error == null");
70 if (handler
== null
) {
71 throw new IllegalArgumentException("Trying to create instance with parameter handler == null");
73 SslUntrustedCertDialog dialog
= new SslUntrustedCertDialog();
74 dialog
.mHandler
= handler
;
75 dialog
.mErrorViewAdapter
= new SslErrorViewAdapter(error
);
76 dialog
.mCertificateViewAdapter
= new SslCertificateViewAdapter(error
.getCertificate());
80 public static SslUntrustedCertDialog
newInstanceForFullSslError(CertificateCombinedException sslException
) {
81 if (sslException
== null
) {
82 throw new IllegalArgumentException("Trying to create instance with parameter sslException == null");
84 SslUntrustedCertDialog dialog
= new SslUntrustedCertDialog();
85 dialog
.m509Certificate
= sslException
.getServerCertificate();
86 dialog
.mErrorViewAdapter
= new CertificateCombinedExceptionViewAdapter(sslException
);
87 dialog
.mCertificateViewAdapter
= new X509CertificateViewAdapter(sslException
.getServerCertificate());
91 public static SslUntrustedCertDialog
newInstanceForFullSslError(X509Certificate cert
, SslError error
, SslErrorHandler handler
) {
93 throw new IllegalArgumentException("Trying to create instance with parameter cert == null");
96 throw new IllegalArgumentException("Trying to create instance with parameter error == null");
98 if (handler
== null
) {
99 throw new IllegalArgumentException("Trying to create instance with parameter handler == null");
101 SslUntrustedCertDialog dialog
= new SslUntrustedCertDialog();
102 dialog
.m509Certificate
= cert
;
103 dialog
.mHandler
= handler
;
104 dialog
.mErrorViewAdapter
= new SslErrorViewAdapter(error
);
105 dialog
.mCertificateViewAdapter
= new X509CertificateViewAdapter(cert
);
111 public void onAttach(Activity activity
) {
112 super.onAttach(activity
);
113 if (!(activity
instanceof OnSslUntrustedCertListener
)) {
114 throw new IllegalArgumentException("The host activity must implement " + OnSslUntrustedCertListener
.class.getCanonicalName());
120 public void onCreate(Bundle savedInstanceState
) {
121 super.onCreate(savedInstanceState
);
122 setRetainInstance(true
); // force to keep the state of the fragment on configuration changes (such as device rotations)
123 setCancelable(false
);
128 public View
onCreateView(LayoutInflater inflater
, ViewGroup container
, Bundle savedInstanceState
) {
129 // Create a view by inflating desired layout
131 mView
= inflater
.inflate(R
.layout
.ssl_untrusted_cert_layout
, container
, false
);
132 mView
.findViewById(R
.id
.details_scroll
).setVisibility(View
.GONE
);
133 mErrorViewAdapter
.updateErrorView(mView
);
135 ((ViewGroup
)mView
.getParent()).removeView(mView
);
138 Button ok
= (Button
) mView
.findViewById(R
.id
.ok
);
139 ok
.setOnClickListener(new OnCertificateTrusted());
141 Button cancel
= (Button
) mView
.findViewById(R
.id
.cancel
);
142 cancel
.setOnClickListener(new OnCertificateNotTrusted());
144 Button details
= (Button
) mView
.findViewById(R
.id
.details_btn
);
145 details
.setOnClickListener(new OnClickListener() {
148 public void onClick(View v
) {
149 View detailsScroll
= mView
.findViewById(R
.id
.details_scroll
);
150 if (detailsScroll
.getVisibility() == View
.VISIBLE
) {
151 detailsScroll
.setVisibility(View
.GONE
);
152 ((Button
) v
).setText(R
.string
.ssl_validator_btn_details_see
);
155 detailsScroll
.setVisibility(View
.VISIBLE
);
156 ((Button
) v
).setText(R
.string
.ssl_validator_btn_details_hide
);
157 mCertificateViewAdapter
.updateCertificateView(mView
);
168 public Dialog
onCreateDialog(Bundle savedInstanceState
) {
169 final Dialog dialog
= super.onCreateDialog(savedInstanceState
);
170 dialog
.requestWindowFeature(Window
.FEATURE_NO_TITLE
);
175 public void onDestroyView() {
176 if (getDialog() != null
&& getRetainInstance())
177 getDialog().setDismissMessage(null
);
178 super.onDestroyView();
181 private class OnCertificateNotTrusted
implements OnClickListener
{
184 public void onClick(View v
) {
185 getDialog().cancel();
186 if (mHandler
!= null
) {
189 ((OnSslUntrustedCertListener
)getSherlockActivity()).onCancelCertificate();
194 private class OnCertificateTrusted
implements OnClickListener
{
197 public void onClick(View v
) {
199 if (mHandler
!= null
) {
202 if (m509Certificate
!= null
) {
203 Activity activity
= getSherlockActivity();
205 NetworkUtils
.addCertToKnownServersStore(m509Certificate
, activity
); // TODO make this asynchronously, it can take some time
206 ((OnSslUntrustedCertListener
)activity
).onSavedCertificate();
208 } catch (GeneralSecurityException e
) {
209 ((OnSslUntrustedCertListener
)activity
).onFailedSavingCertificate();
210 Log_OC
.e(TAG
, "Server certificate could not be saved in the known-servers trust store ", e
);
212 } catch (IOException e
) {
213 ((OnSslUntrustedCertListener
)activity
).onFailedSavingCertificate();
214 Log_OC
.e(TAG
, "Server certificate could not be saved in the known-servers trust store ", e
);
222 public interface OnSslUntrustedCertListener
{
223 public void onSavedCertificate();
224 public void onFailedSavingCertificate();
225 public void onCancelCertificate();
228 public interface ErrorViewAdapter
{
229 void updateErrorView(View mView
);
232 public interface CertificateViewAdapter
{
233 void updateCertificateView(View mView
);