1a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert/* 2a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * Copyright (C) 2010 The Android Open Source Project 3a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * 4a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 5a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * you may not use this file except in compliance with the License. 6a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * You may obtain a copy of the License at 7a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * 8a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 9a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * 10a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * Unless required by applicable law or agreed to in writing, software 11a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 12a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * See the License for the specific language governing permissions and 14a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * limitations under the License. 15a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert */ 16a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 17a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertpackage com.android.browser; 18a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 19a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertimport android.content.Context; 20a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertimport android.content.SharedPreferences; 21a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertimport android.database.ContentObserver; 22a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertimport android.net.Uri; 23a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertimport android.os.AsyncTask; 24a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertimport android.os.Handler; 25a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertimport android.preference.PreferenceManager; 26a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertimport android.provider.Settings; 27a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertimport android.text.TextUtils; 28a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertimport android.webkit.GeolocationPermissions; 29a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertimport android.webkit.ValueCallback; 30a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 31a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertimport java.util.HashSet; 32a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertimport java.util.Set; 33a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 34a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert/** 35a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * Manages the interaction between the secure system setting for default geolocation 36a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * permissions and the browser. 37a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert */ 38a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringertclass SystemAllowGeolocationOrigins { 39a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 40a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert // Preference key for the value of the system setting last read by the browser 41a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert private final static String LAST_READ_ALLOW_GEOLOCATION_ORIGINS = 42a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert "last_read_allow_geolocation_origins"; 43a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 44a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert // The application context 45a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert private final Context mContext; 46a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 47a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert // The observer used to listen to the system setting. 48a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert private final SettingObserver mSettingObserver; 49a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 50a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert public SystemAllowGeolocationOrigins(Context context) { 51914c5591baeb86bf30a5bc28930071442a822d60Ben Murdoch mContext = context.getApplicationContext(); 52a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert mSettingObserver = new SettingObserver(); 53a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 54a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 55a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert /** 56a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * Checks whether the setting has changed and installs an observer to listen for 57a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * future changes. Must be called on the application main thread. 58a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert */ 59a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert public void start() { 60a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert // Register to receive notifications when the system settings change. 61a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert Uri uri = Settings.Secure.getUriFor(Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS); 62a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert mContext.getContentResolver().registerContentObserver(uri, false, mSettingObserver); 63a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 64a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert // Read and apply the setting if needed. 65a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert maybeApplySettingAsync(); 66a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 67a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 68a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert /** 69a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * Stops the manager. 70a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert */ 71a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert public void stop() { 72a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert mContext.getContentResolver().unregisterContentObserver(mSettingObserver); 73a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 74a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 75a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert void maybeApplySettingAsync() { 76cadae72b6309303bc7b22e85181222b73e176c32John Reck BackgroundHandler.execute(mMaybeApplySetting); 77a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 78a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 79a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert /** 80a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * Checks to see if the system setting has changed and if so, 81a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * updates the Geolocation permissions accordingly. 82a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert */ 83cadae72b6309303bc7b22e85181222b73e176c32John Reck private Runnable mMaybeApplySetting = new Runnable() { 84cadae72b6309303bc7b22e85181222b73e176c32John Reck 85cadae72b6309303bc7b22e85181222b73e176c32John Reck @Override 86cadae72b6309303bc7b22e85181222b73e176c32John Reck public void run() { 87cadae72b6309303bc7b22e85181222b73e176c32John Reck // Get the new value 88cadae72b6309303bc7b22e85181222b73e176c32John Reck String newSetting = getSystemSetting(); 89cadae72b6309303bc7b22e85181222b73e176c32John Reck 90cadae72b6309303bc7b22e85181222b73e176c32John Reck // Get the last read value 91cadae72b6309303bc7b22e85181222b73e176c32John Reck SharedPreferences preferences = BrowserSettings.getInstance() 92cadae72b6309303bc7b22e85181222b73e176c32John Reck .getPreferences(); 93cadae72b6309303bc7b22e85181222b73e176c32John Reck String lastReadSetting = 94cadae72b6309303bc7b22e85181222b73e176c32John Reck preferences.getString(LAST_READ_ALLOW_GEOLOCATION_ORIGINS, ""); 95cadae72b6309303bc7b22e85181222b73e176c32John Reck 96cadae72b6309303bc7b22e85181222b73e176c32John Reck // If the new value is the same as the last one we read, we're done. 97cadae72b6309303bc7b22e85181222b73e176c32John Reck if (TextUtils.equals(lastReadSetting, newSetting)) { 98cadae72b6309303bc7b22e85181222b73e176c32John Reck return; 99cadae72b6309303bc7b22e85181222b73e176c32John Reck } 100a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 101cadae72b6309303bc7b22e85181222b73e176c32John Reck // Save the new value as the last read value 102cadae72b6309303bc7b22e85181222b73e176c32John Reck preferences.edit() 103cadae72b6309303bc7b22e85181222b73e176c32John Reck .putString(LAST_READ_ALLOW_GEOLOCATION_ORIGINS, newSetting) 104cadae72b6309303bc7b22e85181222b73e176c32John Reck .apply(); 105a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 106cadae72b6309303bc7b22e85181222b73e176c32John Reck Set<String> oldOrigins = parseAllowGeolocationOrigins(lastReadSetting); 107cadae72b6309303bc7b22e85181222b73e176c32John Reck Set<String> newOrigins = parseAllowGeolocationOrigins(newSetting); 108cadae72b6309303bc7b22e85181222b73e176c32John Reck Set<String> addedOrigins = setMinus(newOrigins, oldOrigins); 109cadae72b6309303bc7b22e85181222b73e176c32John Reck Set<String> removedOrigins = setMinus(oldOrigins, newOrigins); 110a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 111cadae72b6309303bc7b22e85181222b73e176c32John Reck // Remove the origins in the last read value 112cadae72b6309303bc7b22e85181222b73e176c32John Reck removeOrigins(removedOrigins); 113a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 114cadae72b6309303bc7b22e85181222b73e176c32John Reck // Add the origins in the new value 115cadae72b6309303bc7b22e85181222b73e176c32John Reck addOrigins(addedOrigins); 116cadae72b6309303bc7b22e85181222b73e176c32John Reck } 117cadae72b6309303bc7b22e85181222b73e176c32John Reck }; 118a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 119a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert /** 120a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * Parses the value of the default geolocation permissions setting. 121a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * 122a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * @param setting A space-separated list of origins. 123a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * @return A mutable set of origins. 124a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert */ 125a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert private static HashSet<String> parseAllowGeolocationOrigins(String setting) { 126a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert HashSet<String> origins = new HashSet<String>(); 127a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert if (!TextUtils.isEmpty(setting)) { 128a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert for (String origin : setting.split("\\s+")) { 129a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert if (!TextUtils.isEmpty(origin)) { 130a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert origins.add(origin); 131a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 132a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 133a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 134a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert return origins; 135a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 136a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 137a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert /** 138a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * Gets the difference between two sets. Does not modify any of the arguments. 139a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * 140a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * @return A set containing all elements in {@code x} that are not in {@code y}. 141a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert */ 142a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert private <A> Set<A> setMinus(Set<A> x, Set<A> y) { 143a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert HashSet<A> z = new HashSet<A>(x.size()); 144a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert for (A a : x) { 145a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert if (!y.contains(a)) { 146a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert z.add(a); 147a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 148a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 149a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert return z; 150a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 151a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 152a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert /** 153a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * Gets the current system setting for default allowed geolocation origins. 154a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * 155a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * @return The default allowed origins. Returns {@code ""} if not set. 156a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert */ 157a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert private String getSystemSetting() { 158a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert String value = Settings.Secure.getString(mContext.getContentResolver(), 159a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS); 160a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert return value == null ? "" : value; 161a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 162a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 163a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert /** 164a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * Adds geolocation permissions for the given origins. 165a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert */ 166a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert private void addOrigins(Set<String> origins) { 167a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert for (String origin : origins) { 168a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert GeolocationPermissions.getInstance().allow(origin); 169a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 170a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 171a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 172a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert /** 173a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * Removes geolocation permissions for the given origins, if they are allowed. 174a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * If they are denied or not set, nothing is done. 175a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert */ 176a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert private void removeOrigins(Set<String> origins) { 177a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert for (final String origin : origins) { 178a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert GeolocationPermissions.getInstance().getAllowed(origin, new ValueCallback<Boolean>() { 179a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert public void onReceiveValue(Boolean value) { 180a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert if (value != null && value.booleanValue()) { 181a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert GeolocationPermissions.getInstance().clear(origin); 182a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 183a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 184a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert }); 185a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 186a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 187a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 188a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert /** 189a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert * Listens for changes to the system setting. 190a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert */ 191a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert private class SettingObserver extends ContentObserver { 192a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 193a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert SettingObserver() { 194a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert super(new Handler()); 195a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 196a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 197a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert @Override 198a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert public void onChange(boolean selfChange) { 199a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert maybeApplySettingAsync(); 200a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 201a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert } 202a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert 203a7611811e0d744a7220b7bf80c8f795af5ea53edBjorn Bringert} 204