2 * ownCloud Android client application
5 * @author David A. Velasco
6 * Copyright (C) 2015 ownCloud Inc.
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 package com
.owncloud
.android
.ui
.dialog
;
23 import java
.io
.IOException
;
24 import java
.security
.GeneralSecurityException
;
25 import java
.security
.cert
.X509Certificate
;
27 import android
.app
.Activity
;
28 import android
.app
.Dialog
;
29 import android
.net
.http
.SslError
;
30 import android
.os
.Bundle
;
31 import android
.support
.v4
.app
.DialogFragment
;
32 import android
.view
.LayoutInflater
;
33 import android
.view
.View
;
34 import android
.view
.ViewGroup
;
35 import android
.view
.Window
;
36 import android
.view
.View
.OnClickListener
;
37 import android
.webkit
.SslErrorHandler
;
38 import android
.widget
.Button
;
40 import com
.owncloud
.android
.R
;
41 import com
.owncloud
.android
.lib
.common
.network
.CertificateCombinedException
;
42 import com
.owncloud
.android
.lib
.common
.network
.NetworkUtils
;
43 import com
.owncloud
.android
.lib
.common
.utils
.Log_OC
;
44 import com
.owncloud
.android
.ui
.adapter
.CertificateCombinedExceptionViewAdapter
;
45 import com
.owncloud
.android
.ui
.adapter
.SslCertificateViewAdapter
;
46 import com
.owncloud
.android
.ui
.adapter
.SslErrorViewAdapter
;
47 import com
.owncloud
.android
.ui
.adapter
.X509CertificateViewAdapter
;
50 * Dialog to show information about an untrusted certificate and allow the user
51 * to decide trust on it or not.
53 * Abstract implementation of common functionality for different dialogs that
54 * get the information about the error and the certificate from different classes.
56 public class SslUntrustedCertDialog
extends DialogFragment
{
58 private final static String TAG
= SslUntrustedCertDialog
.class.getSimpleName();
60 protected View mView
= null
;
61 protected SslErrorHandler mHandler
= null
;
62 protected X509Certificate m509Certificate
= null
;
64 private ErrorViewAdapter mErrorViewAdapter
= null
;
65 private CertificateViewAdapter mCertificateViewAdapter
= null
;
67 public static SslUntrustedCertDialog
newInstanceForEmptySslError(SslError error
, SslErrorHandler handler
) {
69 throw new IllegalArgumentException("Trying to create instance with parameter error == null");
71 if (handler
== null
) {
72 throw new IllegalArgumentException("Trying to create instance with parameter handler == null");
74 SslUntrustedCertDialog dialog
= new SslUntrustedCertDialog();
75 dialog
.mHandler
= handler
;
76 dialog
.mErrorViewAdapter
= new SslErrorViewAdapter(error
);
77 dialog
.mCertificateViewAdapter
= new SslCertificateViewAdapter(error
.getCertificate());
81 public static SslUntrustedCertDialog
newInstanceForFullSslError(CertificateCombinedException sslException
) {
82 if (sslException
== null
) {
83 throw new IllegalArgumentException("Trying to create instance with parameter sslException == null");
85 SslUntrustedCertDialog dialog
= new SslUntrustedCertDialog();
86 dialog
.m509Certificate
= sslException
.getServerCertificate();
87 dialog
.mErrorViewAdapter
= new CertificateCombinedExceptionViewAdapter(sslException
);
88 dialog
.mCertificateViewAdapter
= new X509CertificateViewAdapter(sslException
.getServerCertificate());
92 public static SslUntrustedCertDialog
newInstanceForFullSslError(X509Certificate cert
, SslError error
, SslErrorHandler handler
) {
94 throw new IllegalArgumentException("Trying to create instance with parameter cert == null");
97 throw new IllegalArgumentException("Trying to create instance with parameter error == null");
99 if (handler
== null
) {
100 throw new IllegalArgumentException("Trying to create instance with parameter handler == null");
102 SslUntrustedCertDialog dialog
= new SslUntrustedCertDialog();
103 dialog
.m509Certificate
= cert
;
104 dialog
.mHandler
= handler
;
105 dialog
.mErrorViewAdapter
= new SslErrorViewAdapter(error
);
106 dialog
.mCertificateViewAdapter
= new X509CertificateViewAdapter(cert
);
112 public void onAttach(Activity activity
) {
113 Log_OC
.d(TAG
, "onAttach");
114 super.onAttach(activity
);
115 if (!(activity
instanceof OnSslUntrustedCertListener
)) {
116 throw new IllegalArgumentException("The host activity must implement " + OnSslUntrustedCertListener
.class.getCanonicalName());
122 public void onCreate(Bundle savedInstanceState
) {
123 Log_OC
.d(TAG
, "onCreate, savedInstanceState is " + savedInstanceState
);
124 super.onCreate(savedInstanceState
);
125 setRetainInstance(true
); // force to keep the state of the fragment on configuration changes (such as device rotations)
126 setCancelable(false
);
131 public View
onCreateView(LayoutInflater inflater
, ViewGroup container
, Bundle savedInstanceState
) {
132 Log_OC
.d(TAG
, "onCreateView, savedInsanceState is " + savedInstanceState
);
133 // Create a view by inflating desired layout
135 mView
= inflater
.inflate(R
.layout
.ssl_untrusted_cert_layout
, container
, false
);
136 mView
.findViewById(R
.id
.details_scroll
).setVisibility(View
.GONE
);
137 mErrorViewAdapter
.updateErrorView(mView
);
139 ((ViewGroup
)mView
.getParent()).removeView(mView
);
142 Button ok
= (Button
) mView
.findViewById(R
.id
.ok
);
143 ok
.setOnClickListener(new OnCertificateTrusted());
145 Button cancel
= (Button
) mView
.findViewById(R
.id
.cancel
);
146 cancel
.setOnClickListener(new OnCertificateNotTrusted());
148 Button details
= (Button
) mView
.findViewById(R
.id
.details_btn
);
149 details
.setOnClickListener(new OnClickListener() {
152 public void onClick(View v
) {
153 View detailsScroll
= mView
.findViewById(R
.id
.details_scroll
);
154 if (detailsScroll
.getVisibility() == View
.VISIBLE
) {
155 detailsScroll
.setVisibility(View
.GONE
);
156 ((Button
) v
).setText(R
.string
.ssl_validator_btn_details_see
);
159 detailsScroll
.setVisibility(View
.VISIBLE
);
160 ((Button
) v
).setText(R
.string
.ssl_validator_btn_details_hide
);
161 mCertificateViewAdapter
.updateCertificateView(mView
);
172 public Dialog
onCreateDialog(Bundle savedInstanceState
) {
173 Log_OC
.d(TAG
, "onCreateDialog, savedInstanceState is " + savedInstanceState
);
174 final Dialog dialog
= super.onCreateDialog(savedInstanceState
);
175 dialog
.requestWindowFeature(Window
.FEATURE_NO_TITLE
);
180 public void onDestroyView() {
181 Log_OC
.d(TAG
, "onDestroyView");
182 if (getDialog() != null
&& getRetainInstance())
183 getDialog().setDismissMessage(null
);
184 super.onDestroyView();
187 private class OnCertificateNotTrusted
implements OnClickListener
{
190 public void onClick(View v
) {
191 getDialog().cancel();
192 if (mHandler
!= null
) {
195 ((OnSslUntrustedCertListener
)getActivity()).onCancelCertificate();
200 private class OnCertificateTrusted
implements OnClickListener
{
203 public void onClick(View v
) {
205 if (mHandler
!= null
) {
208 if (m509Certificate
!= null
) {
209 Activity activity
= getActivity();
211 NetworkUtils
.addCertToKnownServersStore(m509Certificate
, activity
); // TODO make this asynchronously, it can take some time
212 ((OnSslUntrustedCertListener
)activity
).onSavedCertificate();
214 } catch (GeneralSecurityException e
) {
215 ((OnSslUntrustedCertListener
)activity
).onFailedSavingCertificate();
216 Log_OC
.e(TAG
, "Server certificate could not be saved in the known-servers trust store ", e
);
218 } catch (IOException e
) {
219 ((OnSslUntrustedCertListener
)activity
).onFailedSavingCertificate();
220 Log_OC
.e(TAG
, "Server certificate could not be saved in the known-servers trust store ", e
);
228 public interface OnSslUntrustedCertListener
{
229 public void onSavedCertificate();
230 public void onFailedSavingCertificate();
231 public void onCancelCertificate();
234 public interface ErrorViewAdapter
{
235 void updateErrorView(View mView
);
238 public interface CertificateViewAdapter
{
239 void updateCertificateView(View mView
);