summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/app/SearchDialog.java4
-rw-r--r--core/java/android/app/SuggestionsAdapter.java145
-rw-r--r--core/java/android/webkit/WebSettings.java170
-rw-r--r--core/res/res/color/search_url_text.xml21
-rw-r--r--core/res/res/values/colors.xml4
5 files changed, 318 insertions, 26 deletions
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 022a9d9..6d6aca4 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -991,7 +991,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
};
@Override
- public void cancel() {
+ public void dismiss() {
if (!isShowing()) return;
// We made sure the IME was displayed, so also make sure it is closed
@@ -1003,7 +1003,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
getWindow().getDecorView().getWindowToken(), 0);
}
- super.cancel();
+ super.dismiss();
}
/**
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 49c94d1..c8e952f 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -18,7 +18,8 @@ package android.app;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.res.Resources.NotFoundException;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
@@ -300,29 +301,17 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
((SuggestionItemView)view).setColor(backgroundColor);
final boolean isHtml = mFormatCol > 0 && "html".equals(cursor.getString(mFormatCol));
- setViewText(cursor, views.mText1, mText1Col, isHtml);
- setViewText(cursor, views.mText2, mText2Col, isHtml);
- setViewIcon(cursor, views.mIcon1, mIconName1Col);
- setViewIcon(cursor, views.mIcon2, mIconName2Col);
- }
-
- private void setViewText(Cursor cursor, TextView v, int textCol, boolean isHtml) {
- if (v == null) {
- return;
- }
- CharSequence text = null;
- if (textCol >= 0) {
- String str = cursor.getString(textCol);
- text = (str != null && isHtml) ? Html.fromHtml(str) : str;
+ String text1 = null;
+ if (mText1Col >= 0) {
+ text1 = cursor.getString(mText1Col);
}
- // Set the text even if it's null, since we need to clear any previous text.
- v.setText(text);
-
- if (TextUtils.isEmpty(text)) {
- v.setVisibility(View.GONE);
- } else {
- v.setVisibility(View.VISIBLE);
+ String text2 = null;
+ if (mText2Col >= 0) {
+ text2 = cursor.getString(mText2Col);
}
+ ((SuggestionItemView)view).setTextStrings(text1, text2, isHtml, mProviderContext);
+ setViewIcon(cursor, views.mIcon1, mIconName1Col);
+ setViewIcon(cursor, views.mIcon2, mIconName2Col);
}
private void setViewIcon(Cursor cursor, ImageView v, int iconNameCol) {
@@ -476,7 +465,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
if (drawable != null) {
mOutsideDrawablesCache.put(drawableId, drawable);
}
- } catch (NotFoundException nfe) {
+ } catch (Resources.NotFoundException nfe) {
if (DBG) Log.d(LOG_TAG, "Icon resource not found: " + drawableId);
// drawable = null;
}
@@ -509,8 +498,82 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
* draws on top of the list view selection highlight).
*/
private class SuggestionItemView extends ViewGroup {
+ /**
+ * Parses a given HTMl string and manages Spannable variants of the string for different
+ * states of the suggestion item (selected, pressed and normal). Colors for these different
+ * states are specified in the html font tag color attribute in the format '@<RESOURCEID>'
+ * where RESOURCEID is the ID of a ColorStateList or Color resource.
+ */
+ private class MultiStateText {
+ private CharSequence mNormal = null; // text to display in normal state.
+ private CharSequence mSelected = null; // text to display in selected state.
+ private CharSequence mPressed = null; // text to display in pressed state.
+ private String mPlainText = null; // valid if the text is stateless plain text.
+
+ public MultiStateText(boolean isHtml, String text, Context context) {
+ if (!isHtml || text == null) {
+ mPlainText = text;
+ return;
+ }
+
+ String textNormal = text;
+ String textSelected = text;
+ String textPressed = text;
+ int textLength = text.length();
+ int start = text.indexOf("\"@");
+
+ // For each font color attribute which has the value in the form '@<RESOURCEID>',
+ // try to load the resource and create the display strings for the 3 states.
+ while (start >= 0) {
+ start++;
+ int end = text.indexOf("\"", start);
+ if (end == -1) break;
+
+ String colorIdString = text.substring(start, end);
+ int colorId = Integer.parseInt(colorIdString.substring(1));
+ try {
+ // The following call works both for color lists and colors.
+ ColorStateList csl = context.getResources().getColorStateList(colorId);
+ int normalColor = csl.getColorForState(
+ View.EMPTY_STATE_SET, csl.getDefaultColor());
+ int selectedColor = csl.getColorForState(
+ View.SELECTED_STATE_SET, csl.getDefaultColor());
+ int pressedColor = csl.getColorForState(
+ View.PRESSED_STATE_SET, csl.getDefaultColor());
+
+ // Convert the int color values into a hex string, and strip the first 2
+ // characters which will be the alpha (html doesn't want this).
+ textNormal = textNormal.replace(colorIdString,
+ "#" + Integer.toHexString(normalColor).substring(2));
+ textSelected = textSelected.replace(colorIdString,
+ "#" + Integer.toHexString(selectedColor).substring(2));
+ textPressed = textPressed.replace(colorIdString,
+ "#" + Integer.toHexString(pressedColor).substring(2));
+ } catch (Resources.NotFoundException e) {
+ // Nothing to do.
+ }
+
+ start = text.indexOf("\"@", end);
+ }
+ mNormal = Html.fromHtml(textNormal);
+ mSelected = Html.fromHtml(textSelected);
+ mPressed = Html.fromHtml(textPressed);
+ }
+ public CharSequence normal() {
+ return (mPlainText != null) ? mPlainText : mNormal;
+ }
+ public CharSequence selected() {
+ return (mPlainText != null) ? mPlainText : mSelected;
+ }
+ public CharSequence pressed() {
+ return (mPlainText != null) ? mPlainText : mPressed;
+ }
+ }
+
private int mBackgroundColor; // the background color to draw in normal state.
private View mView; // the suggestion item's view.
+ private MultiStateText mText1Strings = null;
+ private MultiStateText mText2Strings = null;
protected SuggestionItemView(Context context, Cursor cursor) {
// Initialize ourselves
@@ -537,12 +600,48 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
}
}
+ private void setInitialTextForView(TextView view, MultiStateText multiState,
+ String plainText) {
+ // Set the text even if it's null, since we need to clear any previous text.
+ CharSequence text = (multiState != null) ? multiState.normal() : plainText;
+ view.setText(text);
+
+ if (TextUtils.isEmpty(text)) {
+ view.setVisibility(View.GONE);
+ } else {
+ view.setVisibility(View.VISIBLE);
+ }
+ }
+
+ public void setTextStrings(String text1, String text2, boolean isHtml, Context context) {
+ mText1Strings = new MultiStateText(isHtml, text1, context);
+ mText2Strings = new MultiStateText(isHtml, text2, context);
+
+ ChildViewCache views = (ChildViewCache) getTag();
+ setInitialTextForView(views.mText1, mText1Strings, text1);
+ setInitialTextForView(views.mText2, mText2Strings, text2);
+ }
+
+ public void updateTextViewContentIfRequired() {
+ // Check if the pressed or selected state has changed since the last call.
+ boolean isPressedNow = isPressed();
+ boolean isSelectedNow = isSelected();
+
+ ChildViewCache views = (ChildViewCache) getTag();
+ views.mText1.setText((isPressedNow ? mText1Strings.pressed() :
+ (isSelectedNow ? mText1Strings.selected() : mText1Strings.normal())));
+ views.mText2.setText((isPressedNow ? mText2Strings.pressed() :
+ (isSelectedNow ? mText2Strings.selected() : mText2Strings.normal())));
+ }
+
public void setColor(int backgroundColor) {
mBackgroundColor = backgroundColor;
}
@Override
public void dispatchDraw(Canvas canvas) {
+ updateTextViewContentIfRequired();
+
if (mBackgroundColor != 0 && !isPressed() && !isSelected()) {
canvas.drawColor(mBackgroundColor);
}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index ec671d5..9f01923 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -16,15 +16,27 @@
package android.webkit;
+import android.content.ContentValues;
import android.content.Context;
+import android.content.SharedPreferences;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
+import android.preference.PreferenceManager;
import android.provider.Checkin;
+import android.provider.Settings;
+import android.util.Log;
+import java.io.File;
import java.lang.SecurityException;
+
+import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.database.sqlite.SQLiteStatement;
+import java.util.HashSet;
import java.util.Locale;
/**
@@ -176,6 +188,43 @@ public class WebSettings {
private boolean mBuiltInZoomControls = false;
private boolean mAllowFileAccess = true;
+ // Donut-specific hack to keep Gears permissions in sync with the
+ // system location setting.
+ // TODO: Make sure this hack is removed in Eclair, when Gears
+ // is also removed.
+ // Used to remember if we checked the Gears permissions already.
+ static boolean mCheckedGearsPermissions = false;
+ // The Gears permissions database directory.
+ private final static String GEARS_DATABASE_DIR = "gears";
+ // The Gears permissions database file name.
+ private final static String GEARS_DATABASE_FILE = "permissions.db";
+ // The Gears location permissions table.
+ private final static String GEARS_LOCATION_ACCESS_TABLE_NAME =
+ "LocationAccess";
+ // The Gears storage access permissions table.
+ private final static String GEARS_STORAGE_ACCESS_TABLE_NAME = "Access";
+ // The Gears permissions db schema version table.
+ private final static String GEARS_SCHEMA_VERSION_TABLE_NAME =
+ "VersionInfo";
+ // The shared pref name.
+ private static final String LAST_KNOWN_LOCATION_SETTING =
+ "lastKnownLocationSystemSetting";
+ // The Browser package name.
+ private static final String BROWSER_PACKAGE_NAME = "com.android.browser";
+ // The Google URLs whitelisted for Gears location access.
+ private static HashSet<String> sGearsWhiteList;
+
+ static {
+ sGearsWhiteList = new HashSet<String>();
+ // NOTE: DO NOT ADD A "/" AT THE END!
+ sGearsWhiteList.add("http://www.google.com");
+ sGearsWhiteList.add("http://www.google.co.uk");
+ }
+
+ private static final String LOGTAG = "webcore";
+ static final boolean DEBUG = false;
+ static final boolean LOGV_ENABLED = DEBUG;
+
// Class to handle messages before WebCore is ready.
private class EventHandler {
// Message id for syncing
@@ -196,6 +245,7 @@ public class WebSettings {
switch (msg.what) {
case SYNC:
synchronized (WebSettings.this) {
+ checkGearsPermissions();
if (mBrowserFrame.mNativeFrame != 0) {
nativeSync(mBrowserFrame.mNativeFrame);
}
@@ -1163,6 +1213,126 @@ public class WebSettings {
return size;
}
+ private void checkGearsPermissions() {
+ // Did we already check the permissions?
+ if (mCheckedGearsPermissions) {
+ return;
+ }
+ // Are we running in the browser?
+ if (!BROWSER_PACKAGE_NAME.equals(mContext.getPackageName())) {
+ return;
+ }
+ // Is the pluginsPath sane?
+ if (mPluginsPath == null || mPluginsPath.length() == 0) {
+ // We don't yet have a meaningful plugin path, so
+ // we can't do anything about the Gears permissions.
+ return;
+ }
+ // Remember we checked the Gears permissions.
+ mCheckedGearsPermissions = true;
+ // Get the current system settings.
+ int setting = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.USE_LOCATION_FOR_SERVICES, -1);
+ // Check if we need to set the Gears permissions.
+ if (setting != -1 && locationSystemSettingChanged(setting)) {
+ setGearsPermissionForGoogleDomains(setting);
+ }
+ }
+
+ private boolean locationSystemSettingChanged(int newSetting) {
+ SharedPreferences prefs =
+ PreferenceManager.getDefaultSharedPreferences(mContext);
+ int oldSetting = 0;
+ oldSetting = prefs.getInt(LAST_KNOWN_LOCATION_SETTING, oldSetting);
+ if (oldSetting == newSetting) {
+ return false;
+ }
+ Editor ed = prefs.edit();
+ ed.putInt(LAST_KNOWN_LOCATION_SETTING, newSetting);
+ ed.commit();
+ return true;
+ }
+
+ private void setGearsPermissionForGoogleDomains(int systemPermission) {
+ // Transform the system permission into a Gears permission
+ int gearsPermission = (systemPermission == 1 ? 1 : 2);
+ // Build the path to the Gears library.
+
+ File file = new File(mPluginsPath).getParentFile();
+ if (file == null) {
+ return;
+ }
+ // Build the Gears database file name.
+ file = new File(file.getAbsolutePath() + File.separator
+ + GEARS_DATABASE_DIR + File.separator + GEARS_DATABASE_FILE);
+ // Remember whether or not we need to create the LocationAccess table.
+ boolean needToCreateTables = !file.exists();
+ // Try opening the Gears database.
+ SQLiteDatabase permissions;
+ try {
+ permissions = SQLiteDatabase.openOrCreateDatabase(file, null);
+ } catch (SQLiteException e) {
+ if (LOGV_ENABLED) {
+ Log.v(LOGTAG, "Could not open Gears permission DB: " +
+ e.getMessage());
+ }
+ // Just bail out.
+ return;
+ }
+ // We now have a database open. Begin a transaction.
+ permissions.beginTransaction();
+ try {
+ if (needToCreateTables) {
+ // Create the tables. Note that this creates the
+ // Gears tables for the permissions DB schema version 2.
+ // The Gears schema upgrade process will take care of the rest.
+ // First, the storage access table.
+ SQLiteStatement statement = permissions.compileStatement(
+ "CREATE TABLE IF NOT EXISTS " +
+ GEARS_STORAGE_ACCESS_TABLE_NAME +
+ " (Name TEXT UNIQUE, Value)");
+ statement.execute();
+ // Next the location access table.
+ statement = permissions.compileStatement(
+ "CREATE TABLE IF NOT EXISTS " +
+ GEARS_LOCATION_ACCESS_TABLE_NAME +
+ " (Name TEXT UNIQUE, Value)");
+ statement.execute();
+ // Finally, the schema version table.
+ statement = permissions.compileStatement(
+ "CREATE TABLE IF NOT EXISTS " +
+ GEARS_SCHEMA_VERSION_TABLE_NAME +
+ " (Name TEXT UNIQUE, Value)");
+ statement.execute();
+ // Set the schema version to 2.
+ ContentValues schema = new ContentValues();
+ schema.put("Name", "Version");
+ schema.put("Value", 2);
+ permissions.insert(GEARS_SCHEMA_VERSION_TABLE_NAME, null,
+ schema);
+ }
+
+ ContentValues permissionValues = new ContentValues();
+
+ for (String url : sGearsWhiteList) {
+ permissionValues.put("Name", url);
+ permissionValues.put("Value", gearsPermission);
+ permissions.replace(GEARS_LOCATION_ACCESS_TABLE_NAME, null,
+ permissionValues);
+ permissionValues.clear();
+ }
+ // Commit the transaction.
+ permissions.setTransactionSuccessful();
+ } catch (SQLiteException e) {
+ if (LOGV_ENABLED) {
+ Log.v(LOGTAG, "Could not set the Gears permissions: " +
+ e.getMessage());
+ }
+ } finally {
+ permissions.endTransaction();
+ permissions.close();
+ }
+ }
/* Post a SYNC message to handle syncing the native settings. */
private synchronized void postSync() {
// Only post if a sync is not pending
diff --git a/core/res/res/color/search_url_text.xml b/core/res/res/color/search_url_text.xml
new file mode 100644
index 0000000..449fdf0
--- /dev/null
+++ b/core/res/res/color/search_url_text.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true" android:color="@android:color/search_url_text_pressed"/>
+ <item android:state_selected="true" android:color="@android:color/search_url_text_selected"/>
+ <item android:color="@android:color/search_url_text_normal"/> <!-- not selected -->
+</selector>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index d284d0f..b7de997 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -74,7 +74,9 @@
<color name="perms_normal_perm_color">#c0c0c0</color>
<!-- For search-related UIs -->
- <color name="search_url_text">#7fa87f</color>
+ <color name="search_url_text_normal">#7fa87f</color>
+ <color name="search_url_text_selected">@android:color/black</color>
+ <color name="search_url_text_pressed">@android:color/black</color>
<color name="search_widget_corpus_item_background">@android:color/lighter_gray</color>
</resources>