OSDN Git Service

Add UI support in the browser for HTML5 databases
authorNicolas Roard <nicolasroard@google.com>
Mon, 11 May 2009 12:34:17 +0000 (13:34 +0100)
committerNicolas Roard <nicolasroard@google.com>
Mon, 11 May 2009 14:21:18 +0000 (15:21 +0100)
12 files changed:
AndroidManifest.xml
res/layout/permission_dialog.xml [new file with mode: 0644]
res/values/arrays.xml [new file with mode: 0644]
res/values/strings.xml
res/xml/browser_preferences.xml
src/com/android/browser/BrowserActivity.java
src/com/android/browser/BrowserPreferencesPage.java
src/com/android/browser/BrowserQuotaPreference.java [new file with mode: 0644]
src/com/android/browser/BrowserSettings.java
src/com/android/browser/BrowserYesNoPreference.java
src/com/android/browser/OriginSettings.java [new file with mode: 0644]
src/com/android/browser/PermissionDialog.java [new file with mode: 0644]

index ace5750..df01226 100644 (file)
                   android:theme="@android:style/Theme.Dialog">
         </activity>
 
+        <activity android:name="PermissionDialog"
+                  android:configChanges="orientation|keyboardHidden"
+                  android:theme="@android:style/Theme.Dialog">
+        </activity>
+
         <activity android:name="GearsNativeDialog"
                   android:configChanges="orientation|keyboardHidden"
                   android:theme="@android:style/Theme.Dialog">
diff --git a/res/layout/permission_dialog.xml b/res/layout/permission_dialog.xml
new file mode 100644 (file)
index 0000000..ff24eaf
--- /dev/null
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2009, 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.
+ */
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  android:drawingCacheQuality="auto"
+  android:layout_width="fill_parent"
+  android:layout_height="wrap_content"
+  android:orientation="vertical"
+  android:padding="0dip">
+
+  <LinearLayout
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:padding="10dip">
+
+    <ImageView
+      android:id="@+id/icon"
+      android:paddingRight="10dip"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:layout_centerHorizontal="true"/>
+
+    <TextView
+      android:id="@+id/dialog_title"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:layout_centerVertical="true"
+      android:gravity="center_vertical"
+      android:visibility="gone"
+      android:textSize="16dip"
+      android:textStyle="bold"
+      android:textColor="@color/white"/>
+
+  </LinearLayout>
+
+  <LinearLayout
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <ImageView android:id="@+id/titleDivider"
+        android:layout_width="fill_parent"
+        android:layout_height="1dip"
+        android:scaleType="fitXY"
+        android:gravity="fill_horizontal"
+        android:src="@drawable/dialog_divider_horizontal_light"
+        android:layout_marginLeft="10dip"
+        android:layout_marginRight="10dip"/>
+
+  </LinearLayout>
+
+  <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:paddingBottom="10dip"
+    android:layout_weight="1">
+
+    <LinearLayout
+      android:orientation="vertical"
+      android:layout_width="fill_parent"
+      android:paddingTop="10dip"
+      android:paddingLeft="10dip"
+      android:paddingRight="10dip"
+      android:layout_height="wrap_content">
+
+      <TextView
+        android:id="@+id/origin"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:visibility="gone"
+        android:textStyle="bold"
+        android:gravity="left"
+        android:textSize="16dip"
+        android:textColor="@color/white"/>
+
+      <TextView
+        android:id="@+id/dialog_message"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:paddingLeft="4dip"
+        android:paddingTop="10dip"
+        android:gravity="left"
+        android:textSize="16dip"
+        android:textColor="@color/white"/>
+
+    </LinearLayout>
+
+  </ScrollView>
+
+  <LinearLayout
+    android:layout_width="fill_parent"
+    android:background="@color/gray"
+    android:layout_height="wrap_content"
+    android:paddingTop="4dip"
+    android:paddingLeft="0dip"
+    android:paddingRight="0dip">
+
+    <LinearLayout android:id="@+id/leftSpacer"
+       android:layout_weight="0.25"
+       android:layout_width="0dip"
+       android:layout_height="wrap_content"
+       android:orientation="horizontal"
+       android:visibility="gone"/>
+
+    <Button
+      android:id="@+id/button_allow"
+      android:layout_width="96dip"
+      android:layout_height="48dip"
+      android:layout_gravity="left"
+      android:layout_weight="1"
+      android:maxLines="2"
+      android:textSize="13dip"/>
+
+    <Button
+      android:id="@+id/button_alwaysdeny"
+      android:layout_width="96dip"
+      android:layout_height="48dip"
+      android:layout_gravity="left"
+      android:layout_weight="1"
+      android:maxLines="2"
+      android:textSize="13dip"/>
+
+    <Button
+      android:id="@+id/button_deny"
+      android:layout_width="96dip"
+      android:layout_height="48dip"
+      android:layout_gravity="right"
+      android:layout_weight="1"
+      android:maxLines="2"
+      android:textSize="13dip"/>
+
+    <LinearLayout android:id="@+id/rightSpacer"
+      android:layout_width="0dip"
+      android:layout_weight="0.25"
+      android:layout_height="wrap_content"
+      android:orientation="horizontal"
+      android:visibility="gone" />
+
+  </LinearLayout>
+
+</LinearLayout>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
new file mode 100644 (file)
index 0000000..219cc6b
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2009 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.
+  -->
+<resources>
+   <string-array name="webstorage_quota_entries">
+      <item>No quota allowed</item>
+      <item>5 MB</item>
+      <item>10 MB</item>
+      <item>30 MB</item>
+      <item>100 MB</item>
+   </string-array>
+   <string-array name="webstorage_quota_entries_values">
+      <item>0</item>
+      <item>5</item>
+      <item>10</item>
+      <item>30</item>
+      <item>100</item>
+   </string-array>
+</resources>
+
index 77464d7..22ff0df 100644 (file)
     <!-- Settings summary -->
     <string name="pref_extras_gears_enable_summary">Applications that extend browser functionality</string>
     <!-- Settings label -->
