diff options
| -rw-r--r-- | res/layout/provider_list_fragment.xml | 5 | ||||
| -rwxr-xr-x | res/values/strings.xml | 6 | ||||
| -rw-r--r-- | src/se/leap/leapclient/ConfigHelper.java | 1 | ||||
| -rw-r--r-- | src/se/leap/leapclient/ConfigurationWizard.java | 82 | ||||
| -rw-r--r-- | src/se/leap/leapclient/NewProviderDialog.java | 4 | ||||
| -rw-r--r-- | src/se/leap/leapclient/ProviderAPI.java | 30 | ||||
| -rw-r--r-- | src/se/leap/leapclient/ProviderListContent.java | 126 | ||||
| -rw-r--r-- | src/se/leap/leapclient/ProviderListFragment.java | 25 | 
8 files changed, 162 insertions, 117 deletions
diff --git a/res/layout/provider_list_fragment.xml b/res/layout/provider_list_fragment.xml index 9bb775d7..0db0734b 100644 --- a/res/layout/provider_list_fragment.xml +++ b/res/layout/provider_list_fragment.xml @@ -10,12 +10,13 @@          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:layout_weight="1"
 +	android:layout_alignParentTop="true"
          android:drawSelectorOnTop="false" />
      <Button
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
 -        android:onClick="addNewProvider"
 +        android:onClick="addAndSelectNewProvider"
          android:text="@string/new_provider_button" />
 -</LinearLayout>
\ No newline at end of file +</LinearLayout>
 diff --git a/res/values/strings.xml b/res/values/strings.xml index c0ba6ebd..80dd85bd 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -262,7 +262,7 @@      <string name="eip_service_label">EIP:</string>      <string name="eip_type_active">EIP</string>      <string name="title_activity_configuration_wizard">Configure LEAP</string> -    <string name="new_provider_button">Add new Provider</string> +    <string name="new_provider_button">Select new Provider</string>      <string name="introduce_new_provider">Introduce new provider</string>      <string name="save">Save</string>      <string name="new_provider_uri">New provider\'s main URL</string> @@ -287,7 +287,7 @@      <string name="incorrectly_downloaded_json_files_message">You have not entered a LEAP provider URL or it is unavailable</string>      <string name="correctly_downloaded_json_files_message">Your anon cert has been correctly downloaded</string>      <string name="incorrectly_downloaded_certificate_message">Your anon cert was not downloaded</string> -    <string name="incorrectly_updated_provider_dot_json_message">Install a new version of this app.</string> +    <string name="incorrectly_updated_provider_dot_json_message">Server is down.</string>      <string name="not_valid_password_message">Your password is not well-formed: it should have at least 8 characters.</string>      <string name="succesful_authentication_message">Authentication succeeded.</string>      <string name="authentication_failed_message">Authentication failed.</string> @@ -297,4 +297,4 @@      <string name="authed_cert_download_failed_message">Your own cert has incorrectly been downloaded.</string> -</resources>
