eu.operando.proxy.filters.domain.DomainFiltersActivity.java Source code

Java tutorial

Introduction

Here is the source code for eu.operando.proxy.filters.domain.DomainFiltersActivity.java

Source

/*
 * Copyright (c) 2016 {UPRC}.
 *
 * OperandoApp is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * OperandoApp is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with OperandoApp.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *       Nikos Lykousas {UPRC}, Constantinos Patsakis {UPRC}
 * Initially developed in the context of OPERANDO EU project www.operando.eu
 */

package eu.operando.proxy.filters.domain;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.util.Patterns;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;

import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.OnClick;
import eu.operando.R;
import eu.operando.proxy.MainContext;
import eu.operando.proxy.database.DatabaseHelper;
import eu.operando.proxy.database.model.DomainFilter;
import eu.operando.proxy.database.model.FilterFile;
import eu.operando.proxy.filters.DownloadTask;

public class DomainFiltersActivity extends AppCompatActivity {

    private static final String TAG = "DomainFiltersActivity";

    private MainContext mainContext = MainContext.INSTANCE;

    @InjectView(R.id.recycler_view_holder)
    public FrameLayout recyclerViewHolder;

    private RecyclerView recyclerView;

    private List<DomainFilter> userFilters;

    private List<FilterFile> externalFilters;

    private UserDomainFiltersAdapter userDomainFiltersAdapter;

    private ExternalDomainFiltersAdapter externalDomainFiltersAdapter;

    private MenuItem deleteAction;

    private Bus BUS = mainContext.getBUS();

    private DatabaseHelper db = mainContext.getDatabaseHelper();

    private int viewSelected = 0; //0: user, 1: external

    private Set<DomainFilter> userDomainFiltersSelected = new HashSet<>();
    private Set<FilterFile> externalFilterFilesSelected = new HashSet<>();

    protected void updateFiltersList() {
        userFilters = db.getAllUserDomainFilters();
        externalFilters = db.getAllDomainFilterFiles();
    }

    protected void inValidateSelections() {
        userDomainFiltersSelected.clear();
        externalFilterFilesSelected.clear();
        if (userDomainFiltersAdapter != null && externalDomainFiltersAdapter != null) {
            userDomainFiltersAdapter.updateEditAction();
            externalDomainFiltersAdapter.updateEditAction();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setTheme(MainContext.INSTANCE.getSettings().getThemeStyle().themeAppCompatStyle());
        updateFiltersList();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.filters_content);
        ButterKnife.inject(this);

        userDomainFiltersAdapter = new UserDomainFiltersAdapter();
        externalDomainFiltersAdapter = new ExternalDomainFiltersAdapter();

        recyclerView = new RecyclerView(this);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        //recyclerView.setAdapter(userDomainFiltersAdapter);
        //recyclerViewHolder.addView(recyclerView);

        //Setup Toolbar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setHomeButtonEnabled(true);
            actionBar.setDisplayHomeAsUpEnabled(true);
            View spinnerContainer = LayoutInflater.from(this).inflate(R.layout.toolbar_spinner, toolbar, false);
            ActionBar.LayoutParams lp = new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);
            toolbar.addView(spinnerContainer, lp);

            DomainFiltersSpinnerAdapter spinnerAdapter = new DomainFiltersSpinnerAdapter();