+    <string name="pref_extras_webstorage_settings">Local Storage</string>
+    <!-- Settings summary -->
+    <string name="pref_extras_webstorage_settings_summary">Allow websites to store information on your phone</string>
+    <!-- Settings label -->
+    <string name="pref_extras_webstorage_enable">Enable Database Storage</string>
+    <!-- Settings summary -->
+    <string name="pref_extras_webstorage_enable_summary">Allow websites to store informatin in a local database</string>
+    <!-- Settings label -->
+    <string name="pref_extras_webstorage_set_location">Set Databases Location</string>
+    <!-- Settings summary -->
+    <string name="pref_extras_webstorage_set_location_summary">Define where the databases are stored</string>
+    <!-- Settings label -->
+    <string name="pref_extras_webstorage_set_quota">Set Default Quota</string>
+    <!-- Settings summary -->
+    <string name="pref_extras_webstorage_set_quota_summary">The amount of storage new websites can use without your permission</string>
+    <!-- Settings label -->
+    <string name="pref_extras_webstorage_manage_databases">Manage Databases</string>
+    <!-- Settings summary -->
+    <string name="pref_extras_webstorage_manage_databases_summary">Configure existing databases</string>
+    <!-- Settings label -->
+    <string name="pref_extras_webstorage_clear_databases">Clear All Existing Databases</string>
+    <!-- Settings summary -->
+    <string name="pref_extras_webstorage_clear_databases_summary">Clear all data stored in local databases</string>
+    <string name="pref_extras_webstorage_clear_databases_dlg">All existing databases will be cleared</string>
+    <!-- Settings label -->
     <string name="pref_extras_gears_settings">Gears settings</string>
     <!-- Settings summary -->
     <string name="pref_plugin_installed">Plugins list</string>
     <!-- Gears Dialogs -->
     <string name="query_data_prompt">Allow storage</string>
     <string name="query_data_message">This web site would like to store information on your phone.</string>
+    <string name="query_storage_quota_prompt">Increase storage quota</string>
+    <string name="query_storage_quota_message">This web site is over its current
+      storage limit. Would you like to increase its quota limit ?</string>
     <string name="location_prompt">Access your location</string>
     <string name="location_message">This web site would like to have access to your location.</string>
     <string name="shortcut_prompt">Create a shortcut</string>
     <string name="unrecognized_dialog_message">Unrecognized dialog type</string>
     <string name="default_button">OK</string>
 