\ No newline at end of file +</resources> diff --git a/src/se/leap/leapclient/ConfigHelper.java b/src/se/leap/leapclient/ConfigHelper.java index cab5fdee..9a3bd991 100644 --- a/src/se/leap/leapclient/ConfigHelper.java +++ b/src/se/leap/leapclient/ConfigHelper.java @@ -64,6 +64,7 @@ public class ConfigHelper {      PREFERENCES_KEY = "LEAPPreferences",      USER_DIRECTORY = "leap_android",      PROVIDER_NAME = "provider_name", +    PROVIDER_ID = "provider_id",      PROVIDER_MAIN_URL = "provider_main_url",      PROVIDER_JSON_URL = "provider_json_url",      CUSTOM = "custom", diff --git a/src/se/leap/leapclient/ConfigurationWizard.java b/src/se/leap/leapclient/ConfigurationWizard.java index ce279425..6bf94ca6 100644 --- a/src/se/leap/leapclient/ConfigurationWizard.java +++ b/src/se/leap/leapclient/ConfigurationWizard.java @@ -50,9 +50,9 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn          providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler());
          providerAPI_result_receiver.setReceiver(this);
 -         +        
          ConfigHelper.setSharedPreferences(getSharedPreferences(ConfigHelper.PREFERENCES_KEY, MODE_PRIVATE));
 -         +        
          loadPreseededProviders();
          // Only create our fragments if we're not restoring a saved instance
 @@ -72,15 +72,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn  	@Override
  	public void onReceiveResult(int resultCode, Bundle resultData) {
 -		if(resultCode == ConfigHelper.CUSTOM_PROVIDER_ADDED){
 -			ProviderListFragment providerList = new ProviderListFragment();
 -
 -			FragmentManager fragmentManager = getFragmentManager();
 -			fragmentManager.beginTransaction()
 -				.replace(R.id.configuration_wizard_layout, providerList, "providerlist")
 -				.commit();
 -		}
 -		else if(resultCode == ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON) {
 +		if(resultCode == ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON) {
  			JSONObject provider_json;
  			try {
  				provider_json = new JSONObject(resultData.getString(ConfigHelper.PROVIDER_KEY));
 @@ -88,10 +80,13 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn  				ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json);
  				ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, danger_on);
  				ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON));
 -	
  				mConfigState.setAction(PROVIDER_SET);
 +				if(mProgressDialog == null)
 +					mProgressDialog =  ProgressDialog.show(this, getResources().getString(R.string.config_wait_title), getResources().getString(R.string.config_connecting_provider), true);
  				mProgressDialog.setMessage(getResources().getString(R.string.config_downloading_services));
 +				if(mSelectedProvider == null)
 +					mSelectedProvider = getProvider(resultData.getString(ConfigHelper.PROVIDER_ID));
  				downloadJSONFiles(mSelectedProvider);
  			} catch (JSONException e) {
  				// TODO Auto-generated catch block
 @@ -100,14 +95,12 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn  				mProgressDialog.dismiss();
  				Toast.makeText(this, getResources().getString(R.string.config_error_parsing), Toast.LENGTH_LONG);
  				setResult(RESULT_CANCELED, mConfigState);
 -				finish();
  			}
  		}
  		else if(resultCode == ConfigHelper.INCORRECTLY_UPDATED_PROVIDER_DOT_JSON) {
  			mProgressDialog.dismiss();
  			Toast.makeText(getApplicationContext(), R.string.incorrectly_updated_provider_dot_json_message, Toast.LENGTH_LONG).show();
  			setResult(RESULT_CANCELED, mConfigState);
 -			finish();
  		}
  		else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_JSON_FILES) {
  			if (ConfigHelper.getBoolFromSharedPref(ConfigHelper.ALLOWED_ANON)){
 @@ -122,22 +115,20 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn  			}
  		}
  		else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES) {
 -        	Toast.makeText(getApplicationContext(), R.string.incorrectly_downloaded_json_files_message, Toast.LENGTH_LONG).show();
 -        	setResult(RESULT_CANCELED, mConfigState);
 -        	finish();
 +			Toast.makeText(getApplicationContext(), R.string.incorrectly_downloaded_json_files_message, Toast.LENGTH_LONG).show();
 +			setResult(RESULT_CANCELED, mConfigState);
  		}
  		else if(resultCode == ConfigHelper.CORRECTLY_DOWNLOADED_CERTIFICATE) {
  			mProgressDialog.dismiss();
  			Toast.makeText(getApplicationContext(), R.string.correctly_downloaded_json_files_message, Toast.LENGTH_LONG).show();
  			Toast.makeText(getApplicationContext(), R.string.success, Toast.LENGTH_LONG).show();
  			//mConfigState.putExtra(CERTIFICATE_RETRIEVED, true); // If this isn't the last step and finish() is moved...
 -        	setResult(RESULT_OK);
 -        	finish();
 +			setResult(RESULT_OK);
 +			finish();
  		} else if(resultCode == ConfigHelper.INCORRECTLY_DOWNLOADED_CERTIFICATE) {
  			mProgressDialog.dismiss();
  			Toast.makeText(getApplicationContext(), R.string.incorrectly_downloaded_certificate_message, Toast.LENGTH_LONG).show();
          	setResult(RESULT_CANCELED, mConfigState);
 -			finish();
  		}
  	}
 @@ -147,18 +138,23 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn       */
      @Override
      public void onItemSelected(String id) {
 -    	//TODO Code 2 pane view
 -    	Iterator<ProviderItem> preseeded_providers_iterator = ProviderListContent.ITEMS.iterator();
 -    	while(preseeded_providers_iterator.hasNext())
 -    	{
 -    		ProviderItem provider = preseeded_providers_iterator.next();
 -    		if(provider.id.equalsIgnoreCase(id))
 -    		{
 -    			mProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.config_wait_title), getResources().getString(R.string.config_connecting_provider), true);
 -    			mSelectedProvider = provider;
 -    			saveProviderJson(mSelectedProvider);
 -    		}
 -    	}
 +	    //TODO Code 2 pane view
 +	    ProviderItem selected_provider = getProvider(id);
 +	    if(mProgressDialog == null)
 +		    mProgressDialog =  ProgressDialog.show(this, getResources().getString(R.string.config_wait_title), getResources().getString(R.string.config_connecting_provider), true);
 +	    mSelectedProvider = selected_provider;
 +	    saveProviderJson(mSelectedProvider);
 +    }
 +
 +    private ProviderItem getProvider(String id) {
 +	    Iterator<ProviderItem> providers_iterator = ProviderListContent.ITEMS.iterator();
 +	    while(providers_iterator.hasNext()) {
 +		    ProviderItem provider = providers_iterator.next();
 +		    if(provider.id.equalsIgnoreCase(id)) {
 +			    return provider;
 +		    }
 +	    }
 +	    return null;
      }
      /**
 @@ -237,7 +233,7 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn  		provider_API_command.putExtra(ConfigHelper.DOWNLOAD_JSON_FILES_BUNDLE_EXTRA, method_and_parameters);
  		provider_API_command.putExtra(ConfigHelper.RECEIVER_KEY, providerAPI_result_receiver);
 - +
  		startService(provider_API_command);
  	}
 @@ -261,20 +257,20 @@ implements ProviderListFragment.Callbacks, NewProviderDialog.NewProviderDialogIn  	 * Open the new provider dialog
  	 * @param view from which the dialog is showed
  	 */
 -	public void addNewProvider(View view) {
 +	public void addAndSelectNewProvider(View view) {
  		FragmentTransaction fragment_transaction = getFragmentManager().beginTransaction();
 -	    Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.NEW_PROVIDER_DIALOG);
 -	    if (previous_new_provider_dialog != null) {
 -	        fragment_transaction.remove(previous_new_provider_dialog);
 -	    }
 -	    fragment_transaction.addToBackStack(null);
 -
 -	    DialogFragment newFragment = NewProviderDialog.newInstance();
 -	    newFragment.show(fragment_transaction, ConfigHelper.NEW_PROVIDER_DIALOG);
 +		Fragment previous_new_provider_dialog = getFragmentManager().findFragmentByTag(ConfigHelper.NEW_PROVIDER_DIALOG);
 +		if (previous_new_provider_dialog != null) {
 +			fragment_transaction.remove(previous_new_provider_dialog);
 +		}
 +		fragment_transaction.addToBackStack(null);
 +		
 +		DialogFragment newFragment = NewProviderDialog.newInstance();
 +		newFragment.show(fragment_transaction, ConfigHelper.NEW_PROVIDER_DIALOG);
  	}
  	@Override
 -	public void saveProvider(String provider_main_url, boolean danger_on) {
 +	public void saveAndSelectProvider(String provider_main_url, boolean danger_on) {
  		Intent provider_API_command = new Intent(this, ProviderAPI.class);
  		Bundle method_and_parameters = new Bundle();
 diff --git a/src/se/leap/leapclient/NewProviderDialog.java b/src/se/leap/leapclient/NewProviderDialog.java index 678e805f..cf361719 100644 --- a/src/se/leap/leapclient/NewProviderDialog.java +++ b/src/se/leap/leapclient/NewProviderDialog.java @@ -22,7 +22,7 @@ import android.widget.Toast;  public class NewProviderDialog extends DialogFragment {  	public interface NewProviderDialogInterface { -        public void saveProvider(String url_provider, boolean danger_on); +        public void saveAndSelectProvider(String url_provider, boolean danger_on);      }  	NewProviderDialogInterface interface_with_ConfigurationWizard; @@ -64,7 +64,7 @@ public class NewProviderDialog extends DialogFragment {  					}  					boolean danger_on = danger_checkbox.isChecked();  					if(validURL(entered_url)) { -						interface_with_ConfigurationWizard.saveProvider(entered_url, danger_on); +						interface_with_ConfigurationWizard.saveAndSelectProvider(entered_url, danger_on);  						Toast.makeText(getActivity().getApplicationContext(), R.string.valid_url_entered, Toast.LENGTH_LONG).show();  					} else {  						url_input_field.setText(""); diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java index 72cc9b62..e7e3918c 100644 --- a/src/se/leap/leapclient/ProviderAPI.java +++ b/src/se/leap/leapclient/ProviderAPI.java @@ -91,8 +91,9 @@ public class ProviderAPI extends IntentService {  			}  		}  		else if ((task = task_for.getBundleExtra(ConfigHelper.DOWNLOAD_NEW_PROVIDER_DOTJSON)) != null) { -			if(downloadNewProviderDotJSON(task)) { -				receiver.send(ConfigHelper.CUSTOM_PROVIDER_ADDED, Bundle.EMPTY); +			Bundle result = downloadNewProviderDotJSON(task); +			if(result.getBoolean(ConfigHelper.RESULT_KEY)) { +				receiver.send(ConfigHelper.CORRECTLY_UPDATED_PROVIDER_DOT_JSON, result);  			} else {  				receiver.send(ConfigHelper.INCORRECTLY_DOWNLOADED_JSON_FILES, Bundle.EMPTY);  			} @@ -287,7 +288,8 @@ public class ProviderAPI extends IntentService {  	 * @param task containing a boolean meaning if the user completely trusts this provider, and the provider main url entered in the new custom provider dialog.  	 * @return true if provider.json file was successfully parsed as a JSON object.  	 */ -	private boolean downloadNewProviderDotJSON(Bundle task) { +	private Bundle downloadNewProviderDotJSON(Bundle task) { +		Bundle result = new Bundle();  		boolean custom = true;  		boolean danger_on = task.getBoolean(ConfigHelper.DANGER_ON); @@ -298,14 +300,26 @@ public class ProviderAPI extends IntentService {  		JSONObject provider_json;  		try {  			provider_json = getJSONFromProvider(provider_json_url, danger_on); -			ProviderListContent.addItem(new ProviderItem(provider_name, provider_json_url, provider_json, custom, danger_on)); +			if(provider_json == null) { +				result.putBoolean(ConfigHelper.RESULT_KEY, false); +			} else {    			 + +				ConfigHelper.saveSharedPref(ConfigHelper.PROVIDER_KEY, provider_json); +				ConfigHelper.saveSharedPref(ConfigHelper.DANGER_ON, danger_on); +				ConfigHelper.saveSharedPref(ConfigHelper.ALLOWED_ANON, provider_json.getJSONObject(ConfigHelper.SERVICE_KEY).getBoolean(ConfigHelper.ALLOWED_ANON)); +				ProviderItem added_provider = new ProviderItem(provider_name, provider_json_url, provider_json, custom, danger_on); +				ProviderListContent.addItem(added_provider); + +				result.putString(ConfigHelper.PROVIDER_ID, added_provider.getId()); +				result.putBoolean(ConfigHelper.RESULT_KEY, true); +				result.putString(ConfigHelper.PROVIDER_KEY, provider_json.toString()); +				result.putBoolean(ConfigHelper.DANGER_ON, danger_on); +			}  		} catch (JSONException e) { -			// TODO Auto-generated catch block -			e.printStackTrace(); -			return false; +			result.putBoolean(ConfigHelper.RESULT_KEY, false);  		} -		return true; +		return result;  	}  	/** diff --git a/src/se/leap/leapclient/ProviderListContent.java b/src/se/leap/leapclient/ProviderListContent.java index 8727b16b..dc3d6ab3 100644 --- a/src/se/leap/leapclient/ProviderListContent.java +++ b/src/se/leap/leapclient/ProviderListContent.java @@ -6,6 +6,8 @@ import java.util.ArrayList;  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
 +import java.net.URL;
 +import java.net.MalformedURLException;
  import org.json.JSONException;
  import org.json.JSONObject;
 @@ -18,54 +20,59 @@ import org.json.JSONObject;   */
  public class ProviderListContent {
 -    public static List<ProviderItem> ITEMS = new ArrayList<ProviderItem>();
 +	public static List<ProviderItem> ITEMS = new ArrayList<ProviderItem>();
 -    public static Map<String, ProviderItem> ITEM_MAP = new HashMap<String, ProviderItem>();
 -    
 -    /**
 -     * Adds a new provider item to the end of the items map, and to the items list.
 -     * @param item
 -     */
 -    public static void addItem(ProviderItem item) {
 -        ITEMS.add(item);
 -        ITEM_MAP.put(String.valueOf(ITEMS.size()), item);
 -    }
 +	public static Map<String, ProviderItem> ITEM_MAP = new HashMap<String, ProviderItem>();
 -    /**
 -     * A provider item.
 -     */
 -    public static class ProviderItem {  
 -    	public boolean custom = false;
 -    	public String id;
 -        public String name;
 -        public String provider_json_url;
 +	/**
 +	 * Adds a new provider item to the end of the items map, and to the items list.
 +	 * @param item
 +	 */
 +	public static void addItem(ProviderItem item) {
 +		ITEMS.add(item);
 +		ITEM_MAP.put(String.valueOf(ITEMS.size()), item);
 +	}
 +
 +	/**
 +	 * A provider item.
 +	 */
 +	public static class ProviderItem {  
 +		public boolean custom = false;
 +		public String id;
 +		public String name;
 +		public String domain;
 +		public String provider_json_url;
  		public JSONObject provider_json;
 -        public String provider_json_filename;
 -        public String eip_service_json_url;
 -        public String cert_json_url;
 -        public boolean danger_on = false;
 +		public String provider_json_filename;
 +		public String eip_service_json_url;
 +		public String cert_json_url;
 +		public boolean danger_on = false;
 +
 +		/**
 +		 * @param name of the provider
 +		 * @param urls_file_input_stream file input stream linking with the assets url file
 +		 * @param custom if it's a new provider entered by the user or not
 +		 * @param danger_on if the user trusts completely the new provider
 +		 */
 +		public ProviderItem(String name, InputStream urls_file_input_stream, boolean custom, boolean danger_on) {
 -        /**
 -         * @param name of the provider
 -         * @param urls_file_input_stream file input stream linking with the assets url file
 -         * @param custom if it's a new provider entered by the user or not
 -         * @param danger_on if the user trusts completely the new provider
 -         */
 -        public ProviderItem(String name, InputStream urls_file_input_stream, boolean custom, boolean danger_on) {
 -        	
 -        	try {
 -        		byte[] urls_file_bytes = new byte[urls_file_input_stream.available()];
 -        		urls_file_input_stream.read(urls_file_bytes);
 -        		String urls_file_content = new String(urls_file_bytes);
 +			try {
 +				byte[] urls_file_bytes = new byte[urls_file_input_stream.available()];
 +				urls_file_input_stream.read(urls_file_bytes);
 +				String urls_file_content = new String(urls_file_bytes);
  				JSONObject file_contents = new JSONObject(urls_file_content);
  				id = name;
  				this.name = name;
  				provider_json_url = file_contents.getString(ConfigHelper.PROVIDER_JSON_URL);
 -				provider_json_filename = file_contents.getString("assets_json_provider");
 +				domain = new URL(provider_json_url).getHost();
 +				//provider_json_filename = file_contents.getString("assets_json_provider");
  				eip_service_json_url = file_contents.getString("json_eip_service");
  				cert_json_url = file_contents.getString(ConfigHelper.CERT_KEY);
  				this.custom = custom;
  				this.danger_on = danger_on;
 +			} catch (MalformedURLException e) {
 +				// TODO Auto-generated catch block
 +				e.printStackTrace();
  			} catch (JSONException e) {
  				// TODO Auto-generated catch block
  				e.printStackTrace();
 @@ -73,37 +80,46 @@ public class ProviderListContent {  				// TODO Auto-generated catch block
  				e.printStackTrace();
  			}
 -        }
 +		}
 +
 +		/**
 +		 * @param name of the provider
 +		 * @param provider_json_url used to download provider.json file of the provider
 +		 * @param provider_json already downloaded
 +		 * @param custom if it's a new provider entered by the user or not
 +		 * @param danger_on if the user trusts completely the new provider
 +		 */
 +		public ProviderItem(String name, String provider_json_url, JSONObject provider_json, boolean custom, boolean danger_on) {
 -        /**
 -         * @param name of the provider
 -         * @param provider_json_url used to download provider.json file of the provider
 -         * @param provider_json already downloaded
 -         * @param custom if it's a new provider entered by the user or not
 -         * @param danger_on if the user trusts completely the new provider
 -         */
 -        public ProviderItem(String name, String provider_json_url, JSONObject provider_json, boolean custom, boolean danger_on) {
 -        	
 -        	try {
 +			try {
  				id = name;
 -				this.name = name;
 +				//this.name = name;
  				this.provider_json_url = provider_json_url;
  				this.provider_json = provider_json;
 +				this.name = provider_json.getJSONObject("name").getString("en");
 +				domain = new URL(provider_json_url).getHost();
  				eip_service_json_url = provider_json.getString(ConfigHelper.API_URL_KEY) + "/" + provider_json.getString(ConfigHelper.API_VERSION_KEY) + "/" + ConfigHelper.EIP_SERVICE_API_PATH;
 -				cert_json_url = (String) provider_json.get("ca_cert_uri");
 +				cert_json_url = provider_json.getString("ca_cert_uri");
  				this.custom = custom;
  				this.danger_on = danger_on;
  				if(custom)
  					provider_json_filename = name + "_provider.json".replaceFirst("__", "_");
 +			} catch (MalformedURLException e) {
 +				// TODO Auto-generated catch block
 +				e.printStackTrace();
  			} catch (JSONException e) {
  				// TODO Auto-generated catch block
  				e.printStackTrace();
  			}
 -        }
 +		}
 +
 +		@Override
 +		public String toString() {
 +			return name;
 +		}
 -        @Override
 -        public String toString() {
 -            return name;
 -        }
 -    }
 +		public String getId() {
 +			return id;
 +		}
 +	}
  }
 diff --git a/src/se/leap/leapclient/ProviderListFragment.java b/src/se/leap/leapclient/ProviderListFragment.java index ee3ee8ea..f4f5feb9 100644 --- a/src/se/leap/leapclient/ProviderListFragment.java +++ b/src/se/leap/leapclient/ProviderListFragment.java @@ -9,6 +9,8 @@ import android.view.View;  import android.view.ViewGroup;
  import android.widget.ArrayAdapter;
  import android.widget.ListView;
 +import android.content.Context;
 +import android.widget.TwoLineListItem;
  /**
   * A list fragment representing a list of Providers. This fragment
 @@ -74,10 +76,25 @@ public class ProviderListFragment extends ListFragment {          super.onCreate(savedInstanceState);
          content_adapter = new ArrayAdapter<ProviderListContent.ProviderItem>(
                  getActivity(),
 -                android.R.layout.simple_list_item_activated_1,
 -                android.R.id.text1,
 -                ProviderListContent.ITEMS);
 -        setListAdapter(content_adapter);
 +                android.R.layout.simple_list_item_activated_2,
 +		ProviderListContent.ITEMS) {
 +			@Override
 +			public View getView(int position, View convertView, ViewGroup parent){
 +				TwoLineListItem row;            
 +				if (convertView == null) {
 +					LayoutInflater inflater = (LayoutInflater)getActivity().getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 +					row = (TwoLineListItem)inflater.inflate(android.R.layout.simple_list_item_2, null);                    
 +				} else {
 +					row = (TwoLineListItem)convertView;
 +				}
 +				ProviderListContent.ProviderItem data = ProviderListContent.ITEMS.get(position);
 +				row.getText1().setText(data.domain);
 +				row.getText2().setText(data.name);
 +
 +				return row;
 +			}
 +	};
 +	setListAdapter(content_adapter);
      }
      @Override
  | 