            Spinner spinner = (Spinner) spinnerContainer.findViewById(R.id.toolbar_spinner);
            spinner.setAdapter(spinnerAdapter);
            spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    viewSelected = position;
                    recyclerViewHolder.removeAllViews();
                    //recyclerViewHolder.invalidate();
                    switch (position) {
                    case 0:
                        recyclerView.setAdapter(userDomainFiltersAdapter);
                        break;
                    case 1:
                        recyclerView.setAdapter(externalDomainFiltersAdapter);
                        break;
                    default:
                        recyclerView.setAdapter(userDomainFiltersAdapter);
                        break;
                    }
                    recyclerViewHolder.addView(recyclerView);
                    inValidateSelections();

                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {
                }
            });

        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.filter_menu, menu);
        deleteAction = menu.getItem(0);
        deleteAction.setEnabled(false);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    protected void onResume() {
        super.onResume();
        BUS.register(userDomainFiltersAdapter);
        BUS.register(externalDomainFiltersAdapter);
    }

    @Override
    protected void onPause() {
        super.onPause();
        BUS.unregister(userDomainFiltersAdapter);
        BUS.unregister(externalDomainFiltersAdapter);
    }

    @OnClick(R.id.add_filter)
    public void addFilter() {

        if (viewSelected == 0) { //User Filter

            View dialogView = getLayoutInflater().inflate(R.layout.user_domain_filter_dialog, null);
            final EditText input = (EditText) dialogView.findViewById(R.id.filter_content);
            final CheckBox isWildcard = (CheckBox) dialogView.findViewById(R.id.is_wildcard);

            AlertDialog.Builder builder = new AlertDialog.Builder(this).setTitle("New DomainFilter")
                    .setView(dialogView)
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {

                            DomainFilter domainFilter = new DomainFilter();
                            domainFilter.setContent(input.getText().toString().toLowerCase());
                            domainFilter.setSource(null);
                            domainFilter.setIsWildcard(isWildcard.isChecked());
                            db.createDomainFilter(domainFilter);
                            updateFiltersList();
                            userDomainFiltersAdapter.notifyItemInserted(userFilters.size() - 1);
                            recyclerView.scrollToPosition(userFilters.size() - 1);
                        }
                    }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            // Canceled.
                        }
                    });

            final AlertDialog dialog = builder.create();

            input.addTextChangedListener(new TextWatcher() {
                @Override
                public void afterTextChanged(Editable s) {
                    if (Patterns.DOMAIN_NAME.matcher(s).matches()) {
                        dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
                    } else
                        dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
                }

                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                }
            });

            dialog.setOnShowListener(new DialogInterface.OnShowListener() {
                @Override
                public void onShow(DialogInterface dialog) {
                    ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
                }
            });

            dialog.show();

        } else { //Imported filter list
            final EditText input = new EditText(this);
            input.setSingleLine(true);
            input.setHint("Enter URL");
            new AlertDialog.Builder(this).setTitle("Import filters from remote file (hosts file format)")
                    .setView(input).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {

                            final String importUrl = input.getText().toString();
                            importExternalFilters(importUrl);

                        }
                    }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            // Canceled.
                        }
                    }).show();
        }
    }

    protected void importExternalFilters(final String importUrl) {
        //String timestap = SimpleDateFormat.getDateTimeInstance().format(new Date().getTime());
        final File tmp = new File(getFilesDir(), "domainfilters_" + System.currentTimeMillis());
        try {
            new DownloadTask(DomainFiltersActivity.this, new URL(importUrl), tmp, new DownloadTask.Listener() {
                @Override
                public void onCompleted() {
                    Toast.makeText(DomainFiltersActivity.this, R.string.msg_downloaded, Toast.LENGTH_LONG).show();

                    new AsyncTask<Void, Void, Integer>() {

                        ProgressDialog dialog;

                        @Override
                        protected void onPreExecute() {
                            dialog = ProgressDialog.show(DomainFiltersActivity.this, null,
                                    "Parsing downloaded file...");
                            dialog.setCancelable(false);
                        }

                        @Override
                        protected Integer doInBackground(Void... params) {
                            Integer count = 0;
                            BufferedReader br = null;
                            try {
                                br = new BufferedReader(new FileReader(tmp));
                                String line;
                                while ((line = br.readLine()) != null) {
                                    int hash = line.indexOf('#');
                                    if (hash >= 0)
                                        line = line.substring(0, hash);
                                    line = line.trim();

                                    if (line.length() > 0) {
                                        String[] words = line.split("\\s+");
                                        if (words.length == 2) {
                                            String blockedDomain = words[1].toLowerCase();
                                            if (blockedDomain.equals("local") || StringUtils.containsAny(
                                                    blockedDomain, "localhost", "127.0.0.1", "broadcasthost"))
                                                continue;
                                            DomainFilter domainFilter = new DomainFilter();
                                            domainFilter.setContent(blockedDomain);
                                            domainFilter.setSource(importUrl);
                                            domainFilter.setIsWildcard(false);
                                            db.createDomainFilter(domainFilter);
                                            count++;
                                        } else
                                            Log.i(TAG, "Invalid hosts file line: " + line);
                                    }
                                }
                                Log.i(TAG, count + " entries read");
                            } catch (IOException ex) {
                                Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
                            } finally {
                                if (br != null)
                                    try {
                                        br.close();
                                    } catch (IOException exex) {
                                        Log.e(TAG, exex.toString() + "\n" + Log.getStackTraceString(exex));
                                    }
                            }

                            return count;
                        }

                        @Override
                        protected void onPostExecute(Integer count) {
                            dialog.dismiss();
                            if (count > 0) {
                                updateFiltersList();
                                externalDomainFiltersAdapter.notifyDataSetChanged();
                            }
                        }
                    }.execute();
                }

                @Override
                public void onCancelled() {
                    if (tmp.exists())
                        tmp.delete();
                }

                @Override
                public void onException(Throwable ex) {
                    if (tmp.exists())
                        tmp.delete();

                    ex.printStackTrace();
                    Toast.makeText(DomainFiltersActivity.this, ex.getMessage(), Toast.LENGTH_LONG).show();
                }
            }).execute();
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
            Toast.makeText(DomainFiltersActivity.this, ex.toString(), Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);
            break;
        case R.id.action_delete:
            if (viewSelected == 0)
                userDomainFiltersAdapter.deleteCheckedItems();
            else
                externalDomainFiltersAdapter.deleteCheckedItems();
            break;
        default:
            return super.onOptionsItemSelected(item);
        }
        return true;
    }

    private class DomainFiltersSpinnerAdapter extends BaseAdapter {

        final String[] filterSrcArray = new String[] { "User specified", "External" };

        @Override
        public int getCount() {
            return filterSrcArray.length;
        }

        @Override
        public String getItem(int position) {
            return filterSrcArray[position];
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = convertView != null ? convertView
                    : getLayoutInflater().inflate(R.layout.toolbar_spinner_item_actionbar, parent, false);

            TextView title = (TextView) view.findViewById(R.id.toolbarTitle);
            title.setText(getResources().getString(R.string.domain_filters));

            TextView subtitle = (TextView) view.findViewById(R.id.toolbarSubtitle);
            subtitle.setText(getItem(position));
            return view;
        }

        @Override
        public View getDropDownView(int position, View convertView, ViewGroup parent) {

            View view = convertView != null ? convertView
                    : getLayoutInflater().inflate(R.layout.toolbar_spinner_item_dropdown, parent, false);

            TextView textView = (TextView) view.findViewById(R.id.toolbarSpinnerCell);
            textView.setText(getItem(position));

            return view;
        }
    }

    /*
    -----------------------------------------
    Domain Filters entered manually by user
    -----------------------------------------
     */
    private class UserDomainFiltersAdapter extends RecyclerView.Adapter<UserDomainFiltersRowHolder> {

        @Override
        public UserDomainFiltersRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new UserDomainFiltersRowHolder(getLayoutInflater().inflate(R.layout.filter_row, parent, false));
        }

        @Override
        public void onBindViewHolder(UserDomainFiltersRowHolder holder, int position) {

            DomainFilter DomainFilter = userFilters.get(position);
            holder.setDomainFilter(DomainFilter);
            holder.setChecked(userDomainFiltersSelected.contains(DomainFilter));
        }

        @Override
        public int getItemCount() {
            return userFilters.size();
        }

        @Subscribe
        public void onUserDomainFilterCheckStateChangedEvent(UserDomainFilterCheckStateChangedEvent event) {
            if (event.isChecked) {
                userDomainFiltersSelected.add(event.DomainFilter);
            } else {
                userDomainFiltersSelected.remove(event.DomainFilter);
            }

            //Enable or disable the delete option when there are userDomainFiltersSelected items
            updateEditAction();
        }

        public void updateEditAction() {
            if (viewSelected == 0 && userDomainFiltersSelected.size() > 0)
                deleteAction.setEnabled(true);
            else
                deleteAction.setEnabled(false);
        }

        public void deleteCheckedItems() {
            for (DomainFilter DomainFilter : userDomainFiltersSelected) {
                db.deleteDomainFilter(DomainFilter);
                updateFiltersList();
                userDomainFiltersAdapter.notifyDataSetChanged();
            }
            inValidateSelections();
        }
    }

    class UserDomainFiltersRowHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        private TextView contentLabel;
        private CheckBox checkBox;

        private DomainFilter domainFilter;

        public UserDomainFiltersRowHolder(View itemView) {
            super(itemView);

            itemView.setOnClickListener(this);
            contentLabel = ButterKnife.findById(itemView, R.id.filter_content);
            checkBox = ButterKnife.findById(itemView, R.id.checkbox);
            checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    BUS.post(new UserDomainFilterCheckStateChangedEvent(domainFilter, isChecked));
                }
            });
        }

        public void setDomainFilter(DomainFilter DomainFilter) {
            this.domainFilter = DomainFilter;
            contentLabel.setText(DomainFilter.getContent());
        }

        public void setChecked(boolean checked) {
            checkBox.setChecked(checked);
        }

        @Override
        public void onClick(View view) {

            View dialogView = getLayoutInflater().inflate(R.layout.user_domain_filter_dialog, null);
            final EditText input = (EditText) dialogView.findViewById(R.id.filter_content);
            input.append(domainFilter.getContent());
            final CheckBox isWildcard = (CheckBox) dialogView.findViewById(R.id.is_wildcard);
            isWildcard.setChecked(domainFilter.isWildcard());
            AlertDialog.Builder builder = new AlertDialog.Builder(itemView.getContext())
                    .setTitle("Edit DomainFilter").setView(dialogView)
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            domainFilter.setContent(input.getText().toString());
                            domainFilter.setIsWildcard(isWildcard.isChecked());
                            db.updateDomainFilter(domainFilter);
                            updateFiltersList();
                            userDomainFiltersAdapter.notifyDataSetChanged();

                        }
                    }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            // Canceled.
                        }
                    });

            final AlertDialog dialog = builder.create();

            input.addTextChangedListener(new TextWatcher() {
                @Override
                public void afterTextChanged(Editable s) {
                    if (Patterns.DOMAIN_NAME.matcher(s).matches()) {
                        dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
                    } else
                        dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
                }

                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                }
            });

            dialog.show();

        }
    }

    public class UserDomainFilterCheckStateChangedEvent {
        public boolean isChecked;
        public DomainFilter DomainFilter;

        public UserDomainFilterCheckStateChangedEvent(DomainFilter DomainFilter, boolean isChecked) {
            this.DomainFilter = DomainFilter;
            this.isChecked = isChecked;
        }
    }

    /*
    -------------------------------------------
    Domain Filters imported from remote file
    -------------------------------------------
     */

    private class ExternalDomainFiltersAdapter extends RecyclerView.Adapter<ExternalDomainFiltersRowHolder> {

        @Override
        public ExternalDomainFiltersRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new ExternalDomainFiltersRowHolder(
                    getLayoutInflater().inflate(R.layout.filter_row, parent, false));
        }

        @Override
        public void onBindViewHolder(ExternalDomainFiltersRowHolder holder, int position) {

            Log.e("TAG", externalFilters.toString());

            FilterFile filterFile = externalFilters.get(position);

            Log.e("TAG", "---->" + filterFile);

            holder.setFilterFile(filterFile);
            holder.setChecked(externalFilterFilesSelected.contains(filterFile));
        }

        @Override
        public int getItemCount() {
            return externalFilters.size();
        }

        @Subscribe
        public void onExternalDomainFilterCheckStateChangedEvent(ExternalDomainFilterCheckStateChangedEvent event) {
            if (event.isChecked) {
                externalFilterFilesSelected.add(event.filterFile);
            } else {
                externalFilterFilesSelected.remove(event.filterFile);
            }
            updateEditAction();
        }

        public void updateEditAction() {
            if (viewSelected == 1 && externalFilterFilesSelected.size() > 0)
                deleteAction.setEnabled(true);
            else
                deleteAction.setEnabled(false);
        }

        public void deleteCheckedItems() {
            for (FilterFile filterFile : externalFilterFilesSelected) {
                db.deleteDomainFilterFile(filterFile);
                updateFiltersList();
                externalDomainFiltersAdapter.notifyDataSetChanged();
            }
            inValidateSelections();
        }
    }

    class ExternalDomainFiltersRowHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        private TextView contentLabel;
        private CheckBox checkBox;

        private FilterFile filterFile;

        public ExternalDomainFiltersRowHolder(View itemView) {
            super(itemView);

            itemView.setOnClickListener(this);
            contentLabel = ButterKnife.findById(itemView, R.id.filter_content);
            checkBox = ButterKnife.findById(itemView, R.id.checkbox);
            checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    BUS.post(new ExternalDomainFilterCheckStateChangedEvent(filterFile, isChecked));
                }
            });
        }

        public void setFilterFile(FilterFile filterFile) {
            this.filterFile = filterFile;
            contentLabel.setText(filterFile.getTitle());
        }

        public void setChecked(boolean checked) {
            checkBox.setChecked(checked);
        }

        @Override
        public void onClick(View view) {
            final String importUrl = filterFile.getSource();
            new AlertDialog.Builder(itemView.getContext()).setTitle("FilterFile actions")
                    .setMessage("URL: " + importUrl)
                    .setPositiveButton("Update", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            db.deleteDomainFilterFile(importUrl);
                            importExternalFilters(importUrl);
                            updateFiltersList();
                            externalDomainFiltersAdapter.notifyDataSetChanged();
                            inValidateSelections();
                        }
                    }).setNeutralButton("Preview", new DialogInterface.OnClickListener() { //Scrollable dialog preview
                        public void onClick(DialogInterface dialog, int whichButton) {

                            new AsyncTask<Void, Void, Spanned>() {
                                ProgressDialog dialog;

                                @Override
                                protected void onPreExecute() {
                                    dialog = ProgressDialog.show(DomainFiltersActivity.this, null,
                                            "Generating filters list...");
                                    dialog.setCancelable(false);
                                }

                                @Override
                                protected Spanned doInBackground(Void... params) {
                                    return Html.fromHtml(
                                            TextUtils.join("<br />", db.getAllDomainFiltersForSource(importUrl)));
                                }

                                @Override
                                protected void onPostExecute(Spanned filters) {
                                    dialog.dismiss();
                                    final AlertDialog.Builder prevDialog = new AlertDialog.Builder(
                                            itemView.getContext());
                                    View rootView = getLayoutInflater().inflate(R.layout.dialog_scrollable_text,
                                            null);
                                    prevDialog.setView(rootView);
                                    final AlertDialog alertDialog = prevDialog.create();
                                    ((TextView) rootView.findViewById(R.id.tv_scrollable_text)).setText(filters);
                                    ((TextView) rootView.findViewById(R.id.tv_scrollable_text_dialog_title))
                                            .setText("Entries");
                                    rootView.findViewById(R.id.btn_close)
                                            .setOnClickListener(new View.OnClickListener() {
                                                @Override
                                                public void onClick(View v) {
                                                    alertDialog.dismiss();
                                                }
                                            });
                                    alertDialog.show();
                                }
                            }.execute();
                        }
                    }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            // Canceled.
                        }
                    }).show();

        }
    }

    public class ExternalDomainFilterCheckStateChangedEvent {
        public boolean isChecked;
        public FilterFile filterFile;

        public ExternalDomainFilterCheckStateChangedEvent(FilterFile filterFile, boolean isChecked) {
            this.filterFile = filterFile;
            this.isChecked = isChecked;
        }
    }
}