auto import from //branches/cupcake/...@131421
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index b6942d2..d8fd3fa 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -120,6 +120,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import android.widget.Toast;
+import android.widget.ZoomRingController;
 
 import com.google.android.googleapps.IGoogleLoginService;
 import com.google.android.googlelogin.GoogleLoginServiceConstants;
@@ -131,6 +132,7 @@
 import java.io.InputStream;
 import java.io.IOException;
 import java.net.MalformedURLException;
+import java.net.URI;
 import java.net.URL;
 import java.net.URLEncoder;
 import java.text.ParseException;
@@ -743,6 +745,9 @@
                     }
                 }
             };
+            
+        // Show a tutorial for the new zoom interaction (the method ensure we only show it once)
+        ZoomRingController.showZoomTutorialOnce(this);
     }
 
     @Override
@@ -3389,10 +3394,44 @@
             return;
         }
 
+        // java.net.URI is a lot stricter than KURL so we have to undo
+        // KURL's percent-encoding and redo the encoding using java.net.URI.
+        URI uri = null;
+        try {
+            // Undo the percent-encoding that KURL may have done.
+            String newUrl = new String(URLUtil.decode(url.getBytes()));
+            // Parse the url into pieces
+            WebAddress w = new WebAddress(newUrl);
+            String frag = null;
+            String query = null;
+            String path = w.mPath;
+            // Break the path into path, query, and fragment
+            if (path.length() > 0) {
+                // Strip the fragment
+                int idx = path.lastIndexOf('#');
+                if (idx != -1) {
+                    frag = path.substring(idx + 1);
+                    path = path.substring(0, idx);
+                }
+                idx = path.lastIndexOf('?');
+                if (idx != -1) {
+                    query = path.substring(idx + 1);
+                    path = path.substring(0, idx);
+                }
+            }
+            uri = new URI(w.mScheme, w.mAuthInfo, w.mHost, w.mPort, path,
+                    query, frag);
+        } catch (Exception e) {
+            Log.e(LOGTAG, "Could not parse url for download: " + url, e);
+            return;
+        }
+
+        // XXX: Have to use the old url since the cookies were stored using the
+        // old percent-encoded url.
         String cookies = CookieManager.getInstance().getCookie(url);
 
         ContentValues values = new ContentValues();
