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