summaryrefslogtreecommitdiff
path: root/app/src/main/java/se/leap
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/se/leap')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java1
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java8
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java12
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/fragments/Settings_Allowed_Apps.java364
5 files changed, 385 insertions, 2 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java b/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java
index 89aeb4be..024bfaba 100644
--- a/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java
+++ b/app/src/main/java/se/leap/bitmaskclient/DrawerSettingsAdapter.java
@@ -45,6 +45,7 @@ public class DrawerSettingsAdapter extends BaseAdapter {
public static final int BATTERY_SAVER = 3;
public static final int ALWAYS_ON = 4;
public static final int DONATE = 5;
+ public static final int SELECT_APPS = 6;
//view types
public final static int VIEW_SIMPLE_TEXT = 0;
diff --git a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
index 640c143a..21bc8360 100644
--- a/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/drawer/NavigationDrawerFragment.java
@@ -59,6 +59,8 @@ import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.fragments.AboutFragment;
import se.leap.bitmaskclient.fragments.AlwaysOnDialog;
import se.leap.bitmaskclient.fragments.LogFragment;
+import se.leap.bitmaskclient.fragments.SelectAppsFragment;
+import se.leap.bitmaskclient.fragments.Settings_Allowed_Apps;
import static android.content.Context.MODE_PRIVATE;
import static se.leap.bitmaskclient.BitmaskApp.getRefWatcher;
@@ -74,6 +76,7 @@ import static se.leap.bitmaskclient.DrawerSettingsAdapter.DONATE;
import static se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem.getSimpleTextInstance;
import static se.leap.bitmaskclient.DrawerSettingsAdapter.DrawerSettingsItem.getSwitchInstance;
import static se.leap.bitmaskclient.DrawerSettingsAdapter.LOG;
+import static se.leap.bitmaskclient.DrawerSettingsAdapter.SELECT_APPS;
import static se.leap.bitmaskclient.DrawerSettingsAdapter.SWITCH_PROVIDER;
import static se.leap.bitmaskclient.R.string.about_fragment_title;
import static se.leap.bitmaskclient.R.string.donate_title;
@@ -273,6 +276,7 @@ public class NavigationDrawerFragment extends Fragment {
settingsListAdapter.addItem(getSimpleTextInstance(getContext(), getString(donate_title), R.drawable.ic_donate_36, DONATE));
}
settingsListAdapter.addItem(getSimpleTextInstance(getContext(), getString(about_fragment_title), R.drawable.ic_about_36, ABOUT));
+ settingsListAdapter.addItem(getSimpleTextInstance(getContext(), getString(about_fragment_title), R.drawable.ic_about_36, SELECT_APPS));
}
private ActionBar setupActionBar() {
@@ -494,6 +498,10 @@ public class NavigationDrawerFragment extends Fragment {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(DONATION_URL));
startActivity(browserIntent);
break;
+ case SELECT_APPS:
+ fragment = new Settings_Allowed_Apps();
+ setActionBarTitle(about_fragment_title);
+ break;
default:
break;
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
index 55ade1ae..77666378 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
@@ -16,6 +16,9 @@
*/
package se.leap.bitmaskclient.eip;
+import android.content.Context;
+import android.content.SharedPreferences;
+
import com.google.gson.Gson;
import org.json.JSONException;
@@ -23,9 +26,12 @@ import org.json.JSONObject;
import java.io.IOException;
import java.io.StringReader;
+import java.util.HashSet;
+import java.util.Set;
import de.blinkt.openvpn.VpnProfile;
import de.blinkt.openvpn.core.ConfigParser;
+import se.leap.bitmaskclient.BitmaskApp;
/**
* Gateway provides objects defining gateways and their metadata.
@@ -52,7 +58,7 @@ public class Gateway {
* Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json
* and create a VpnProfile belonging to it.
*/
- public Gateway(JSONObject eip_definition, JSONObject secrets, JSONObject gateway) {
+ public Gateway(JSONObject eip_definition, JSONObject secrets, JSONObject gateway, Context context) {
this.gateway = gateway;
this.secrets = secrets;
@@ -62,7 +68,11 @@ public class Gateway {
mName = locationAsName(eip_definition);
mVpnProfile = createVPNProfile();
+ System.out.println("###########" + mName + "###########");
mVpnProfile.mName = mName;
+
+ SharedPreferences allow_apps = context.getSharedPreferences("BITMASK", Context.MODE_MULTI_PROCESS);
+ mVpnProfile.mAllowedAppsVpn = new HashSet<String>(allow_apps.getStringSet("ALLOW_APPS", new HashSet<String>()));
}
private JSONObject getGeneralConfiguration(JSONObject eip_definition) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
index 060843fd..8edf81ef 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
@@ -93,7 +93,7 @@ public class GatewaysManager {
JSONObject gw = gatewaysDefined.getJSONObject(i);
if (isOpenVpnGateway(gw)) {
JSONObject secrets = secretsConfiguration();
- Gateway aux = new Gateway(eipDefinition, secrets, gw);
+ Gateway aux = new Gateway(eipDefinition, secrets, gw, context);
if (!gateways.contains(aux)) {
addGateway(aux);
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/fragments/Settings_Allowed_Apps.java b/app/src/main/java/se/leap/bitmaskclient/fragments/Settings_Allowed_Apps.java
new file mode 100644
index 00000000..f930b278
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/fragments/Settings_Allowed_Apps.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2012-2016 Arne Schwabe
+ * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
+ */
+
+package se.leap.bitmaskclient.fragments;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.support.v4.app.Fragment;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.CompoundButton;
+import android.widget.Filter;
+import android.widget.Filterable;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.SearchView;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.Vector;
+
+import de.blinkt.openvpn.VpnProfile;
+import se.leap.bitmaskclient.EipSetupListener;
+import se.leap.bitmaskclient.EipSetupObserver;
+import se.leap.bitmaskclient.R;
+
+/**
+ * Created by arne on 16.11.14.
+ */
+public class Settings_Allowed_Apps extends Fragment implements AdapterView.OnItemClickListener, CompoundButton.OnCheckedChangeListener, View.OnClickListener {
+ private ListView mListView;
+ private VpnProfile mProfile;
+ private TextView mDefaultAllowTextView;
+ private PackageAdapter mListAdapter;
+
+ private SharedPreferences allow_apps;
+ private SharedPreferences.Editor allow_apps_editor;
+ private Set<String> apps;
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ AppViewHolder avh = (AppViewHolder) view.getTag();
+ avh.checkBox.toggle();
+ }
+
+ @Override
+ public void onClick(View v) {
+
+ }
+
+ static class AppViewHolder {
+ public ApplicationInfo mInfo;
+ public View rootView;
+ public TextView appName;
+ public ImageView appIcon;
+ //public TextView appSize;
+ //public TextView disabled;
+ public CompoundButton checkBox;
+
+ static public AppViewHolder createOrRecycle(LayoutInflater inflater, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = inflater.inflate(R.layout.allowed_application_layout, parent, false);
+
+ // Creates a ViewHolder and store references to the two children views
+ // we want to bind data to.
+ AppViewHolder holder = new AppViewHolder();
+ holder.rootView = convertView;
+ holder.appName = (TextView) convertView.findViewById(R.id.app_name);
+ holder.appIcon = (ImageView) convertView.findViewById(R.id.app_icon);
+ //holder.appSize = (TextView) convertView.findViewById(R.id.app_size);
+ //holder.disabled = (TextView) convertView.findViewById(R.id.app_disabled);
+ holder.checkBox = (CompoundButton) convertView.findViewById(R.id.app_selected);
+ convertView.setTag(holder);
+
+ return holder;
+ } else {
+ // Get the ViewHolder back to get fast access to the TextView
+ // and the ImageView.
+ return (AppViewHolder) convertView.getTag();
+ }
+ }
+
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ String packageName = (String) buttonView.getTag();
+
+ if (isChecked) {
+ Log.d("openvpn", "adding to allowed apps" + packageName);
+
+ apps.add(packageName);
+
+ } else {
+ Log.d("openvpn", "removing from allowed apps" + packageName);
+ //Log.d("eneko", this.getContext().getSharedPreferences("BITMASK", Context.MODE_MULTI_PROCESS).getString("ALLOW_APPS", ""));
+
+ apps.remove(packageName);
+ }
+ allow_apps_editor.clear();
+ allow_apps_editor.putStringSet("ALLOW_APPS", apps);
+ allow_apps_editor.apply();
+ }
+
+
+ class PackageAdapter extends BaseAdapter implements Filterable {
+ private Vector<ApplicationInfo> mPackages;
+ private final LayoutInflater mInflater;
+ private final PackageManager mPm;
+ private ItemFilter mFilter = new ItemFilter();
+ private Vector<ApplicationInfo> mFilteredData;
+
+
+ private class ItemFilter extends Filter {
+ @Override
+ protected FilterResults performFiltering(CharSequence constraint) {
+
+ String filterString = constraint.toString().toLowerCase(Locale.getDefault());
+
+ FilterResults results = new FilterResults();
+
+
+ int count = mPackages.size();
+ final Vector<ApplicationInfo> nlist = new Vector<>(count);
+
+ for (int i = 0; i < count; i++) {
+ ApplicationInfo pInfo = mPackages.get(i);
+ CharSequence appName = pInfo.loadLabel(mPm);
+
+ if (TextUtils.isEmpty(appName))
+ appName = pInfo.packageName;
+
+ if (appName instanceof String) {
+ if (((String) appName).toLowerCase(Locale.getDefault()).contains(filterString))
+ nlist.add(pInfo);
+ } else {
+ if (appName.toString().toLowerCase(Locale.getDefault()).contains(filterString))
+ nlist.add(pInfo);
+ }
+ }
+ results.values = nlist;
+ results.count = nlist.size();
+
+ return results;
+ }
+
+ @Override
+ protected void publishResults(CharSequence constraint, FilterResults results) {
+ mFilteredData = (Vector<ApplicationInfo>) results.values;
+ notifyDataSetChanged();
+ }
+
+ }
+
+
+ PackageAdapter(Context c, VpnProfile vp) {
+ mPm = c.getPackageManager();
+ mProfile = vp;
+ mInflater = LayoutInflater.from(c);
+
+ mPackages = new Vector<>();
+ mFilteredData = mPackages;
+ }
+
+ private void populateList(Activity c) {
+ List<ApplicationInfo> installedPackages = mPm.getInstalledApplications(PackageManager.GET_META_DATA);
+
+ // Remove apps not using Internet
+
+ int androidSystemUid = 0;
+ ApplicationInfo system = null;
+ Vector<ApplicationInfo> apps = new Vector<ApplicationInfo>();
+
+ try {
+ system = mPm.getApplicationInfo("android", PackageManager.GET_META_DATA);
+ androidSystemUid = system.uid;
+ apps.add(system);
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+
+
+ for (ApplicationInfo app : installedPackages) {
+
+ if (mPm.checkPermission(Manifest.permission.INTERNET, app.packageName) == PackageManager.PERMISSION_GRANTED &&
+ app.uid != androidSystemUid) {
+
+ apps.add(app);
+ }
+ }
+
+ Collections.sort(apps, new ApplicationInfo.DisplayNameComparator(mPm));
+ mPackages = apps;
+ mFilteredData = apps;
+ c.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ notifyDataSetChanged();
+ }
+ });
+ }
+
+ @Override
+ public int getCount() {
+ return mFilteredData.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mFilteredData.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return mFilteredData.get(position).packageName.hashCode();
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ AppViewHolder viewHolder = AppViewHolder.createOrRecycle(mInflater, convertView, parent);
+ convertView = viewHolder.rootView;
+ viewHolder.mInfo = mFilteredData.get(position);
+ final ApplicationInfo mInfo = mFilteredData.get(position);
+
+
+ CharSequence appName = mInfo.loadLabel(mPm);
+
+ if (TextUtils.isEmpty(appName))
+ appName = mInfo.packageName;
+ viewHolder.appName.setText(appName);
+ viewHolder.appIcon.setImageDrawable(mInfo.loadIcon(mPm));
+ viewHolder.checkBox.setTag(mInfo.packageName);
+ viewHolder.checkBox.setOnCheckedChangeListener(Settings_Allowed_Apps.this);
+ viewHolder.checkBox.setChecked(apps.contains(mInfo.packageName));
+
+
+ // viewHolder.checkBox.setChecked(mProfile.mAllowedAppsVpn.contains(mInfo.packageName));
+ return viewHolder.rootView;
+ }
+
+ @Override
+ public Filter getFilter() {
+ return mFilter;
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+// changeDisallowText(mProfile.mAllowedAppsVpnAreDisallowed);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ allow_apps = this.getContext().getSharedPreferences("BITMASK", Context.MODE_MULTI_PROCESS);
+ allow_apps_editor = allow_apps.edit();
+ apps = new HashSet<String>(allow_apps.getStringSet("ALLOW_APPS", new HashSet<String>()));
+
+// /String profileUuid = getArguments().getString(getActivity().getPackageName() + ".profileUUID");
+// mProfile = EipSetupObserver.getProfile();
+// getActivity().setTitle(getString(R.string.edit_profile_title, mProfile.getName()));
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.allowed_apps, menu);
+
+ SearchView searchView = (SearchView) menu.findItem( R.id.app_search_widget ).getActionView();
+ searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ mListView.setFilterText(query);
+ mListView.setTextFilterEnabled(true);
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ mListView.setFilterText(newText);
+ if (TextUtils.isEmpty(newText))
+ mListView.setTextFilterEnabled(false);
+ else
+ mListView.setTextFilterEnabled(true);
+
+ return true;
+ }
+ });
+ searchView.setOnCloseListener(new SearchView.OnCloseListener() {
+ @Override
+ public boolean onClose() {
+ mListView.clearTextFilter();
+ mListAdapter.getFilter().filter("");
+ return false;
+ }
+ });
+
+ super.onCreateOptionsMenu(menu, inflater);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.allowed_vpn_apps, container, false);
+
+ mDefaultAllowTextView = (TextView) v.findViewById(R.id.default_allow_text);
+
+ Switch vpnOnDefaultSwitch = (Switch) v.findViewById(R.id.default_allow);
+
+ vpnOnDefaultSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+
+ changeDisallowText(isChecked);
+ mProfile.mAllowedAppsVpnAreDisallowed = isChecked;
+ }
+ });
+
+// vpnOnDefaultSwitch.setChecked(mProfile.mAllowedAppsVpnAreDisallowed);
+
+ mListView = (ListView) v.findViewById(android.R.id.list);
+
+ mListAdapter = new PackageAdapter(getActivity(), mProfile);
+ mListView.setAdapter(mListAdapter);
+ mListView.setOnItemClickListener(this);
+
+ mListView.setEmptyView(v.findViewById(R.id.loading_container));
+
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ mListAdapter.populateList(getActivity());
+ }
+ }).start();
+
+ return v;
+ }
+
+ private void changeDisallowText(boolean selectedAreDisallowed) {
+ if (selectedAreDisallowed)
+ mDefaultAllowTextView.setText(R.string.vpn_disallow_radio);
+ else
+ mDefaultAllowTextView.setText(R.string.vpn_allow_radio);
+ }
+}