+    <!-- HTML5 dialogs -->
+    <!-- Used as a toast notification after the user close the html5 webstorage permission dialog -->
+    <string name="webstorage_notification">The quota for this site can be changed in the Local Storage section of the Browser settings</string>
+    <!-- Used in the Browser Settings -->
+    <string name="webstorage_manage_quota_title">Manage Quota</string>
+    <string name="webstorage_manage_quota_summary">Set a new size quota</string>
+    <string name="webstorage_clear_data_title">Clear All Data</string>
+    <string name="webstorage_clear_data_summary">Remove all databases associated with this website</string>
+    <!-- Confirmation dialog when the user ask to clear all data for an origin -->
+    <string name="webstorage_clear_data_dialog_title">Clear All Data</string>
+    <string name="webstorage_clear_data_dialog_message">All stored data by this origin will be deleted</string>
+    <!-- Strings used in the summary of origins -->
+    <string name="webstorage_origin_summary_mb_used">MB used</string>
+    <string name="webstorage_origin_summary_no_quota_left">no allowed quota left</string>
+    <string name="webstorage_origin_summary_mb_left">MB left in the quota</string>
+
     <!-- Zoom-related strings --><skip />
     <!-- Caption for a button that is shown when the zoom widget is showing.  The button's action will switch to the zoom overview mode. -->
     <string name="zoom_overview_button_text">Overview</string>
index 79dfb92..c5b6b24 100644 (file)
                     android:title="@string/pref_extras_gears_settings"
                     android:summary="@string/pref_extras_gears_settings_summary" />
 
+            <PreferenceScreen
+                    android:key="webstorage_settings"
+                    android:title="@string/pref_extras_webstorage_settings"
+                    android:summary="@string/pref_extras_webstorage_settings_summary">
+
+                  <CheckBoxPreference
+                        android:key="enable_database"
+                        android:defaultValue="true"
+                        android:title="@string/pref_extras_webstorage_enable"
+                        android:summary="@string/pref_extras_webstorage_enable_summary" />
+
+                  <ListPreference
+                        android:key="webstorage_default_quota"
+                        android:dependency="enable_database"
+                        android:title="@string/pref_extras_webstorage_set_quota"
+                        android:summary="@string/pref_extras_webstorage_set_quota_summary"
+                        android:entries="@array/webstorage_quota_entries"
+                        android:entryValues="@array/webstorage_quota_entries_values" />
+
+                  <PreferenceScreen
+                        android:key="webstorage_manage_databases"
+                        android:dependency="enable_database"
+                        android:title="@string/pref_extras_webstorage_manage_databases"
+                        android:summary="@string/pref_extras_webstorage_manage_databases_summary" />
+
+                  <com.android.browser.BrowserYesNoPreference
+                        android:key="webstorage_clear_databases"
+                        android:dependency="enable_database"
+                        android:title="@string/pref_extras_webstorage_clear_databases"
+                        android:summary="@string/pref_extras_webstorage_clear_databases_summary"
+                        android:dialogMessage="@string/pref_extras_webstorage_clear_databases_dlg"
+                        android:dialogTitle="@string/clear"
+                        android:dialogIcon="@android:drawable/ic_dialog_alert" />
+
+            </PreferenceScreen>
+
             <com.android.browser.BrowserYesNoPreference
                     android:key="reset_default_preferences"
                     android:title="@string/pref_extras_reset_default"
index af65072..c24577c 100644 (file)
@@ -163,6 +163,8 @@ public class BrowserActivity extends Activity
 
     private SensorManager mSensorManager = null;
 
