]> git.ipfire.org Git - thirdparty/strongswan.git/blob
1ceba87f7fa4b07801d731a9fe6f1260a3d28aa9
[thirdparty/strongswan.git] /
1 /*
2 * Copyright (C) 2012-2015 Tobias Brunner
3 *
4 * Copyright (C) secunet Security Networks AG
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 package org.strongswan.android.ui;
18
19 import android.content.Context;
20 import android.os.Bundle;
21 import android.text.TextUtils;
22 import android.view.Menu;
23 import android.view.MenuInflater;
24 import android.view.MenuItem;
25 import android.view.View;
26 import android.widget.ListView;
27 import android.widget.SearchView;
28 import android.widget.SearchView.OnQueryTextListener;
29
30 import org.strongswan.android.R;
31 import org.strongswan.android.logic.TrustedCertificateManager;
32 import org.strongswan.android.logic.TrustedCertificateManager.TrustedCertificateSource;
33 import org.strongswan.android.security.TrustedCertificateEntry;
34 import org.strongswan.android.ui.adapter.TrustedCertificateAdapter;
35
36 import java.beans.PropertyChangeEvent;
37 import java.beans.PropertyChangeListener;
38 import java.security.cert.X509Certificate;
39 import java.util.ArrayList;
40 import java.util.Collections;
41 import java.util.Hashtable;
42 import java.util.List;
43 import java.util.Map.Entry;
44
45 import androidx.annotation.NonNull;
46 import androidx.annotation.Nullable;
47 import androidx.fragment.app.ListFragment;
48 import androidx.loader.app.LoaderManager;
49 import androidx.loader.app.LoaderManager.LoaderCallbacks;
50 import androidx.loader.content.AsyncTaskLoader;
51 import androidx.loader.content.Loader;
52
53 public class TrustedCertificateListFragment extends ListFragment implements LoaderCallbacks<List<TrustedCertificateEntry>>, OnQueryTextListener
54 {
55 public static final String EXTRA_CERTIFICATE_SOURCE = "certificate_source";
56 private OnTrustedCertificateSelectedListener mListener;
57 private TrustedCertificateAdapter mAdapter;
58 private TrustedCertificateSource mSource = TrustedCertificateSource.SYSTEM;
59
60 /**
61 * The activity containing this fragment should implement this interface
62 */
63 public interface OnTrustedCertificateSelectedListener
64 {
65 public void onTrustedCertificateSelected(TrustedCertificateEntry selected);
66 }
67
68 @Override
69 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
70 {
71 super.onViewCreated(view, savedInstanceState);
72 setHasOptionsMenu(true);
73
74 setEmptyText(getString(R.string.no_certificates));
75
76 mAdapter = new TrustedCertificateAdapter(getActivity());
77 setListAdapter(mAdapter);
78
79 setListShown(false);
80
81 Bundle arguments = getArguments();
82 if (arguments != null)
83 {
84 mSource = (TrustedCertificateSource)arguments.getSerializable(EXTRA_CERTIFICATE_SOURCE);
85 }
86
87 LoaderManager.getInstance(this).initLoader(0, null, this);
88 }
89
90 @Override
91 public void onDestroy()
92 {
93 super.onDestroy();
94 }
95
96 @Override
97 public void onAttach(Context context)
98 {
99 super.onAttach(context);
100
101 if (context instanceof OnTrustedCertificateSelectedListener)
102 {
103 mListener = (OnTrustedCertificateSelectedListener)context;
104 }
105 }
106
107 @Override
108 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
109 {
110 MenuItem item = menu.add(R.string.search);
111 item.setIcon(android.R.drawable.ic_menu_search);
112 item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
113
114 SearchView sv = new SearchView(getActivity());
115 sv.setOnQueryTextListener(this);
116 item.setActionView(sv);
117 }
118
119 @Override
120 public boolean onQueryTextSubmit(String query)
121 { /* already handled when the text changes */
122 return true;
123 }
124
125 @Override
126 public boolean onQueryTextChange(String newText)
127 {
128 String search = TextUtils.isEmpty(newText) ? null : newText;
129 mAdapter.getFilter().filter(search);
130 return true;
131 }
132
133 @Override
134 public Loader<List<TrustedCertificateEntry>> onCreateLoader(int id, Bundle args)
135 { /* we don't need the id as we have only one loader */
136 return new CertificateListLoader(getActivity(), mSource);
137 }
138
139 @Override
140 public void onLoadFinished(Loader<List<TrustedCertificateEntry>> loader, List<TrustedCertificateEntry> data)
141 {
142 mAdapter.setData(data);
143
144 if (isResumed())
145 {
146 setListShown(true);
147 }
148 else
149 {
150 setListShownNoAnimation(true);
151 }
152 }
153
154 @Override
155 public void onLoaderReset(Loader<List<TrustedCertificateEntry>> loader)
156 {
157 mAdapter.setData(null);
158 }
159
160 @Override
161 public void onListItemClick(ListView l, View v, int position, long id)
162 {
163 if (mListener != null)
164 {
165 mListener.onTrustedCertificateSelected(mAdapter.getItem(position));
166 }
167 }
168
169 public static class CertificateListLoader extends AsyncTaskLoader<List<TrustedCertificateEntry>>
170 {
171 private List<TrustedCertificateEntry> mData;
172 private final TrustedCertificateSource mSource;
173 private TrustedCertificateManagerObserver mObserver;
174
175 public CertificateListLoader(Context context, TrustedCertificateSource source)
176 {
177 super(context);
178 mSource = source;
179 }
180
181 @Override
182 public List<TrustedCertificateEntry> loadInBackground()
183 {
184 TrustedCertificateManager certman = TrustedCertificateManager.getInstance().load();
185 Hashtable<String, X509Certificate> certificates = certman.getCACertificates(mSource);
186 List<TrustedCertificateEntry> selected;
187
188 selected = new ArrayList<TrustedCertificateEntry>();
189 for (Entry<String, X509Certificate> entry : certificates.entrySet())
190 {
191 selected.add(new TrustedCertificateEntry(entry.getKey(), entry.getValue()));
192 }
193 Collections.sort(selected);
194 return selected;
195 }
196
197 @Override
198 protected void onStartLoading()
199 {
200 if (mData != null)
201 { /* if we have data ready, deliver it directly */
202 deliverResult(mData);
203 }
204 if (takeContentChanged() || mData == null)
205 {
206 forceLoad();
207 }
208 }
209
210 @Override
211 public void deliverResult(List<TrustedCertificateEntry> data)
212 {
213 if (isReset())
214 {
215 return;
216 }
217 mData = data;
218 if (isStarted())
219 { /* if it is started we deliver the data directly,
220 * otherwise this is handled in onStartLoading */
221 if (mObserver == null)
222 {
223 mObserver = new TrustedCertificateManagerObserver();
224 TrustedCertificateManager.getInstance().addObserver(mObserver);
225 }
226 super.deliverResult(data);
227 }
228 }
229
230 @Override
231 protected void onReset()
232 {
233 if (mObserver != null)
234 {
235 TrustedCertificateManager.getInstance().deleteObserver(mObserver);
236 mObserver = null;
237 }
238 mData = null;
239 super.onReset();
240 }
241
242 @Override
243 protected void onAbandon()
244 {
245 if (mObserver != null)
246 {
247 TrustedCertificateManager.getInstance().deleteObserver(mObserver);
248 mObserver = null;
249 }
250 }
251
252 private class TrustedCertificateManagerObserver implements PropertyChangeListener
253 {
254 private ForceLoadContentObserver mContentObserver = new ForceLoadContentObserver();
255
256 @Override
257 public void propertyChange(PropertyChangeEvent evt)
258 {
259 mContentObserver.onChange(false);
260 }
261 }
262 }
263 }