-        values.put(Downloads.URI, url);
+        values.put(Downloads.URI, uri.toString());
         values.put(Downloads.COOKIE_DATA, cookies);
         values.put(Downloads.USER_AGENT, userAgent);
         values.put(Downloads.NOTIFICATION_PACKAGE,
@@ -3402,7 +3441,7 @@
         values.put(Downloads.VISIBILITY, Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
         values.put(Downloads.MIMETYPE, mimetype);
         values.put(Downloads.FILENAME_HINT, filename);
-        values.put(Downloads.DESCRIPTION, Uri.parse(url).getHost());
+        values.put(Downloads.DESCRIPTION, uri.getHost());
         if (contentLength > 0) {
             values.put(Downloads.TOTAL_BYTES, contentLength);
         }
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 5038a4e..06ccf01 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -334,6 +334,8 @@
     
     public void toggleDebugSettings() {
         showDebugSettings = !showDebugSettings;
+        navDump = showDebugSettings;
+        update();
     }
 
     /**
diff --git a/src/com/android/browser/FakeWebView.java b/src/com/android/browser/FakeWebView.java
index 7997672..633b799 100644
--- a/src/com/android/browser/FakeWebView.java
+++ b/src/com/android/browser/FakeWebView.java
@@ -34,10 +34,12 @@
  */
 public class FakeWebView extends ImageView {
     private TabControl.Tab mTab;
+    private Picture        mPicture;
     private boolean        mUsesResource;
 
     private class Listener implements WebView.PictureListener {
         public void onNewPicture(WebView view, Picture p) {
+            FakeWebView.this.mPicture = p;
             FakeWebView.this.invalidate();
         }
     };
@@ -69,13 +71,12 @@
             if (mTab != null) {
                 final WebView w = mTab.getTopWindow();
                 if (w != null) {
-                    Picture p = w.capturePicture();
-                    if (p != null) {
+                    if (mPicture != null) {
                         canvas.save();
                         float scale = getWidth() * w.getScale() / w.getWidth();
                         canvas.scale(scale, scale);
                         canvas.translate(-w.getScrollX(), -w.getScrollY());
-                        canvas.drawPicture(p);
+                        canvas.drawPicture(mPicture);
                         canvas.restore();
                     }
                 }
@@ -99,10 +100,12 @@
         mTab = t;
         if (t != null && t.getWebView() != null) {
             Listener l = new Listener();
-            t.getWebView().setPictureListener(l);
             if (t.getSubWebView() != null) {
                 t.getSubWebView().setPictureListener(l);
+            } else {
+                t.getWebView().setPictureListener(l);
             }
+            mPicture = mTab.getTopWindow().capturePicture();
         }
     }
 }
diff --git a/src/com/android/browser/GearsBaseDialog.java b/src/com/android/browser/GearsBaseDialog.java
index afd0dd2..3379537 100644
--- a/src/com/android/browser/GearsBaseDialog.java
+++ b/src/com/android/browser/GearsBaseDialog.java
@@ -17,6 +17,7 @@
 package com.android.browser;
 
 import android.app.Activity;
+import android.app.Dialog;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -191,14 +192,14 @@
                   public void onClick(View v) {
                     mHandler.sendEmptyMessage(ALWAYS_DENY);
                   }
-                }, true, false);
+                });
 
     setupButton(R.id.button_allow, allowRsc,
                 new Button.OnClickListener() {
                   public void onClick(View v) {
                     mHandler.sendEmptyMessage(ALLOW);
                   }
-                }, false, true);
+                });
 
     setupButton(R.id.button_deny, denyRsc,
                 new Button.OnClickListener() {
@@ -249,6 +250,67 @@
   }
 
   /**
+   * Utility method to hide a view.
+   */
+  void hideView(View v, int rsc) {
+    if (rsc == 0) {
+      return;
+    }
+    View view = v.findViewById(rsc);
+    if (view != null) {
+      view.setVisibility(View.GONE);
+    }
+  }
+
+  /**
+   * Utility method to show a view.
+   */
+  void showView(View v, int rsc) {
+    if (rsc == 0) {
+      return;
+    }
+    View view = v.findViewById(rsc);
+    if (view != null) {
+      view.setVisibility(View.VISIBLE);
+    }
+  }
+
+  /**
+   * Utility method to set a text.
+   */
+  void setText(View v, int rsc, CharSequence text) {
+    if (rsc == 0) {
+      return;
+    }
+    View view = v.findViewById(rsc);
+    if (view != null) {
+      TextView textView = (TextView) view;
+      textView.setText(text);
+      textView.setVisibility(View.VISIBLE);
+    }
+  }
+
+  /**
+   * Utility method to set a text.
+   */
+  void setText(View v, int rsc, int txtRsc) {
+    if (rsc == 0) {
+      return;
+    }
+    View view = v.findViewById(rsc);
+    if (view != null) {
+      TextView textView = (TextView) view;
+      if (txtRsc == 0) {
+        textView.setVisibility(View.GONE);
+      } else {
+        CharSequence text = getString(txtRsc);
+        textView.setText(text);
+        textView.setVisibility(View.VISIBLE);
+      }
+    }
+  }
+
+  /**
    * Utility class to download an icon in the background.
    * Once done ask the UI thread to update the icon.
    */
@@ -360,7 +422,7 @@
    */
   public void setupDialog(TextView message, ImageView icon) {
     message.setText(R.string.unrecognized_dialog_message);
-    icon.setImageResource(R.drawable.gears_icon_48x48);
+    icon.setImageResource(R.drawable.ic_dialog_menu_generic);
     message.setVisibility(View.VISIBLE);
   }
 
@@ -373,4 +435,29 @@
     setupDialog();
   }
 
