auto import from //depot/cupcake/@135843
diff --git a/src/com/android/browser/GearsBaseDialog.java b/src/com/android/browser/GearsBaseDialog.java
new file mode 100644
index 0000000..638ba27
--- /dev/null
+++ b/src/com/android/browser/GearsBaseDialog.java
@@ -0,0 +1,474 @@
+/*
+ * 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.Dialog;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Handler;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.UnderlineSpan;
+import android.util.Log;
+import android.view.InflateException;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.lang.ClassCastException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Base dialog class for gears
+ */
+class GearsBaseDialog {
+
+  private static final String TAG = "GearsNativeDialog";
+  protected Handler mHandler;
+  protected Activity mActivity;
+  protected String mDialogArguments;
+
+  private Bitmap mIcon;
+  private final int MAX_ICON_SIZE = 64;
+  protected int mChoosenIconSize;
+
+  // Dialog closing types
+  public static final int CANCEL = 0;
+  public static final int ALWAYS_DENY = 1;
+  public static final int ALLOW = 2;
+  public static final int DENY = 3;
+  public static final int NEW_ICON = 4;
+  public static final int UPDATE_ICON = 5;
+  public static final int REQUEST_ICON = 6;
+  public static final int PAUSE_REQUEST_ICON = 7;
+  public static final int CLEAR_REQUEST_ICON = 8;
+
+  protected final String LOCAL_DATA_STRING = "localData";
+  protected final String LOCAL_STORAGE_STRING = "localStorage";
+  protected final String LOCATION_DATA_STRING = "locationData";
+
+  protected String mGearsVersion = "UNDEFINED";
+  protected boolean mDebug = false;
+
+  public GearsBaseDialog(Activity activity, Handler handler, String arguments) {
+    mActivity = activity;
+    mHandler = handler;
+    mDialogArguments = arguments;
+  }
+
+  Resources getResources() {
+    return mActivity.getResources();
+  }
+
+  Object getSystemService(String name) {
+    return mActivity.getSystemService(name);
+  }
+
+  View findViewById(int id) {
+    return mActivity.findViewById(id);
+  }
+
+  private String getString(int id) {
+    return mActivity.getString(id);
+  }
+
+  public void setDebug(boolean debug) {
+    mDebug = debug;
+  }
+
+  public void setGearsVersion(String version) {
+    mGearsVersion = version;
+  }
+
+  public String closeDialog(int closingType) {
+    return null;
+  }
+
+  /*
+   * Utility methods for setting up the dialogs elements
+   */
+
+  /**
+   * Inflate a given layout in a view (which has to be
+   * a ViewGroup, e.g. LinearLayout).
+   * This is used to share the basic dialog outline among
+   * the different dialog types.
+   */
+  void inflate(int layout, int viewID) {
+    LayoutInflater inflater = (LayoutInflater) getSystemService(
+        Context.LAYOUT_INFLATER_SERVICE);
+    View view = findViewById(viewID);
+    if (view != null) {
+      try {
+        ViewGroup viewGroup = (ViewGroup) view;
+        inflater.inflate(layout, viewGroup);
+      } catch (ClassCastException e) {
+        String msg = "exception, the view (" + view + ")";
+        msg += " is not a ViewGroup";
+        Log.e(TAG, msg, e);
+      } catch (InflateException e) {
+        Log.e(TAG, "exception while inflating the layout", e);
+      }
+    } else {
+      String msg = "problem, trying to inflate a non-existent view";
+      msg += " (" + viewID + ")";
+      Log.e(TAG, msg);
+    }
+  }
+
+  /**
+   * Button setup.
+   * Set the button's text and its listener. If the text resource's id
+   * is 0, makes the button invisible.
+   */
+  void setupButton(int buttonRscID,
+                   int rscString,
+                   View.OnClickListener listener,
+                   boolean isLink,
+                   boolean requestFocus) {
+    View view = findViewById(buttonRscID);
+    if (view == null) {
+      return;
+    }
+
+    Button button = (Button) view;
+
+    if (rscString == 0) {
+      button.setVisibility(View.GONE);
+    } else {
+      CharSequence text = getString(rscString);
+      button.setText(text);
+      button.setOnClickListener(listener);
+      if (isLink) {
+        displayAsLink(button);
+      }
+      if (requestFocus) {
+        button.requestFocus();
+      }
+    }
+  }
+
+  /**
+   * Button setup: as the above method, except that 'isLink' and
+   * 'requestFocus' default to false.
+   */
+  void setupButton(int buttonRsc, int rsc,
+                   View.OnClickListener listener) {
+    setupButton(buttonRsc, rsc, listener, false, false);
+  }
+
+  /**
+   * Utility method to setup the three dialog buttons.
+   */
+  void setupButtons(int alwaysDenyRsc, int allowRsc, int denyRsc) {
+    setupButton(R.id.button_alwaysdeny, alwaysDenyRsc,
+                new Button.OnClickListener() {
+                  public void onClick(View v) {
+                    mHandler.sendEmptyMessage(ALWAYS_DENY);
+                  }
+                });
+
+    setupButton(R.id.button_allow, allowRsc,
+                new Button.OnClickListener() {
+                  public void onClick(View v) {
+                    mHandler.sendEmptyMessage(ALLOW);
+                  }
+                });
+
+    setupButton(R.id.button_deny, denyRsc,
+                new Button.OnClickListener() {
+                  public void onClick(View v) {
+                    mHandler.sendEmptyMessage(DENY);
+                  }
+                });
+  }
+
+  /**
+   * Display a button as an HTML link. Remove the background, set the
+   * text color to R.color.dialog_link and draw an underline
+   */
+  void displayAsLink(Button button) {
+    if (button == null) {
+      return;
+    }
+
+    CharSequence text = button.getText();
+    button.setBackgroundDrawable(null);
+    int color = getResources().getColor(R.color.dialog_link);
+    button.setTextColor(color);
+    SpannableString str = new SpannableString(text);
+    str.setSpan(new UnderlineSpan(), 0, str.length(),
+                Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+    button.setText(str);
+    button.setFocusable(false);
+  }
+
+  /**
+   * Utility method to set elements' text indicated in
+   * the dialogs' arguments.
+   */
+  void setLabel(JSONObject json, String name, int rsc) {
+    try {
+      if (json.has(name)) {
+        String text = json.getString(name);
+        View view = findViewById(rsc);
+        if (view != null && text != null) {
+          TextView textView = (TextView) view;
+          textView.setText(text);
+          textView.setVisibility(View.VISIBLE);
+        }
+      }
+    } catch (JSONException e) {
+      Log.e(TAG, "json exception", e);
+    }
+  }
+
+  /**
+   * Utility method to hide a view.
+   */
+  void hideView(View v, int rsc) {
+    if (rsc == 0) {
+      return;
+    }
+    View view;
+    if (v == null) {
+      view = findViewById(rsc);
+    } else {
+      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;
+    if (v == null) {
+      view = findViewById(rsc);
+    } else {
+      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.
+   */
+  class IconDownload implements Runnable {
+    private String mUrlString;
+
+    IconDownload(String url) {
+      mUrlString = url;
+    }
+
+    public void run() {
+      if (mUrlString == null) {
+        return;
+      }
+      try {
+        URL url = new URL(mUrlString);
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        connection.setDoInput(true);
+        connection.connect();
+        int length = connection.getContentLength();
+        InputStream is = connection.getInputStream();
+        Bitmap customIcon = BitmapFactory.decodeStream(is);
+        if (customIcon != null) {
+          mIcon = customIcon;
+          mHandler.sendEmptyMessage(UPDATE_ICON);
+        }
+      } catch (ClassCastException e) {
+        Log.e(TAG, "Class cast exception (" + mUrlString + ")", e);
+      } catch (MalformedURLException e) {
+        Log.e(TAG, "Malformed url (" + mUrlString + ") ", e);
+      } catch (IOException e) {
+        Log.e(TAG, "Exception downloading icon (" + mUrlString + ") ", e);
+      }
+    }
+  }
+
+  /**
+   * Utility method to update the icon.
+   * Called on the UI thread.
+   */
+  public void updateIcon() {
+    if (mIcon == null) {
+      return;
+    }
+    View view = findViewById(R.id.origin_icon);
+    if (view != null) {
+      ImageView imageView = (ImageView) view;
+      imageView.setMaxHeight(MAX_ICON_SIZE);
+      imageView.setMaxWidth(MAX_ICON_SIZE);
+      imageView.setScaleType(ImageView.ScaleType.FIT_XY);
+      imageView.setImageBitmap(mIcon);
+      imageView.setVisibility(View.VISIBLE);
+    }
+  }
+
+  /**
+   * Utility method to download an icon from a url and set
+   * it to the GUI element R.id.origin_icon.
+   * It is used both in the shortcut dialog and the
+   * permission dialog.
+   * The actual download is done in the background via
+   * IconDownload; once the icon is downlowded the UI is updated
+   * via updateIcon().
+   * The icon size is included in the layout with the choosen
+   * size, although not displayed, to limit text reflow once
+   * the icon is received.
+   */
+  void downloadIcon(String url) {
+    if (url == null) {
+      return;
+    }
+    View view = findViewById(R.id.origin_icon);
+    if (view != null) {
+      view.setMinimumWidth(mChoosenIconSize);
+      view.setMinimumHeight(mChoosenIconSize);
+      view.setVisibility(View.INVISIBLE);
+    }
+    Thread thread = new Thread(new IconDownload(url));
+    thread.start();
+  }
+
+  /**
+   * Utility method that get the dialogMessage
+   * and icon and ask the setupDialog(message,icon)
+   * method to set the values.
+   */
+  public void setupDialog() {
+    TextView dialogMessage = null;
+    ImageView icon = null;
+
+    View view = findViewById(R.id.dialog_message);
+    if (view != null) {
+      dialogMessage = (TextView) view;
+    }
+
+    View iconView = findViewById(R.id.icon);
+    if (iconView != null) {
+      icon = (ImageView) iconView;
+    }
+
+    if ((dialogMessage != null) && (icon != null)) {
+      setupDialog(dialogMessage, icon);
+      dialogMessage.setVisibility(View.VISIBLE);
+    }
+  }
+
+  /*
+   * Set the message and icon of the dialog
+   */
+  public void setupDialog(TextView message, ImageView icon) {
+    message.setText(R.string.unrecognized_dialog_message);
+    icon.setImageResource(R.drawable.ic_dialog_menu_generic);
+    message.setVisibility(View.VISIBLE);
+  }
+
+  /**
+   * Setup the dialog
+   * By default, just display a simple message.
+   */
+  public void setup() {
+    setupButtons(0, 0, R.string.default_button);
+    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;
+  }
+
+}