import android.util.Log;
import android.util.Patterns;
import android.util.TypedValue;
-import android.webkit.GeolocationPermissions;
import java.io.File;
"viewer?source=androidclient";
private static final String[] TABLE_NAMES = new String[] {
- "bookmarks", "searches", "geolocation"
+ "bookmarks", "searches"
};
private static final String[] SUGGEST_PROJECTION = new String[] {
"_id", "url", "title", "bookmark", "user_entered"
// make sure that these match the index of TABLE_NAMES
private static final int URI_MATCH_BOOKMARKS = 0;
private static final int URI_MATCH_SEARCHES = 1;
- private static final int URI_MATCH_GEOLOCATION = 2;
// (id % 10) should match the table name index
private static final int URI_MATCH_BOOKMARKS_ID = 10;
private static final int URI_MATCH_SEARCHES_ID = 11;
URI_MATCHER.addURI("browser",
TABLE_NAMES[URI_MATCH_BOOKMARKS] + "/" + SearchManager.SUGGEST_URI_PATH_QUERY,
URI_MATCH_BOOKMARKS_SUGGEST);
- URI_MATCHER.addURI("browser", TABLE_NAMES[URI_MATCH_GEOLOCATION],
- URI_MATCH_GEOLOCATION);
}
// 1 -> 2 add cache table
if (match == -1) {
throw new IllegalArgumentException("Unknown URL");
}
- if (match == URI_MATCH_GEOLOCATION) {
- throw new UnsupportedOperationException("query() not supported for geolocation");
- }
if (match == URI_MATCH_SUGGEST && mResultsCursor != null) {
Cursor results = mResultsCursor;
mResultsCursor = null;
case URI_MATCH_SUGGEST:
return SearchManager.SUGGEST_MIME_TYPE;
- case URI_MATCH_GEOLOCATION:
- return "vnd.android.cursor.dir/geolocation";
-
default:
throw new IllegalArgumentException("Unknown URL");
}
break;
}
- case URI_MATCH_GEOLOCATION:
- String origin = initialValues.getAsString(Browser.GeolocationColumns.ORIGIN);
- if (TextUtils.isEmpty(origin)) {
- throw new IllegalArgumentException("Empty origin");
- }
- GeolocationPermissions.getInstance().allow(origin);
- // TODO: Should we have one URI per permission?
- uri = Browser.GEOLOCATION_URI;
- break;
-
default:
throw new IllegalArgumentException("Unknown URL");
}
throw new IllegalArgumentException("Unknown URL");
}
- if (match == URI_MATCH_GEOLOCATION) {
- return deleteGeolocation(url, where, whereArgs);
- }
-
// need to know whether it's the bookmarks table for a couple of reasons
boolean isBookmarkTable = (match == URI_MATCH_BOOKMARKS_ID);
String id = null;
return count;
}
- private int deleteGeolocation(Uri uri, String where, String[] whereArgs) {
- if (whereArgs.length != 1) {
- throw new IllegalArgumentException("Bad where arguments");
- }
- String origin = whereArgs[0];
- if (TextUtils.isEmpty(origin)) {
- throw new IllegalArgumentException("Empty origin");
- }
- GeolocationPermissions.getInstance().clear(origin);
- getContext().getContentResolver().notifyChange(Browser.GEOLOCATION_URI, null);
- return 1; // We always return 1, to avoid having to check whether anything was actually removed
- }
-
@Override
public int update(Uri url, ContentValues values, String where,
String[] whereArgs) {
--- /dev/null
+/*
+ * Copyright (C) 2010 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.content.SharedPreferences;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.preference.PreferenceManager;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.webkit.GeolocationPermissions;
+import android.webkit.ValueCallback;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Manages the interaction between the secure system setting for default geolocation
+ * permissions and the browser.
+ */
+class SystemAllowGeolocationOrigins {
+
+ // Preference key for the value of the system setting last read by the browser
+ private final static String LAST_READ_ALLOW_GEOLOCATION_ORIGINS =
+ "last_read_allow_geolocation_origins";
+
+ // The application context
+ private final Context mContext;
+
+ // The observer used to listen to the system setting.
+ private final SettingObserver mSettingObserver;
+
+ public SystemAllowGeolocationOrigins(Context context) {
+ mContext = context;
+ mSettingObserver = new SettingObserver();
+ }
+
+ /**
+ * Checks whether the setting has changed and installs an observer to listen for
+ * future changes. Must be called on the application main thread.
+ */
+ public void start() {
+ // Register to receive notifications when the system settings change.
+ Uri uri = Settings.Secure.getUriFor(Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS);
+ mContext.getContentResolver().registerContentObserver(uri, false, mSettingObserver);
+
+ // Read and apply the setting if needed.
+ maybeApplySettingAsync();
+ }
+
+ /**
+ * Stops the manager.
+ */
+ public void stop() {
+ mContext.getContentResolver().unregisterContentObserver(mSettingObserver);
+ }
+
+ void maybeApplySettingAsync() {
+ new AsyncTask<Void,Void,Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ maybeApplySetting();
+ return null;
+ }
+ }.execute();
+ }
+
+ /**
+ * Checks to see if the system setting has changed and if so,
+ * updates the Geolocation permissions accordingly.
+ */
+ private void maybeApplySetting() {
+ // Get the new value
+ String newSetting = getSystemSetting();
+
+ // Get the last read value
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
+ String lastReadSetting =
+ preferences.getString(LAST_READ_ALLOW_GEOLOCATION_ORIGINS, "");
+
+ // If the new value is the same as the last one we read, we're done.
+ if (TextUtils.equals(lastReadSetting, newSetting)) {
+ return;
+ }
+
+ // Save the new value as the last read value
+ preferences.edit()
+ .putString(LAST_READ_ALLOW_GEOLOCATION_ORIGINS, newSetting)
+ .commit();
+
+ Set<String> oldOrigins = parseAllowGeolocationOrigins(lastReadSetting);
+ Set<String> newOrigins = parseAllowGeolocationOrigins(newSetting);
+ Set<String> addedOrigins = setMinus(newOrigins, oldOrigins);
+ Set<String> removedOrigins = setMinus(oldOrigins, newOrigins);
+
+ // Remove the origins in the last read value
+ removeOrigins(removedOrigins);
+
+ // Add the origins in the new value
+ addOrigins(addedOrigins);
+ }
+
+ /**
+ * Parses the value of the default geolocation permissions setting.
+ *
+ * @param setting A space-separated list of origins.
+ * @return A mutable set of origins.
+ */
+ private static HashSet<String> parseAllowGeolocationOrigins(String setting) {
+ HashSet<String> origins = new HashSet<String>();
+ if (!TextUtils.isEmpty(setting)) {
+ for (String origin : setting.split("\\s+")) {
+ if (!TextUtils.isEmpty(origin)) {
+ origins.add(origin);
+ }
+ }
+ }
+ return origins;
+ }
+
+ /**
+ * Gets the difference between two sets. Does not modify any of the arguments.
+ *
+ * @return A set containing all elements in {@code x} that are not in {@code y}.
+ */
+ private <A> Set<A> setMinus(Set<A> x, Set<A> y) {
+ HashSet<A> z = new HashSet<A>(x.size());
+ for (A a : x) {
+ if (!y.contains(a)) {
+ z.add(a);
+ }
+ }
+ return z;
+ }
+
+ /**
+ * Gets the current system setting for default allowed geolocation origins.
+ *
+ * @return The default allowed origins. Returns {@code ""} if not set.
+ */
+ private String getSystemSetting() {
+ String value = Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS);
+ return value == null ? "" : value;
+ }
+
+ /**
+ * Adds geolocation permissions for the given origins.
+ */
+ private void addOrigins(Set<String> origins) {
+ for (String origin : origins) {
+ GeolocationPermissions.getInstance().allow(origin);
+ }
+ }
+
+ /**
+ * Removes geolocation permissions for the given origins, if they are allowed.
+ * If they are denied or not set, nothing is done.
+ */
+ private void removeOrigins(Set<String> origins) {
+ for (final String origin : origins) {
+ GeolocationPermissions.getInstance().getAllowed(origin, new ValueCallback<Boolean>() {
+ public void onReceiveValue(Boolean value) {
+ if (value != null && value.booleanValue()) {
+ GeolocationPermissions.getInstance().clear(origin);
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Listens for changes to the system setting.
+ */
+ private class SettingObserver extends ContentObserver {
+
+ SettingObserver() {
+ super(new Handler());
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ maybeApplySettingAsync();
+ }
+ }
+
+}