+  /**
+   * Method called when the back button is pressed,
+   * allowing the dialog to intercept the default behaviour.
+   */
+  public boolean handleBackButton() {
+    return false;
+  }
+
+  /**
+   * Returns the resource string of the notification displayed
+   * after the dialog. By default, does not return one.
+   */
+  public int notification() {
+    return 0;
+  }
+
+  /**
+   * If a secondary dialog (e.g. a confirmation dialog) is created,
+   * GearsNativeDialog will call this method.
+   */
+  public Dialog onCreateDialog(int id) {
+    // This should be redefined by subclasses as needed.
+    return null;
+  }
+
 }
diff --git a/src/com/android/browser/GearsFilePickerDialog.java b/src/com/android/browser/GearsFilePickerDialog.java
index d84a970..0bb28d4 100644
--- a/src/com/android/browser/GearsFilePickerDialog.java
+++ b/src/com/android/browser/GearsFilePickerDialog.java
@@ -155,7 +155,7 @@
   public void setupDialog(TextView message, ImageView icon) {
     message.setText(R.string.filepicker_message);
     message.setTextSize(24);
-    icon.setImageResource(R.drawable.gears_icon_32x32);
+    icon.setImageResource(R.drawable.ic_dialog_menu_generic);
   }
 
   public boolean onTouch(View v, MotionEvent event) {
@@ -684,7 +684,7 @@
             int color = getResources().getColor(R.color.icon_selection);
             v.setBackgroundColor(color);
           } else {
-            v.setBackgroundColor(Color.WHITE);
+            v.setBackgroundColor(android.R.color.background_dark);
           }
           return false;
         }
