com.android.browser.GearsSettingsDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.android.browser.GearsSettingsDialog.java

Source

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.browser;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.TextView;

import com.android.browser.GearsPermissions.OriginPermissions;
import com.android.browser.GearsPermissions.Permission;
import com.android.browser.GearsPermissions.PermissionsChangesListener;
import com.android.browser.GearsPermissions.PermissionType;

import java.util.Vector;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * Gears Settings dialog
 */
class GearsSettingsDialog extends GearsBaseDialog implements PermissionsChangesListener {

    private static final String TAG = "GearsPermissionsDialog";
    private Vector<OriginPermissions> mSitesPermissions = null;
    private Vector<OriginPermissions> mOriginalPermissions = null;
    private Vector<OriginPermissions> mCurrentPermissions = null;

    private Vector<PermissionType> mPermissions;
    private static final int CONFIRMATION_REMOVE_DIALOG = 1;

    // We declare the permissions globally to simplify the code
    private final PermissionType LOCAL_STORAGE = new PermissionType(LOCAL_STORAGE_STRING);
    private final PermissionType LOCATION_DATA = new PermissionType(LOCATION_DATA_STRING);

    private boolean mChanges = false;

    SettingsAdapter mListAdapter;

    public GearsSettingsDialog(Activity activity, Handler handler, String arguments) {
        super(activity, handler, arguments);
        activity.setContentView(R.layout.gears_settings);
    }

    public void setup() {
        // First let's add the permissions' resources
        LOCAL_STORAGE.setResources(R.string.settings_storage_title, R.string.settings_storage_subtitle_on,
                R.string.settings_storage_subtitle_off);
        LOCATION_DATA.setResources(R.string.settings_location_title, R.string.settings_location_subtitle_on,
                R.string.settings_location_subtitle_off);
        // add the permissions to the list of permissions.
        mPermissions = new Vector<PermissionType>();
        mPermissions.add(LOCAL_STORAGE);
        mPermissions.add(LOCATION_DATA);
        OriginPermissions.setListener(this);

        setupDialog();

        // We manage the permissions using three vectors, mSitesPermissions,
        // mOriginalPermissions and mCurrentPermissions.
        // The dialog's arguments are parsed and a list of permissions is
        // generated and stored in those three vectors.
        // mOriginalPermissions is a separate copy and will not be modified;
        // mSitesPermissions contains the current permissions _only_ --
        // if an origin is removed, it is also removed from mSitesPermissions.
        // Finally, mCurrentPermissions contains the current permissions and
        // is a clone of mSitesPermissions, but removed sites aren't removed,
        // their permissions are simply set to PERMISSION_NOT_SET. This
        // allows us to easily generate the final difference between the
        // original permissions and the final permissions, while directly
        // using mSitesPermissions for the listView adapter (SettingsAdapter).

        mSitesPermissions = new Vector<OriginPermissions>();
        mOriginalPermissions = new Vector<OriginPermissions>();

        try {
            JSONObject json = new JSONObject(mDialogArguments);
            if (json.has("permissions")) {
                JSONArray jsonArray = json.getJSONArray("permissions");
                for (int i = 0; i < jsonArray.length(); i++) {
                    JSONObject infos = jsonArray.getJSONObject(i);
                    String name = null;
                    int localStorage = PermissionType.PERMISSION_NOT_SET;
                    int locationData = PermissionType.PERMISSION_NOT_SET;
                    if (infos.has("name")) {
                        name = infos.getString("name");
                    }
                    if (infos.has(LOCAL_STORAGE_STRING)) {
                        JSONObject perm = infos.getJSONObject(LOCAL_STORAGE_STRING);
                        if (perm.has("permissionState")) {
                            localStorage = perm.getInt("permissionState");
                        }
                    }
                    if (infos.has(LOCATION_DATA_STRING)) {
                        JSONObject perm = infos.getJSONObject(LOCATION_DATA_STRING);
                        if (perm.has("permissionState")) {
                            locationData = perm.getInt("permissionState");
                        }
                    }
                    OriginPermissions perms = new OriginPermissions(name);
                    perms.setPermission(LOCAL_STORAGE, localStorage);
                    perms.setPermission(LOCATION_DATA, locationData);

                    mSitesPermissions.add(perms);
                    mOriginalPermissions.add(new OriginPermissions(perms));
                }
            }
        } catch (JSONException e) {
            Log.e(TAG, "JSON exception ", e);
        }
        mCurrentPermissions = (Vector<OriginPermissions>) mSitesPermissions.clone();

        View listView = findViewById(R.id.sites_list);
        if (listView != null) {
            ListView list = (ListView) listView;
            mListAdapter = new SettingsAdapter(mActivity, mSitesPermissions);
            list.setAdapter(mListAdapter);
            list.setScrollBarStyle(android.view.View.SCROLLBARS_OUTSIDE_INSET);
            list.setOnItemClickListener(mListAdapter);
        }
        if (mDebug) {
            printPermissions();
        }
    }

