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