+    private WebStorage.QuotaUpdater mWebStorageQuotaUpdater = null;
+
     /* Whitelisted webpages
     private static HashSet<String> sWhiteList;
 
@@ -3456,9 +3458,14 @@ public class BrowserActivity extends Activity
                       + currentQuota +
                       ")");
             }
-            // Give the origin an extra megabyte to play with.
-            // TODO: This should show a prompt to the user, really :)
-            quotaUpdater.updateQuota(currentQuota + 1024 * 1024);
+            mWebStorageQuotaUpdater = quotaUpdater;
+            String DIALOG_PACKAGE = "com.android.browser";
+            String DIALOG_CLASS = DIALOG_PACKAGE + ".PermissionDialog";
+            Intent intent = new Intent();
+            intent.setClassName(DIALOG_PACKAGE, DIALOG_CLASS);
+            intent.putExtra(PermissionDialog.PARAM_ORIGIN, url);
+            intent.putExtra(PermissionDialog.PARAM_QUOTA, currentQuota);
+            startActivityForResult(intent, WEBSTORAGE_QUOTA_DIALOG);
         }
     };
 
@@ -4165,6 +4172,14 @@ public class BrowserActivity extends Activity
                     }
                 }
                 break;
+            case WEBSTORAGE_QUOTA_DIALOG:
+                long currentQuota = 0;
+                if (resultCode == RESULT_OK && intent != null) {
+                    currentQuota = intent.getLongExtra(
+                        PermissionDialog.PARAM_QUOTA, currentQuota);
+                }
+                mWebStorageQuotaUpdater.updateQuota(currentQuota);
+                break;
             default:
                 break;
         }
@@ -4721,9 +4736,10 @@ public class BrowserActivity extends Activity
     private BroadcastReceiver mNetworkStateIntentReceiver;
 
     // activity requestCode
-    final static int COMBO_PAGE             = 1;
-    final static int DOWNLOAD_PAGE          = 2;
-    final static int PREFERENCES_PAGE       = 3;
+    final static int COMBO_PAGE                 = 1;
+    final static int DOWNLOAD_PAGE              = 2;
+    final static int PREFERENCES_PAGE           = 3;
+    final static int WEBSTORAGE_QUOTA_DIALOG    = 4;
 
     // the frenquency of checking whether system memory is low
     final static int CHECK_MEMORY_INTERVAL = 30000;     // 30 seconds
index 5d6795b..e093ced 100644 (file)
 package com.android.browser;
 
 import java.util.List;
+import java.util.Vector;
 
+import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
 import android.preference.EditTextPreference;
+import android.preference.ListPreference;
 import android.preference.Preference;
 import android.preference.PreferenceActivity;
+import android.preference.PreferenceScreen;
+import android.util.Log;
+import android.webkit.Plugin;
+import android.webkit.WebStorage;
 import android.webkit.WebView;
 import android.webkit.Plugin;
 
@@ -30,6 +37,8 @@ public class BrowserPreferencesPage extends PreferenceActivity
         implements Preference.OnPreferenceChangeListener, 
         Preference.OnPreferenceClickListener {
 
+    String TAG = "BrowserPreferencesPage";
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -60,6 +69,23 @@ public class BrowserPreferencesPage extends PreferenceActivity
         
         e = findPreference(BrowserSettings.PREF_GEARS_SETTINGS);
         e.setOnPreferenceClickListener(this);
+
+        PreferenceScreen s = (PreferenceScreen)
+            findPreference(BrowserSettings.PREF_WEBSTORAGE_SETTINGS);
+
+        Vector origins = WebStorage.getInstance().getOrigins();
+        if (origins != null) {
+            for (int i = 0;  i < origins.size(); i++) {
+                OriginSettings origin =
+                    new OriginSettings(this, (String) origins.get(i));
+                PreferenceScreen screen =
+                    getPreferenceManager().createPreferenceScreen(this);
+                origin.setScreen(screen);
+                origin.setRootScreen(s);
+                origin.setup();
+                s.addPreference(screen);
+            }
+        }
     }
 
     @Override
diff --git a/src/com/android/browser/BrowserQuotaPreference.java b/src/com/android/browser/BrowserQuotaPreference.java
new file mode 100644 (file)
index 0000000..653c085
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2009 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.preference.ListPreference;
+import android.content.Context;
+import android.preference.PreferenceScreen;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.webkit.WebStorage;
+
+/**
+ * Utility class to display and manage the choosen quota
+ * for an origin (HTML5 WebStorage feature)
+ */
+class BrowserQuotaPreference extends ListPreference {
+
+    private String TAG = "BrowserQuotaPreference";
+    private OriginSettings mOrigin = null;
+    private static long sOneMB = 1024 * 1024;
+
+    // This is the constructor called by the inflater
+    public BrowserQuotaPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public BrowserQuotaPreference(Context context, OriginSettings origin) {
+        super(context);
+        mOrigin = origin;
+    }
+
+    public void setCurrentIndex () {
+        CharSequence[] values = getEntryValues();
+        long quota = 0;
+        if (mOrigin != null) {
+            quota = mOrigin.getQuota();
+        }
+        for (int i = 0; i < values.length; i++) {
+            long value = Long.parseLong(values[i].toString());
+            value *= sOneMB; // the string array is expressed in MB
+            if (value >= quota) {
+                setValueIndex(i);
+                break;
+            }
+        }
+    }
+
+    @Override
+    protected View onCreateDialogView() {
+        setCurrentIndex();
+        return super.onCreateDialogView();
+    }
+
+    @Override
+    protected void onDialogClosed(boolean positiveResult) {
+        super.onDialogClosed(positiveResult);
+        if (mOrigin == null) {
+            return;
+        }
+        if (positiveResult) {
+            long quota = Long.parseLong(getValue());
+            quota *= sOneMB; // getValue() is in MB
+            mOrigin.setQuota(quota);
+        }
+    }
+}
index 95ed17b..9be22ea 100644 (file)
@@ -25,6 +25,9 @@ import android.content.pm.ActivityInfo;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
 import android.os.SystemProperties;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceScreen;