@@ -696,7 +696,7 @@
         int color = getResources().getColor(R.color.icon_selection);
         cell.setBackgroundColor(color);
       } else {
-        cell.setBackgroundColor(Color.WHITE);
+        cell.setBackgroundColor(android.R.color.background_dark);
       }
       Bitmap bmp = elem.getIcon(position);
       if (bmp != null) {
diff --git a/src/com/android/browser/GearsNativeDialog.java b/src/com/android/browser/GearsNativeDialog.java
index c8ae741..c72ad8e 100644
--- a/src/com/android/browser/GearsNativeDialog.java
+++ b/src/com/android/browser/GearsNativeDialog.java
@@ -17,6 +17,7 @@
 package com.android.browser;
 
 import android.app.Activity;
+import android.app.Dialog;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
@@ -24,9 +25,11 @@
 import android.os.Message;
 import android.util.Config;
 import android.util.Log;
+import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.Window;
 import android.widget.BaseAdapter;
+import android.widget.Toast;
 
 import android.webkit.gears.NativeDialog;
 
@@ -90,10 +93,15 @@
 
   @Override
   public void onCreate(Bundle icicle) {
-    super.onCreate(icicle);
-    requestWindowFeature(Window.FEATURE_NO_TITLE);
-    setContentView(R.layout.gears_dialog);
     getArguments();
+    if (mDialogType == SETTINGS_DIALOG) {
+      setTheme(android.R.style.Theme);
+    }
+    super.onCreate(icicle);
+    if (mDialogType != SETTINGS_DIALOG) {
+      requestWindowFeature(Window.FEATURE_NO_TITLE);
+      setContentView(R.layout.gears_dialog);
+    }
 
     switch (mDialogType) {
       case SETTINGS_DIALOG:
@@ -185,6 +193,9 @@
         + "customMessage: \"Press the button to enable my "
         + "application to run offline!\" };";
 
+    String argumentsPermissions2 = "{ locale: \"en-US\", "
+        + "origin: \"http://www.google.com\", dialogType: \"localData\" };";
+
     String argumentsLocation = "{ locale: \"en-US\", "
         + "origin: \"http://www.google.com\", dialogType: \"locationData\","
         + "customIcon: \"http://google-gears.googlecode.com/"
@@ -195,8 +206,8 @@
 
     String argumentsSettings = "{ locale: \"en-US\", permissions: [ { "
         + "name: \"http://www.google.com\", "
-        + "localStorage: { permissionState: 1 }, "
-        + "locationData: { permissionState: 0 } }, "
+        + "localStorage: { permissionState: 0 }, "
+        + "locationData: { permissionState: 1 } }, "
         + "{ name: \"http://www.aaronboodman.com\", "
         + "localStorage: { permissionState: 1 }, "
         + "locationData: { permissionState: 2 } }, "
@@ -204,6 +215,12 @@
         + "localStorage: { permissionState: 2 }, "
         + "locationData: { permissionState: 2 } } ] }";
 
+    String argumentsFilePicker = "{ \"cameraMode\" : \"OFF\", \"filters\""
+        + ": [ \"text/html\", \".txt\" ], \"mode\" : \"MULTIPLE_FILES\" }\"";
+
+    String argumentsFilePicker2 = "{ \"cameraMode\" : \"OFF\", \"filters\""
+        + ": [ \"text/html\", \".txt\" ], \"mode\" : \"SINGLE_FILE\" }\"";
+
     switch (mDialogType) {
       case SHORTCUT_DIALOG:
         mDialogArguments = argumentsShortcuts;
@@ -216,6 +233,9 @@
         break;
       case SETTINGS_DIALOG:
         mDialogArguments = argumentsSettings;
+        break;
+      case FILEPICKER_DIALOG:
+        mDialogArguments = argumentsFilePicker2;
     }
   }
 
@@ -232,6 +252,14 @@
     NativeDialog.closeDialog(ret);
     notifyEndOfDialog();
     finish();
+
+    // If the dialog sets a notification, we display it.
+    int notification = dialog.notification();
+    if (notification != 0) {
+      Toast toast = Toast.makeText(this, notification, Toast.LENGTH_LONG);
+      toast.setGravity(Gravity.BOTTOM, 0, 0);
+      toast.show();
+    }
   }
 
   @Override
@@ -265,10 +293,26 @@
    * NativeDialog that we are done.
    */
   public boolean dispatchKeyEvent(KeyEvent event) {
-    if (event.getKeyCode() ==  KeyEvent.KEYCODE_BACK && event.isDown()) {
-      closeDialog(GearsBaseDialog.CANCEL);
+    if ((event.getKeyCode() == KeyEvent.KEYCODE_BACK)
+      && (event.getAction() == KeyEvent.ACTION_DOWN)) {
+      if (!dialog.handleBackButton()) {
+        // if the dialog doesn't do anything with the back button
+        closeDialog(GearsBaseDialog.CANCEL);
+      }
+      return true; // event consumed
     }
     return super.dispatchKeyEvent(event);
   }
 
+  /**
+   * If the dialog call showDialog() on ourself, we let
+   * it handle the creation of this secondary dialog.
+   * It is used in GearsSettingsDialog, to create the confirmation
+   * dialog when the user click on "Remove this site from Gears"
+   */
+  @Override
+  protected Dialog onCreateDialog(int id) {
+    return dialog.onCreateDialog(id);
+  }
+
 }
diff --git a/src/com/android/browser/GearsPermissions.java b/src/com/android/browser/GearsPermissions.java
index cd46324..e48e045 100644
--- a/src/com/android/browser/GearsPermissions.java
+++ b/src/com/android/browser/GearsPermissions.java
@@ -49,37 +49,37 @@
     public static final int PERMISSION_DENIED = 2;
 
     String mName;
-    int mRowRsc;
-    int mAllowedButtonRsc;
-    int mDeniedButtonRsc;
+    int mTitleRsc;
+    int mSubtitleOnRsc;
+    int mSubtitleOffRsc;
 
     PermissionType(String name) {
       mName = name;
     }
 
-    public void setResources(int rowRsc, int allowedButtonRsc,
-        int deniedButtonRsc) {
-      mRowRsc = rowRsc;
-      mAllowedButtonRsc = allowedButtonRsc;
-      mDeniedButtonRsc = deniedButtonRsc;
-    }
-
-    public int getRowRsc() {
-      return mRowRsc;
-    }
-
-    public int getAllowedButtonRsc() {
-      return mAllowedButtonRsc;
-    }
-
-    public int getDeniedButtonRsc() {
-      return mDeniedButtonRsc;
+    public void setResources(int titleRsc,
+        int subtitleOnRsc, int subtitleOffRsc) {
+      mTitleRsc = titleRsc;
+      mSubtitleOnRsc = subtitleOnRsc;
+      mSubtitleOffRsc = subtitleOffRsc;
     }
 
     public String getName() {
       return mName;
     }
 
+    public int getTitleRsc() {
+      return mTitleRsc;
+    }
+
+    public int getSubtitleOnRsc() {
+      return mSubtitleOnRsc;
+    }
+
+    public int getSubtitleOffRsc() {
+      return mSubtitleOffRsc;
+    }
+
   }
 
   /**
diff --git a/src/com/android/browser/GearsPermissionsDialog.java b/src/com/android/browser/GearsPermissionsDialog.java
index b57ab0b..dbec363 100644
--- a/src/com/android/browser/GearsPermissionsDialog.java
+++ b/src/com/android/browser/GearsPermissionsDialog.java
@@ -35,6 +35,7 @@
   private static final String TAG = "GearsPermissionsDialog";
 
   private String mDialogType;
+  private int mNotification = 0;
 
   public GearsPermissionsDialog(Activity activity,
                                 Handler handler,
@@ -48,15 +49,6 @@
                  R.string.permission_button_allow,
                  R.string.permission_button_deny);
 
-    View contentBorder = findViewById(R.id.content_border);
-    if (contentBorder != null) {
-      contentBorder.setBackgroundResource(R.color.permission_border);
-    }
-    View contentBackground = findViewById(R.id.content_background);
-    if (contentBackground != null) {
-      contentBackground.setBackgroundResource(R.color.permission_background);
-    }
-
     try {
       JSONObject json = new JSONObject(mDialogArguments);
 
@@ -84,6 +76,16 @@
         downloadIcon(iconUrl);
       }
 
+      View msg = findViewById(R.id.permission_dialog_message);
+      if (msg != null) {
+        TextView dialogMessage = (TextView) msg;
+        if (mDialogType.equalsIgnoreCase(LOCAL_DATA_STRING)) {
+          dialogMessage.setText(R.string.query_data_message);
+        } else if (mDialogType.equalsIgnoreCase(LOCATION_DATA_STRING)) {
+          dialogMessage.setText(R.string.location_message);
+        }
+      }
+
     } catch (JSONException e) {
       Log.e(TAG, "JSON exception ", e);
     }
@@ -91,15 +93,11 @@
 
   public void setupDialog(TextView message, ImageView icon) {
     if (mDialogType.equalsIgnoreCase(LOCAL_DATA_STRING)) {
-      message.setText(R.string.query_data_message);
-      icon.setImageResource(R.drawable.gears_local_data);
+      message.setText(R.string.query_data_prompt);
+      icon.setImageResource(android.R.drawable.ic_popup_disk_full);
     } else if (mDialogType.equalsIgnoreCase(LOCATION_DATA_STRING)) {
-      message.setText(R.string.location_message);
-      icon.setImageResource(R.drawable.gears_location_data);
-      View privacyPolicyLabel = findViewById(R.id.privacy_policy_label);
-      if (privacyPolicyLabel != null) {
-        privacyPolicyLabel.setVisibility(View.VISIBLE);
-      }
+      message.setText(R.string.location_prompt);
+      icon.setImageResource(R.drawable.ic_dialog_menu_generic);
     }
   }
 
@@ -108,9 +106,19 @@
     switch (closingType) {
       case ALWAYS_DENY:
         ret = "{\"allow\": false, \"permanently\": true }";
+        if (mDialogType.equalsIgnoreCase(LOCAL_DATA_STRING)) {
+          mNotification = R.string.storage_notification_alwaysdeny;
+        } else if (mDialogType.equalsIgnoreCase(LOCATION_DATA_STRING)) {
+          mNotification = R.string.location_notification_alwaysdeny;
+        }
         break;
       case ALLOW:
         ret = "{\"allow\": true, \"permanently\": true }";
+        if (mDialogType.equalsIgnoreCase(LOCAL_DATA_STRING)) {
+          mNotification = R.string.storage_notification;
+        } else if (mDialogType.equalsIgnoreCase(LOCATION_DATA_STRING)) {
+          mNotification = R.string.location_notification;
+        }
         break;
       case DENY:
         ret = "{\"allow\": false, \"permanently\": false }";
@@ -119,4 +127,7 @@
     return ret;
   }
 
+  public int notification() {
+    return mNotification;
+  }
 }
diff --git a/src/com/android/browser/GearsSettingsDialog.java b/src/com/android/browser/GearsSettingsDialog.java
index 56a1d8d..5ea2342 100644
--- a/src/com/android/browser/GearsSettingsDialog.java
+++ b/src/com/android/browser/GearsSettingsDialog.java
@@ -17,14 +17,21 @@
 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;
@@ -33,6 +40,7 @@
 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;
 
@@ -55,6 +63,7 @@
   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 =
@@ -64,23 +73,23 @@
 
   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.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);
-
+    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);
@@ -88,25 +97,7 @@
     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.
@@ -165,32 +156,23 @@
     View listView = findViewById(R.id.sites_list);
     if (listView != null) {
       ListView list = (ListView) listView;
-      list.setAdapter(new SettingsAdapter(mActivity, mSitesPermissions));
+      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() {
-    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);
-    }
+    setMainTitle();
   }
 
   /**
@@ -198,164 +180,95 @@
    */
   public boolean setPermission(PermissionType type, int perm) {
     if (mChanges == false) {
-      signalChanges();
+      mChanges = true;
     }
     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;
-      }
-    }
+  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
    *
