OSDN Git Service

Use system setting for default geolocation permissions
authorBjorn Bringert <bringert@android.com>
Wed, 24 Mar 2010 11:12:02 +0000 (11:12 +0000)
committerBjorn Bringert <bringert@android.com>
Thu, 25 Mar 2010 13:54:17 +0000 (13:54 +0000)
This reverts change I0be5dbf4d99d07ca13b07fb299155c5aa17a51bd
and adds an observer on the new default geolocation permission
secure setting.

Bug http://b/issue?id=2535598

Change-Id: I4edcbd3080b7d3af5dc6d74f26779b6d92248010

AndroidManifest.xml
src/com/android/browser/BrowserActivity.java
src/com/android/browser/BrowserProvider.java
src/com/android/browser/SystemAllowGeolocationOrigins.java [new file with mode: 0644]

index 50a7be0..7e98019 100644 (file)
@@ -47,8 +47,6 @@
                   android:writePermission="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS">
             <path-permission android:path="/bookmarks/search_suggest_query"
                     android:readPermission="android.permission.GLOBAL_SEARCH" />
-            <path-permission android:path="/geolocation"
-                    android:writePermission="com.android.browser.permission.WRITE_GEOLOCATION_PERMISSIONS" />
         </provider>
         <activity android:name="BrowserActivity"
                   android:label="@string/application_name"
index ff16e4e..406132f 100644 (file)
@@ -365,6 +365,11 @@ public class BrowserActivity extends Activity
         }
         // Work out which packages are installed on the system.
         getInstalledPackages();
+
+        // Start watching the default geolocation permissions
+        mSystemAllowGeolocationOrigins
+                = new SystemAllowGeolocationOrigins(getApplicationContext());
+        mSystemAllowGeolocationOrigins.start();
     }
 
     /**
@@ -981,6 +986,10 @@ public class BrowserActivity extends Activity
         WebIconDatabase.getInstance().close();
 
         unregisterReceiver(mPackageInstallationReceiver);
+
+        // Stop watching the default geolocation permissions
+        mSystemAllowGeolocationOrigins.stop();
+        mSystemAllowGeolocationOrigins = null;
     }
 
     @Override
@@ -3872,6 +3881,8 @@ public class BrowserActivity extends Activity
 
     private BroadcastReceiver mPackageInstallationReceiver;
 
+    private SystemAllowGeolocationOrigins mSystemAllowGeolocationOrigins;
+
     // activity requestCode
     final static int COMBO_PAGE                 = 1;
     final static int DOWNLOAD_PAGE              = 2;
index 501a52a..bf1f9d5 100644 (file)
@@ -48,7 +48,6 @@ import android.text.TextUtils;
 import android.util.Log;
 import android.util.Patterns;
 import android.util.TypedValue;
-import android.webkit.GeolocationPermissions;
 
 
 import java.io.File;
@@ -71,7 +70,7 @@ public class BrowserProvider extends ContentProvider {
             "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"
@@ -113,7 +112,6 @@ public class BrowserProvider extends ContentProvider {
     // 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;
@@ -138,8 +136,6 @@ public class BrowserProvider extends ContentProvider {
         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
@@ -839,9 +835,6 @@ public class BrowserProvider extends ContentProvider {
         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;
@@ -942,9 +935,6 @@ public class BrowserProvider extends ContentProvider {
             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");
         }
@@ -981,16 +971,6 @@ public class BrowserProvider extends ContentProvider {
                 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");
         }
@@ -1020,10 +1000,6 @@ public class BrowserProvider extends ContentProvider {
             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;
@@ -1062,19 +1038,6 @@ public class BrowserProvider extends ContentProvider {
         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) {
diff --git a/src/com/android/browser/SystemAllowGeolocationOrigins.java b/src/com/android/browser/SystemAllowGeolocationOrigins.java
new file mode 100644 (file)
index 0000000..3f5a84e
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * 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();
+        }
+    }
+
+}