• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 
17 package android.webkit;
18 
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.content.SharedPreferences;
22 import android.content.SharedPreferences.Editor;
23 import android.database.ContentObserver;
24 import android.os.Handler;
25 import android.preference.PreferenceManager;
26 import android.provider.Settings;
27 
28 import java.util.HashSet;
29 
30 /**
31  * A class to manage the interaction between the system setting 'Location &
32  * Security - Share with Google' and the browser. When this setting is set
33  * to true, we allow Geolocation for Google origins. When this setting is
34  * set to false, we clear Geolocation permissions for Google origins.
35  */
36 class GoogleLocationSettingManager {
37     // The observer used to listen to the system setting.
38     private GoogleLocationSettingObserver mSettingObserver;
39 
40     // The value of the system setting that indicates true.
41     private final static int sSystemSettingTrue = 1;
42     // The value of the system setting that indicates false.
43     private final static int sSystemSettingFalse = 0;
44     // The value of the USE_LOCATION_FOR_SERVICES system setting last read
45     // by the browser.
46     private final static String LAST_READ_USE_LOCATION_FOR_SERVICES =
47             "lastReadUseLocationForServices";
48     // The Browser package name.
49     private static final String BROWSER_PACKAGE_NAME = "com.android.browser";
50     // The Google origins we consider.
51     private static HashSet<String> sGoogleOrigins;
52     static {
53         sGoogleOrigins = new HashSet<String>();
54         // NOTE: DO NOT ADD A "/" AT THE END!
55         sGoogleOrigins.add("http://www.google.com");
56         sGoogleOrigins.add("http://www.google.co.uk");
57     }
58 
59     private static GoogleLocationSettingManager sGoogleLocationSettingManager = null;
60     private static int sRefCount = 0;
61 
getInstance()62     static GoogleLocationSettingManager getInstance() {
63         if (sGoogleLocationSettingManager == null) {
64             sGoogleLocationSettingManager = new GoogleLocationSettingManager();
65         }
66         return sGoogleLocationSettingManager;
67     }
68 
GoogleLocationSettingManager()69     private GoogleLocationSettingManager() {}
70 
71     /**
72      * Starts the manager. Checks whether the setting has changed and
73      * installs an observer to listen for future changes.
74      */
start(Context context)75     public void start(Context context) {
76         // Are we running in the browser?
77         if (context == null || !BROWSER_PACKAGE_NAME.equals(context.getPackageName())) {
78             return;
79         }
80         // Increase the refCount
81         sRefCount++;
82         // Are we already registered?
83         if (mSettingObserver != null) {
84             return;
85         }
86         // Read and apply the settings if needed.
87         maybeApplySetting(context);
88         // Register to receive notifications when the system settings change.
89         mSettingObserver = new GoogleLocationSettingObserver();
90         mSettingObserver.observe(context);
91     }
92 
93     /**
94      * Stops the manager.
95      */
stop()96     public void stop() {
97         // Are we already registered?
98         if (mSettingObserver == null) {
99             return;
100         }
101         if (--sRefCount == 0) {
102             mSettingObserver.doNotObserve();
103             mSettingObserver = null;
104         }
105     }
106     /**
107      * Checks to see if the system setting has changed and if so,
108      * updates the Geolocation permissions accordingly.
109      * @param the Application context
110      */
maybeApplySetting(Context context)111     private void maybeApplySetting(Context context) {
112         int setting = getSystemSetting(context);
113         if (settingChanged(setting, context)) {
114             applySetting(setting);
115         }
116     }
117 
118     /**
119      * Gets the current system setting for 'Use location for Google services'.
120      * @param the Application context
121      * @return The system setting.
122      */
getSystemSetting(Context context)123     private int getSystemSetting(Context context) {
124         return Settings.Secure.getInt(context.getContentResolver(),
125                                       Settings.Secure.USE_LOCATION_FOR_SERVICES,
126                                       sSystemSettingFalse);
127     }
128 
129     /**
130      * Determines whether the supplied setting has changed from the last
131      * value read by the browser.
132      * @param setting The setting.
133      * @param the Application context
134      * @return Whether the setting has changed from the last value read
135      *     by the browser.
136      */
settingChanged(int setting, Context context)137     private boolean settingChanged(int setting, Context context) {
138         SharedPreferences preferences =
139                 PreferenceManager.getDefaultSharedPreferences(context);
140         // Default to false. If the system setting is false the first time it is ever read by the
141         // browser, there's nothing to do.
142         int lastReadSetting = sSystemSettingFalse;
143         lastReadSetting = preferences.getInt(LAST_READ_USE_LOCATION_FOR_SERVICES,
144                                              lastReadSetting);
145 
146         if (lastReadSetting == setting) {
147             return false;
148         }
149 
150         Editor editor = preferences.edit();
151         editor.putInt(LAST_READ_USE_LOCATION_FOR_SERVICES, setting);
152         editor.commit();
153         return true;
154     }
155 
156     /**
157      * Applies the supplied setting to the Geolocation permissions.
158      * @param setting The setting.
159      */
applySetting(int setting)160     private void applySetting(int setting) {
161         for (String origin : sGoogleOrigins) {
162             if (setting == sSystemSettingTrue) {
163                 GeolocationPermissions.getInstance().allow(origin);
164             } else {
165                 GeolocationPermissions.getInstance().clear(origin);
166             }
167         }
168     }
169 
170     /**
171      * This class implements an observer to listen for changes to the
172      * system setting.
173      */
174     private class GoogleLocationSettingObserver extends ContentObserver {
175         private Context mContext;
176 
GoogleLocationSettingObserver()177         GoogleLocationSettingObserver() {
178             super(new Handler());
179         }
180 
observe(Context context)181         void observe(Context context) {
182             if (mContext != null) {
183                 return;
184             }
185             ContentResolver resolver = context.getContentResolver();
186             resolver.registerContentObserver(Settings.Secure.getUriFor(
187                 Settings.Secure.USE_LOCATION_FOR_SERVICES), false, this);
188             mContext = context;
189         }
190 
doNotObserve()191         void doNotObserve() {
192             if (mContext == null) {
193                 return;
194             }
195             ContentResolver resolver = mContext.getContentResolver();
196             resolver.unregisterContentObserver(this);
197             mContext = null;
198         }
199 
200         @Override
onChange(boolean selfChange)201         public void onChange(boolean selfChange) {
202             // This may come after the call to doNotObserve() above,
203             // so mContext may be null.
204             if (mContext != null) {
205                 maybeApplySetting(mContext);
206             }
207         }
208     }
209 }
210