    private void setMainTitle() {
        String windowTitle = mActivity.getString(R.string.pref_extras_gears_settings);
        mActivity.setTitle(windowTitle);
    }

    public void setupDialog() {
        setMainTitle();
    }

    /**
     * GearsPermissions.PermissionsChangesListener delegate
     */
    public boolean setPermission(PermissionType type, int perm) {
        if (mChanges == false) {
            mChanges = true;
        }
        return mChanges;
    }

    public boolean handleBackButton() {
        return mListAdapter.backButtonPressed();
    }

    /**
     * We use this to create a confirmation dialog when the user
     * clicks on "remove this site from gears"
     */
    public Dialog onCreateDialog(int id) {
        return new AlertDialog.Builder(mActivity).setTitle(R.string.settings_confirmation_remove_title)
                .setMessage(R.string.settings_confirmation_remove)
                .setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
                    public void onClick(DialogInterface dlg, int which) {
                        mListAdapter.removeCurrentSite();
                    }
                }).setNegativeButton(android.R.string.cancel, null).setIcon(android.R.drawable.ic_dialog_alert)
                .create();
    }

    /**
     * Adapter class for the list view in the settings dialog
     *
     * We first display a list of all the origins (sites), or
     * a message saying that no permission is set if the list is empty.
     * When the user click on one of the origin, we then display
     * the list of the permissions existing for that origin.
     * Each permission can be either allowed or denied by clicking
     * on the checkbox.
     * The last row is a special case, allowing to remove the entire origin.
     */
    class SettingsAdapter extends BaseAdapter implements AdapterView.OnItemClickListener {
        private Activity mContext;
        private List mItems;
        private OriginPermissions mCurrentSite;
        private Vector mCurrentPermissions;
        private int MAX_ROW_HEIGHT = 64;

        SettingsAdapter(Activity context, List items) {
            mContext = context;
            mItems = items;
            mCurrentSite = null;
        }

        public int getCount() {
            if (mCurrentSite == null) {
                int size = mItems.size();
                if (size == 0) {
                    return 1;
                } else {
                    return size;
                }
            }
            return mCurrentPermissions.size() + 1;
        }

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

        private String shortName(String url) {
            // We remove the http and https prefix
            if (url.startsWith("http://")) {
                return url.substring(7);
            }
            if (url.startsWith("https://")) {
                return url.substring(8);
            }
            return url;
        }

        public Object getItem(int position) {
            if (mCurrentSite == null) {
                if (mItems.size() == 0) {
                    return null;
                } else {
                    return mItems.get(position);
                }
            }
            return mCurrentPermissions.get(position);
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            View row = convertView;
            if (row == null) { // no cached view, we create one
                LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                row = inflater.inflate(R.layout.gears_settings_row, null);
            }
            row.setMinimumHeight(MAX_ROW_HEIGHT);

            if (mCurrentSite == null) {
                if (mItems.size() == 0) {
                    hideView(row, R.id.title);
                    hideView(row, R.id.subtitle);
                    hideView(row, R.id.checkbox);
                    hideView(row, R.id.icon);
                    setText(row, R.id.info, R.string.settings_empty);
                } else {
                    hideView(row, R.id.subtitle);
                    hideView(row, R.id.info);
                    hideView(row, R.id.checkbox);
                    OriginPermissions perms = (OriginPermissions) mItems.get(position);
                    setText(row, R.id.title, shortName(perms.getOrigin()));
                    showView(row, R.id.icon);
                }
            } else {
                if (position == getCount() - 1) {
                    // last position: "remove this site from gears"
                    hideView(row, R.id.subtitle);
                    hideView(row, R.id.info);
                    hideView(row, R.id.checkbox);
                    hideView(row, R.id.icon);
                    setText(row, R.id.title, R.string.settings_remove_site);
                } else {
                    hideView(row, R.id.info);
                    hideView(row, R.id.icon);
                    showView(row, R.id.checkbox);

                    PermissionType type = (PermissionType) mCurrentPermissions.get(position);
                    setText(row, R.id.title, type.getTitleRsc());

                    View checkboxView = row.findViewById(R.id.checkbox);
                    if (checkboxView != null) {
                        CheckBox checkbox = (CheckBox) checkboxView;
                        int perm = mCurrentSite.getPermission(type);
                        if (perm == PermissionType.PERMISSION_DENIED) {
                            setText(row, R.id.subtitle, type.getSubtitleOffRsc());
                            checkbox.setChecked(false);
                        } else {
                            setText(row, R.id.subtitle, type.getSubtitleOnRsc());
                            checkbox.setChecked(true);
                        }
                    }
                }
            }
            return row;
        }

        public void removeCurrentSite() {
            mCurrentSite.setPermission(LOCAL_STORAGE, PermissionType.PERMISSION_NOT_SET);
            mCurrentSite.setPermission(LOCATION_DATA, PermissionType.PERMISSION_NOT_SET);
            mSitesPermissions.remove(mCurrentSite);
            mCurrentSite = null;
            setMainTitle();
            notifyDataSetChanged();
        }

        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if (mItems.size() == 0) {
                return;
            }
            if (mCurrentSite == null) {
                mCurrentSite = (OriginPermissions) mItems.get(position);
                mCurrentPermissions = new Vector();
                for (int i = 0; i < mPermissions.size(); i++) {
                    PermissionType type = mPermissions.get(i);
                    int perm = mCurrentSite.getPermission(type);
                    if (perm != PermissionType.PERMISSION_NOT_SET) {
                        mCurrentPermissions.add(type);
                    }
                }
                mContext.setTitle(shortName(mCurrentSite.getOrigin()));
            } else {
                if (position == getCount() - 1) { // last item (remove site)
                    // Ask the user to confirm
                    // If yes, removeCurrentSite() will be called via the dialog callback.
                    mActivity.showDialog(CONFIRMATION_REMOVE_DIALOG);
                } else {
                    PermissionType type = (PermissionType) mCurrentPermissions.get(position);
                    if (mCurrentSite.getPermission(type) == PermissionType.PERMISSION_ALLOWED) {
                        mCurrentSite.setPermission(type, PermissionType.PERMISSION_DENIED);
                    } else {
                        mCurrentSite.setPermission(type, PermissionType.PERMISSION_ALLOWED);
                    }
                }
            }
            notifyDataSetChanged();
        }

        public boolean backButtonPressed() {
            if (mCurrentSite != null) { // we intercept the back button
                mCurrentSite = null;
                setMainTitle();
                notifyDataSetChanged();
                return true;
            }
            return false;
        }

    }

    /**
     * Utility method used in debug mode to print the list of
     * permissions (original values and current values).
     */
    public void printPermissions() {
        Log.v(TAG, "Original Permissions: ");
        for (int i = 0; i < mOriginalPermissions.size(); i++) {
            OriginPermissions p = mOriginalPermissions.get(i);
            p.print();
        }
        Log.v(TAG, "Current Permissions: ");
        for (int i = 0; i < mSitesPermissions.size(); i++) {
            OriginPermissions p = mSitesPermissions.get(i);
            p.print();
        }
    }

    /**
     * Computes the difference between the original permissions and the
     * current ones. Returns a json-formatted string.
     * It is used by the Settings dialog.
     */
    public String computeDiff(boolean modif) {
        String ret = null;
        try {
            JSONObject results = new JSONObject();
            JSONArray permissions = new JSONArray();

            for (int i = 0; modif && i < mOriginalPermissions.size(); i++) {
                OriginPermissions original = mOriginalPermissions.get(i);
                OriginPermissions current = mCurrentPermissions.get(i);
                JSONObject permission = new JSONObject();
                boolean modifications = false;

                for (int j = 0; j < mPermissions.size(); j++) {
                    PermissionType type = mPermissions.get(j);

                    if (current.getPermission(type) != original.getPermission(type)) {
                        JSONObject state = new JSONObject();
                        state.put("permissionState", current.getPermission(type));
                        permission.put(type.getName(), state);
                        modifications = true;
                    }
                }

                if (modifications) {
                    permission.put("name", current.getOrigin());
                    permissions.put(permission);
                }
            }
            results.put("modifiedOrigins", permissions);
            ret = results.toString();
        } catch (JSONException e) {
            Log.e(TAG, "JSON exception ", e);
        }
        return ret;
    }

    public String closeDialog(int closingType) {
        String ret = computeDiff(mChanges);

        if (mDebug) {
            printPermissions();
        }

        return ret;
    }

}