Code drop from //branches/cupcake/...@124589
diff --git a/src/com/android/browser/GearsSettingsDialog.java b/src/com/android/browser/GearsSettingsDialog.java
new file mode 100644
index 0000000..dead4f2
--- /dev/null
+++ b/src/com/android/browser/GearsSettingsDialog.java
@@ -0,0 +1,500 @@
+/*
+ * 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.content.Context;
+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.Button;
+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.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;
+
+ // 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;
+
+
+ public GearsSettingsDialog(Activity activity,
+ Handler handler,
+ String arguments) {
+ super (activity, handler, arguments);
+ }
+
+ public void setup() {
+ // First let's add the permissions' resources
+ LOCAL_STORAGE.setResources(R.id.local_storage_choice,
+ R.id.local_storage_allowed,
+ R.id.local_storage_denied);
+
+ LOCATION_DATA.setResources(R.id.location_data_choice,
+ R.id.location_data_allowed,
+ R.id.location_data_denied);
+
+ // add the permissions to the list of permissions.
+ mPermissions = new Vector<PermissionType>();
+ mPermissions.add(LOCAL_STORAGE);
+ mPermissions.add(LOCATION_DATA);
+ OriginPermissions.setListener(this);
+
+
+ inflate(R.layout.gears_dialog_settings, R.id.panel_content);
+ setupDialog();
+ setupButtons(0,
+ R.string.settings_button_allow,
+ R.string.settings_button_deny);
+
+ // by default disable the allow button (it will get enabled if
+ // something is changed by the user)
+ View buttonView = findViewById(R.id.button_allow);
+ if (buttonView != null) {
+ Button button = (Button) buttonView;
+ button.setEnabled(false);
+ }
+
+ View gearsVersionView = findViewById(R.id.gears_version);
+ if (gearsVersionView != null) {
+ TextView gearsVersion = (TextView) gearsVersionView;
+ gearsVersion.setText(mGearsVersion);
+ }
+
+ // 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;
+ list.setAdapter(new SettingsAdapter(mActivity, mSitesPermissions));
+ }
+ if (mDebug) {
+ printPermissions();
+ }
+ }
+
+ public void setupDialog() {
+ View dialogTitleView = findViewById(R.id.dialog_title);
+ if (dialogTitleView != null) {
+ TextView dialogTitle = (TextView) dialogTitleView;
+ dialogTitle.setText(R.string.settings_title);
+ dialogTitle.setVisibility(View.VISIBLE);
+ }
+ View dialogSubtitleView = findViewById(R.id.dialog_subtitle);
+ if (dialogSubtitleView != null) {
+ TextView dialogSubtitle = (TextView) dialogSubtitleView;
+ dialogSubtitle.setText(R.string.settings_message);
+ dialogSubtitle.setVisibility(View.VISIBLE);
+ }
+ View iconView = findViewById(R.id.icon);
+ if (iconView != null) {
+ ImageView icon = (ImageView) iconView;
+ icon.setImageResource(R.drawable.gears_icon_32x32);
+ }
+ }
+
+ /**
+ * GearsPermissions.PermissionsChangesListener delegate
+ */
+ public boolean setPermission(PermissionType type, int perm) {
+ if (mChanges == false) {
+ signalChanges();
+ }
+ return mChanges;
+ }
+
+ /**
+ * Controller class for binding the model (OriginPermissions) with
+ * the UI.
+ */
+ class PermissionController {
+ final static int ALLOWED_BUTTON = 1;
+ final static int DENIED_BUTTON = 2;
+ private int mButtonType;
+ private PermissionType mPermissionType;
+ private OriginPermissions mPermissions;
+
+ PermissionController(PermissionType permissionType, int buttonType,
+ OriginPermissions permissions) {
+ mPermissionType = permissionType;
+ mButtonType = buttonType;
+ mPermissions = permissions;
+ }
+
+ public boolean isChecked() {
+ boolean checked = false;
+
+ switch (mButtonType) {
+ case ALLOWED_BUTTON:
+ if (mPermissions.getPermission(mPermissionType) ==
+ PermissionType.PERMISSION_ALLOWED) {
+ checked = true;
+ } break;
+ case DENIED_BUTTON:
+ if (mPermissions.getPermission(mPermissionType) ==
+ PermissionType.PERMISSION_DENIED) {
+ checked = true;
+ }
+ }
+ return checked;
+ }
+
+ public String print() {
+ return printType() + " for " + mPermissions.getOrigin();
+ }
+
+ private String printType() {
+ switch (mButtonType) {
+ case ALLOWED_BUTTON:
+ return "ALLOWED_BUTTON";
+ case DENIED_BUTTON:
+ return "DENIED_BUTTON";
+ }
+ return "UNKNOWN BUTTON";
+ }
+
+ public void changed(boolean isChecked) {
+ if (isChecked == isChecked()) {
+ return; // already set
+ }
+
+ switch (mButtonType) {
+ case ALLOWED_BUTTON:
+ mPermissions.setPermission(mPermissionType,
+ PermissionType.PERMISSION_ALLOWED);
+ break;
+ case DENIED_BUTTON:
+ mPermissions.setPermission(mPermissionType,
+ PermissionType.PERMISSION_DENIED);
+ break;
+ }
+ }
+ }
+
+
+
+ /**
+ * Adapter class for the list view in the settings dialog
+ *
+ * Every row in the settings dialog display the permissions
+ * for a given origin. For every type of permission
+ * (location, local data...) there is two radio buttons to
+ * authorize or deny the permission.
+ * A remove button is also present to let the user remove
+ * all the authorization of an origin in one step.
+ */
+ class SettingsAdapter extends ArrayAdapter {
+ private Activity mContext;
+ private List mItems;
+
+ SettingsAdapter(Activity context, List items) {
+ super(context, R.layout.gears_dialog_settings_row, items);
+ mContext = context;
+ mItems = items;
+ }
+
+ /*
+ * setup the necessary listeners for the radiobuttons
+ * When the buttons are clicked the permissions change.
+ */
+ private void createAndSetButtonListener(View buttonView,
+ OriginPermissions perms, PermissionType permissionType,
+ int buttonType) {
+ if (buttonView == null) {
+ return;
+ }
+ RadioButton button = (RadioButton) buttonView;
+
+ button.setOnCheckedChangeListener(null);
+ PermissionController p = new PermissionController(permissionType,
+ buttonType, perms);
+ button.setTag(p);
+
+ CompoundButton.OnCheckedChangeListener listener =
+ new CompoundButton.OnCheckedChangeListener() {
+ public void onCheckedChanged(CompoundButton buttonView,
+ boolean isChecked) {
+ PermissionController perm = (PermissionController)buttonView.getTag();
+ perm.changed(isChecked);
+ }
+ };
+
+ button.setOnCheckedChangeListener(listener);
+
+ if (p.isChecked() != button.isChecked()) {
+ button.setChecked(p.isChecked());
+ }
+ }
+
+ /*
+ * setup the remove button for an origin: each row has a global
+ * remove button in addition to the radio buttons controlling the
+ * permissions.
+ */
+ private void setRemoveButton(Button button, OriginPermissions perms) {
+ Button.OnClickListener listener = new Button.OnClickListener() {
+ public void onClick(View buttonView) {
+ if (mChanges == false) {
+ signalChanges();
+ }
+ OriginPermissions perm = (OriginPermissions) buttonView.getTag();
+ perm.setPermission(LOCAL_STORAGE, PermissionType.PERMISSION_NOT_SET);
+ perm.setPermission(LOCATION_DATA, PermissionType.PERMISSION_NOT_SET);
+ mSitesPermissions.remove(perm);
+
+ View view = findViewById(R.id.sites_list);
+ if (view != null) {
+ ListView listView = (ListView) view;
+ ListAdapter listAdapter = listView.getAdapter();
+ if (listAdapter != null) {
+ SettingsAdapter settingsAdapter = (SettingsAdapter) listAdapter;
+ settingsAdapter.notifyDataSetChanged();
+ }
+ }
+ }
+ };
+ button.setTag(perms);
+ button.setOnClickListener(listener);
+ }
+
+ 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_dialog_settings_row, null);
+ }
+
+ OriginPermissions perms = (OriginPermissions) mItems.get(position);
+
+ View nameView = row.findViewById(R.id.origin_name);
+ if (nameView != null) {
+ TextView originName = (TextView) nameView;
+ originName.setText(perms.getOrigin());
+ }
+
+ View removeButtonView = row.findViewById(R.id.origin_remove);
+ if (removeButtonView != null) {
+ Button removeButton = (Button) removeButtonView;
+ setRemoveButton(removeButton, perms);
+ }
+
+ for (int i = 0; i < mPermissions.size(); i++) {
+ PermissionType type = mPermissions.get(i);
+ int rowRsc = type.getRowRsc();
+ int allowedButtonRsc = type.getAllowedButtonRsc();
+ int deniedButtonRsc = type.getDeniedButtonRsc();
+
+ View rowView = row.findViewById(rowRsc);
+ if (rowView != null) {
+ int perm = perms.getPermission(type);
+ if (perm != PermissionType.PERMISSION_NOT_SET) {
+ createAndSetButtonListener(row.findViewById(allowedButtonRsc),
+ perms, type, PermissionController.ALLOWED_BUTTON);
+ createAndSetButtonListener(row.findViewById(deniedButtonRsc),
+ perms, type, PermissionController.DENIED_BUTTON);
+ rowView.setVisibility(View.VISIBLE);
+ } else {
+ rowView.setVisibility(View.GONE);
+ }
+ }
+ }
+
+ return row;
+ }
+ }
+
+ /**
+ * 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();
+ }
+ }
+
+ /**
+ * Utility method used by the settings dialog, signaling
+ * the user the settings have been modified.
+ * We reflect this by enabling the Allow button (disabled
+ * by default).
+ */
+ public void signalChanges() {
+ View view = findViewById(R.id.button_allow);
+ if (view != null) {
+ Button button = (Button) view;
+ button.setEnabled(true);
+ }
+ mChanges = true;
+ }
+
+ /**
+ * 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 = null;
+ switch (closingType) {
+ case ALWAYS_DENY:
+ ret = "{\"allow\": false }";
+ break;
+ case ALLOW:
+ ret = computeDiff(true);
+ break;
+ case DENY:
+ ret = computeDiff(false);
+ break;
+ }
+
+ if (mDebug) {
+ printPermissions();
+ }
+
+ return ret;
+ }
+
+}