-   * 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.
+   * 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 ArrayAdapter {
+  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) {
-      super(context, R.layout.gears_dialog_settings_row, items);
       mContext = context;
       mItems = items;
+      mCurrentSite = null;
     }
 
-    /*
-     * 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);
+    public int getCount() {
+      if (mCurrentSite == null) {
+        int size = mItems.size();
+        if (size == 0) {
+          return 1;
+        } else {
+          return size;
         }
-      };
-
-      button.setOnCheckedChangeListener(listener);
-
-      if (p.isChecked() != button.isChecked()) {
-        button.setChecked(p.isChecked());
       }
+      return mCurrentPermissions.size() + 1;
     }
 
-    /*
-     * 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);
+    public long getItemId(int position) {
+      return position;
+    }
 
-          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();
-            }
-          }
+    private String shortName(String url) {
+        // We remove the http and https prefix
+        if (url.startsWith("http://")) {
+          return url.substring(7);
         }
-      };
-      button.setTag(perms);
-      button.setOnClickListener(listener);
-      displayAsLink(button);
+        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) {
@@ -363,46 +276,117 @@
       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);
+        row = inflater.inflate(R.layout.gears_settings_row, null);
       }
+      row.setMinimumHeight(MAX_ROW_HEIGHT);
 
-      OriginPermissions perms = (OriginPermissions) mItems.get(position);
+      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);
 
-      View nameView = row.findViewById(R.id.origin_name);
-      if (nameView != null) {
-        TextView originName = (TextView) nameView;
-        originName.setText(perms.getOrigin());
-      }
+          PermissionType type =
+              (PermissionType) mCurrentPermissions.get(position);
+          setText(row, R.id.title, type.getTitleRsc());
 
-      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);
+          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;
+    }
+
   }
 
   /**
@@ -423,21 +407,6 @@
   }
 
   /**
-   * 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.
@@ -479,18 +448,7 @@
   }
 
   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;
-    }
+    String ret = computeDiff(mChanges);
 
     if (mDebug) {
       printPermissions();
diff --git a/src/com/android/browser/GearsShortcutDialog.java b/src/com/android/browser/GearsShortcutDialog.java
index deede12..11d936d 100644
--- a/src/com/android/browser/GearsShortcutDialog.java
+++ b/src/com/android/browser/GearsShortcutDialog.java
@@ -37,6 +37,7 @@
   private final String ICON_32 = "icon32x32";
   private final String ICON_48 = "icon48x48";
   private final String ICON_128 = "icon128x128";
+  private int mNotification = 0;
 
   public GearsShortcutDialog(Activity activity,
                              Handler handler,
@@ -45,20 +46,11 @@
   }
 
   public void setup() {
-    inflate(R.layout.gears_dialog_permission, R.id.panel_content);
+    inflate(R.layout.gears_dialog_shortcut, R.id.panel_content);
     setupButtons(R.string.shortcut_button_alwaysdeny,
                  R.string.shortcut_button_allow,
                  R.string.shortcut_button_deny);
 
-    View contentBorder = findViewById(R.id.content_border);
-    if (contentBorder != null) {
-      contentBorder.setBackgroundResource(R.color.shortcut_border);
-    }
-    View contentBackground = findViewById(R.id.content_background);
-    if (contentBackground != null) {
-      contentBackground.setBackgroundResource(R.color.shortcut_background);
-    }
-
     try {
       JSONObject json = new JSONObject(mDialogArguments);
 
@@ -69,17 +61,25 @@
 
       setupDialog();
 
-      setLabel(json, "name", R.id.origin_title);
+      setLabel(json, "name", R.id.shortcut_name);
       setLabel(json, "link", R.id.origin_subtitle);
       setLabel(json, "description", R.id.origin_message);
     } catch (JSONException e) {
       Log.e(TAG, "JSON exception", e);
     }
+
+    TextView msg = (TextView) findViewById(R.id.permission_dialog_message);
+    msg.setText(R.string.shortcut_message);
+
+    View shortcutIcon = findViewById(R.id.shortcut_panel);
+    if (shortcutIcon != null) {
+      shortcutIcon.setVisibility(View.VISIBLE);
+    }
   }
 
   public void setupDialog(TextView message, ImageView icon) {
-    message.setText(R.string.shortcut_message);
-    icon.setImageResource(R.drawable.gears_icon_48x48);
+    message.setText(R.string.shortcut_prompt);
+    icon.setImageResource(R.drawable.ic_dialog_menu_generic);
   }
 
   /**
@@ -136,6 +136,7 @@
         break;
       case ALLOW:
         ret = "{\"allow\": true, \"locations\": 0 }";
+        mNotification = R.string.shortcut_notification;
         break;
       case DENY:
         ret = null;
@@ -144,4 +145,7 @@
     return ret;
   }
 
+  public int notification() {
+    return mNotification;
+  }
 }
diff --git a/src/com/android/browser/MostVisitedActivity.java b/src/com/android/browser/MostVisitedActivity.java
index aeaf2a6..704ee27 100644
--- a/src/com/android/browser/MostVisitedActivity.java
+++ b/src/com/android/browser/MostVisitedActivity.java
@@ -31,8 +31,10 @@
 import android.widget.ListView;
 import android.widget.SimpleCursorAdapter;
 import android.widget.TextView;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
 
 import java.util.Vector;
 
@@ -47,6 +49,12 @@
         CombinedBookmarkHistoryActivity.getIconListenerSet(getContentResolver())
                 .addListener(new IconReceiver());
         setListAdapter(mAdapter);
+        ListView list = getListView();
+        LayoutInflater factory = LayoutInflater.from(this);
+        View v = factory.inflate(R.layout.empty_history, null);
+        addContentView(v, new LayoutParams(LayoutParams.FILL_PARENT,
+                LayoutParams.FILL_PARENT));
+        list.setEmptyView(v);
     }
 
     private class IconReceiver implements IconListener {