+import android.util.Log;
 import android.view.WindowManager;
 import android.webkit.CacheManager;
 import android.webkit.CookieManager;
@@ -32,6 +35,7 @@ import android.webkit.WebView;
 import android.webkit.WebViewDatabase;
 import android.webkit.WebIconDatabase;
 import android.webkit.WebSettings;
+import android.webkit.WebStorage;
 import android.preference.PreferenceManager;
 import android.provider.Browser;
 
@@ -76,10 +80,13 @@ class BrowserSettings extends Observable {
     private boolean showDebugSettings = false;
     private String databasePath; // default value set in loadFromDb()
     private boolean databaseEnabled = true;
+    private long webStorageDefaultQuota = 5 * 1024 * 1024;
     // The Browser always enables Application Caches.
     private boolean appCacheEnabled = true;
     private String appCachePath;  // default value set in loadFromDb().
 
+    private final static String TAG = "BrowserSettings";
+
     // Development settings
     public WebSettings.LayoutAlgorithm layoutAlgorithm =
         WebSettings.LayoutAlgorithm.NARROW_COLUMNS;
@@ -108,10 +115,19 @@ class BrowserSettings extends Observable {
             "privacy_clear_form_data";
     public final static String PREF_CLEAR_PASSWORDS =
             "privacy_clear_passwords";
+    public final static String PREF_CLEAR_DATABASES =
+            "webstorage_clear_databases";
+    public final static String PREF_CLEAR_ALL_DATA =
+            "webstorage_clear_all_data";
+    public final static String PREF_MANAGE_QUOTA =
+            "webstorage_manage_quota";
+    public final static String PREF_DEFAULT_QUOTA =
+            "webstorage_default_quota";
     public final static String PREF_EXTRAS_RESET_DEFAULTS =
             "reset_default_preferences";
     public final static String PREF_DEBUG_SETTINGS = "debug_menu";
     public final static String PREF_GEARS_SETTINGS = "gears_settings";
+    public final static String PREF_WEBSTORAGE_SETTINGS = "webstorage_manage_databases";
     public final static String PREF_TEXT_SIZE = "text_size";
     public final static String PREF_DEFAULT_TEXT_ENCODING =
             "default_text_encoding";
@@ -190,6 +206,7 @@ class BrowserSettings extends Observable {
 
             s.setDatabasePath(b.databasePath);
             s.setDatabaseEnabled(b.databaseEnabled);
+            s.setWebStorageDefaultQuota(b.webStorageDefaultQuota);
 
             // Turn on Application Caches.
             s.setAppCachePath(b.appCachePath);
@@ -242,6 +259,8 @@ class BrowserSettings extends Observable {
         pluginsPath = p.getString("plugins_path", pluginsPath);
         databasePath = p.getString("database_path", databasePath);
         databaseEnabled = p.getBoolean("enable_database", databaseEnabled);
+        webStorageDefaultQuota = Long.parseLong(p.getString(PREF_DEFAULT_QUOTA,
+                String.valueOf(webStorageDefaultQuota)));
         appCacheEnabled = p.getBoolean("enable_appcache",
             appCacheEnabled);
         appCachePath = p.getString("appcache_path", appCachePath);
@@ -466,6 +485,15 @@ class BrowserSettings extends Observable {
         db.clearHttpAuthUsernamePassword();
     }
 
+    /*package*/ void clearDatabases(Context context) {
+        WebStorage.getInstance().deleteAllDatabases();
+        // Remove all listed databases from the preferences
+        PreferenceActivity activity = (PreferenceActivity) context;
+        PreferenceScreen screen = (PreferenceScreen)
+            activity.findPreference(BrowserSettings.PREF_WEBSTORAGE_SETTINGS);
+        screen.removeAll();
+    }
+
     /*package*/ void resetDefaultPreferences(Context ctx) {
         SharedPreferences p =
             PreferenceManager.getDefaultSharedPreferences(ctx);
index 65cde71..11a577b 100644 (file)
@@ -23,11 +23,21 @@ import android.util.AttributeSet;
 
 class BrowserYesNoPreference extends YesNoPreference {
 
+    // This is used for the HTML5 pref UI, where we construct
+    // BrowserYesNoPreference objects on the fly and where we need
+    // to save the corresponding origin.
+    OriginSettings mOrigin = null;
+
     // This is the constructor called by the inflater
     public BrowserYesNoPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
+    public BrowserYesNoPreference(Context context, OriginSettings origin) {
+        super(context);
+        mOrigin = origin;
+    }
+
     @Override
     protected void onDialogClosed(boolean positiveResult) {
         super.onDialogClosed(positiveResult);
@@ -46,6 +56,12 @@ class BrowserYesNoPreference extends YesNoPreference {
                 BrowserSettings.getInstance().clearFormData(context);
             } else if (BrowserSettings.PREF_CLEAR_PASSWORDS.equals(getKey())) {
                 BrowserSettings.getInstance().clearPasswords(context);
+            } else if (BrowserSettings.PREF_CLEAR_DATABASES.equals(getKey())) {
+                BrowserSettings.getInstance().clearDatabases(context);
+            } else if (BrowserSettings.PREF_CLEAR_ALL_DATA.equals(getKey())) {
+                if (mOrigin != null) {
+                    mOrigin.delete();
+                }
             } else if (BrowserSettings.PREF_EXTRAS_RESET_DEFAULTS.equals(
                     getKey())) {
                 BrowserSettings.getInstance().resetDefaultPreferences(context);
diff --git a/src/com/android/browser/OriginSettings.java b/src/com/android/browser/OriginSettings.java
new file mode 100644 (file)
index 0000000..3c7273d
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2009 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.content.Context;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceScreen;
+import android.util.Log;
+import android.webkit.WebStorage;
+
+/**
+ * Manage the settings for an origin.
+ * We use it to keep track of the HTML5 settings, i.e. database (webstorage).
+ */
+class OriginSettings {
+
+    private String TAG = "OriginSettings";
+    private String mOrigin = null;
+    private long mQuota = 0;
+    private long mUsage = 0;
+    private PreferenceScreen mInfoScreen;
+    private PreferenceScreen mRootScreen;
+    private PreferenceActivity mActivity;
+
+    private static String sMBUsed = null;
+    private static String sNoQuotaLeft = null;
+    private static String sMBLeft = null;
+
+    public OriginSettings(PreferenceActivity activity, String origin) {
+        mOrigin = origin;
+        mUsage = WebStorage.getInstance().getUsageForOrigin(mOrigin);
+        mQuota = WebStorage.getInstance().getQuotaForOrigin(mOrigin);
+        mActivity = activity;
+        if (sMBUsed == null) {
+          sMBUsed = mActivity.getString(
+              R.string.webstorage_origin_summary_mb_used);
+          sNoQuotaLeft = mActivity.getString(
+              R.string.webstorage_origin_summary_no_quota_left);
+          sMBLeft = mActivity.getString(
+              R.string.webstorage_origin_summary_mb_left);
+        }
+    }
+
+    public String getOrigin() {
+        return mOrigin;
+    }
+
+    public long getQuota() {
+        return mQuota;
+    }
+
+    public void setScreen(PreferenceScreen screen) {
+        mInfoScreen = screen;
+    }
+
+    public void setRootScreen(PreferenceScreen screen) {
+        mRootScreen = screen;
+    }
+
+    private String sizeValueToString(long value) {
+        float mb = (float) value / (1024.0F * 1024.0F);
+        int val = (int) (mb * 10);
+        float ret = (float) (val / 10.0F);
+        if (ret <= 0) {
+            return "0";
+        }
+        return String.valueOf(ret);
+    }
+
+    public void updateSummary() {
+        String summary = sizeValueToString(mUsage) + " " + sMBUsed;
+        if ((mQuota <= 0) || ((mQuota - mUsage) <= 0)) {
+            summary += ", " + sNoQuotaLeft;
+        } else {
+            summary += " (" + sizeValueToString(mQuota - mUsage);
+            summary += " " + sMBLeft + ")";
+        }
+        mInfoScreen.setSummary(summary);
+        mActivity.onContentChanged();
+    }
+
+    public void setup() {
+        mInfoScreen.setTitle(mOrigin);
+        mInfoScreen.setKey(mOrigin);
+        updateSummary();
+
+        BrowserQuotaPreference manageSite = new BrowserQuotaPreference(mActivity, this);
+        BrowserYesNoPreference clearAllData = new BrowserYesNoPreference(mActivity, this);
+
+        manageSite.setTitle(R.string.webstorage_manage_quota_title);
+        manageSite.setSummary(R.string.webstorage_manage_quota_summary);
+        manageSite.setKey(BrowserSettings.PREF_MANAGE_QUOTA);
+        manageSite.setEntries(R.array.webstorage_quota_entries);
+        manageSite.setEntryValues(R.array.webstorage_quota_entries_values);
+
+        clearAllData.setTitle(R.string.webstorage_clear_data_title);
+        clearAllData.setSummary(R.string.webstorage_clear_data_summary);
+        clearAllData.setKey(BrowserSettings.PREF_CLEAR_ALL_DATA);
+        clearAllData.setDialogTitle(R.string.webstorage_clear_data_dialog_title);
+        clearAllData.setDialogMessage(R.string.webstorage_clear_data_dialog_message);
+        clearAllData.setDialogIcon(android.R.drawable.ic_dialog_alert);
+
+        mInfoScreen.addPreference(manageSite);
+        mInfoScreen.addPreference(clearAllData);
+    }
+
+    public void setQuota(long quota) {
+        mQuota = quota;
+        WebStorage.getInstance().setQuotaForOrigin(mOrigin, mQuota);
+        mInfoScreen.getDialog().dismiss();
+        updateSummary();
+    }
+
+    public void delete() {
+        WebStorage.getInstance().deleteOrigin(mOrigin);
+        mInfoScreen.removeAll();
+        mRootScreen.removePreference(mInfoScreen);
+        mInfoScreen.getDialog().dismiss();
+    }
+}
diff --git a/src/com/android/browser/PermissionDialog.java b/src/com/android/browser/PermissionDialog.java
new file mode 100644 (file)
index 0000000..b71261a
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2009 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.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.Window;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+/**
+ * Permission dialog for HTML5
+ * @hide
+ */
+public class PermissionDialog extends Activity {
+
+    private static final String TAG = "PermissionDialog";
+    public static final String PARAM_ORIGIN = "origin";
+    public static final String PARAM_QUOTA = "quota";
+
+    private String mWebStorageOrigin;
+    private long mWebStorageQuota = 0;
+    private int mNotification = 0;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        getParameters();
+        setupDialog();
+    }
+
+    private void getParameters() {
+        Intent intent = getIntent();
+        mWebStorageOrigin = intent.getStringExtra(PARAM_ORIGIN);
+        mWebStorageQuota = intent.getLongExtra(PARAM_QUOTA, 0);
+    }
+
+    private void setupDialog() {
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+        setContentView(R.layout.permission_dialog);
+
+        setIcon(R.id.icon, android.R.drawable.ic_popup_disk_full);
+        setText(R.id.dialog_title, R.string.query_storage_quota_prompt);
+        setText(R.id.dialog_message, R.string.query_storage_quota_message);
+        setCharSequence(R.id.origin, mWebStorageOrigin);
+
+        setupButton(R.id.button_allow, R.string.permission_button_allow,
+            new View.OnClickListener() {
+                public void onClick(View v) { allow(); }
+            });
+        setupButton(R.id.button_alwaysdeny, R.string.permission_button_alwaysdeny,
+            new View.OnClickListener() {
+                public void onClick(View v) { alwaysdeny(); }
+            });
+        setupButton(R.id.button_deny, R.string.permission_button_deny,
+            new View.OnClickListener() {
+                public void onClick(View v) { deny(); }
+            });
+    }
+
+    private void setText(int viewID, int stringID) {
+        setCharSequence(viewID, getString(stringID));
+    }
+
+    private void setCharSequence(int viewID, CharSequence string) {
+        View view = findViewById(viewID);
+        if (view == null) {
+            return;
+        }
+        view.setVisibility(View.VISIBLE);
+        TextView textView = (TextView) view;
+        textView.setText(string);
+    }
+
+    private void setIcon(int viewID, int imageID) {
+        View view = findViewById(viewID);
+        if (view == null) {
+            return;
+        }
+        view.setVisibility(View.VISIBLE);
+        ImageView icon = (ImageView) view;
+        icon.setImageResource(imageID);
+    }
+
+    private void setupButton(int viewID, int stringID,
+                             View.OnClickListener listener) {
+        View view = findViewById(viewID);
+        if (view == null) {
+            return;
+        }
+        setText(viewID, stringID);
+        view.setOnClickListener(listener);
+    }
+
+    private void useNextQuota() {
+        CharSequence[] values = getResources().getTextArray(
+            R.array.webstorage_quota_entries_values);
+        for (int i=0; i<values.length; i++) {
+            long value = Long.parseLong(values[i].toString());
+            value *= (1024 * 1024); // the string array is expressed in MB
+            if (value > mWebStorageQuota) {
+                mWebStorageQuota = value;
+                break;
+            }
+        }
+    }
+
+    private void allow() {
+        // If somehow there is no "next quota" in the ladder,
+        // we'll add 1MB anyway.
+        mWebStorageQuota += 1024*1024;
+        useNextQuota();
+        mNotification = R.string.webstorage_notification;
+        closeDialog();
+    }
+
+    private void alwaysdeny() {
+        // Setting the quota to 0 will prevent any new data to be
+        // added, but the existing data will not be deleted.
+        mWebStorageQuota = 0;
+        mNotification = R.string.webstorage_notification;
+        closeDialog();
+    }
+
+    private void deny() {
+        closeDialog();
+    }
+
+    private void closeDialog() {
+        Intent intent = new Intent();
+        intent.putExtra(PARAM_QUOTA, mWebStorageQuota);
+        setResult(RESULT_OK, intent);
+        showToast();
+        finish();
+    }
+
+    private void showToast() {
+        if (mNotification != 0) {
+            Toast toast = Toast.makeText(this, mNotification, Toast.LENGTH_LONG);
+            toast.setGravity(Gravity.BOTTOM, 0, 0);
+            toast.show();
+        }
+    }
+
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if ((event.getKeyCode() == KeyEvent.KEYCODE_BACK)
+              && (event.getAction() == KeyEvent.ACTION_DOWN)) {
+            closeDialog();
+            return true; // event consumed
+        }
+        return super.dispatchKeyEvent(event);
+    }
+
+}