auto import from //depot/cupcake/@135843
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;
+  }
+
+}