diff options
Diffstat (limited to 'src/com/android/browser/GearsSettingsDialog.java')
-rw-r--r-- | src/com/android/browser/GearsSettingsDialog.java | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/src/com/android/browser/GearsSettingsDialog.java b/src/com/android/browser/GearsSettingsDialog.java new file mode 100644 index 0000000..5ea2342 --- /dev/null +++ b/src/com/android/browser/GearsSettingsDialog.java @@ -0,0 +1,460 @@ +/* + * 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; + } + +} |