| /* |
| * Copyright (C) 2009 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 android.webkit; |
| |
| import android.content.ContentResolver; |
| import android.content.Context; |
| import android.content.SharedPreferences; |
| import android.content.SharedPreferences.Editor; |
| import android.database.ContentObserver; |
| import android.os.Handler; |
| import android.preference.PreferenceManager; |
| import android.provider.Settings; |
| |
| import java.util.HashSet; |
| |
| /** |
| * A class to manage the interaction between the system setting 'Location & |
| * Security - Share with Google' and the browser. When this setting is set |
| * to true, we allow Geolocation for Google origins. When this setting is |
| * set to false, we clear Geolocation permissions for Google origins. |
| * @hide pending API council review |
| */ |
| class GoogleLocationSettingManager { |
| // The observer used to listen to the system setting. |
| private GoogleLocationSettingObserver mSettingObserver; |
| |
| // The value of the system setting that indicates true. |
| private final static int sSystemSettingTrue = 1; |
| // The value of the system setting that indicates false. |
| private final static int sSystemSettingFalse = 0; |
| // The value of the USE_LOCATION_FOR_SERVICES system setting last read |
| // by the browser. |
| private final static String LAST_READ_USE_LOCATION_FOR_SERVICES = |
| "lastReadUseLocationForServices"; |
| // The Browser package name. |
| private static final String BROWSER_PACKAGE_NAME = "com.android.browser"; |
| // The Google origins we consider. |
| private static HashSet<String> sGoogleOrigins; |
| static { |
| sGoogleOrigins = new HashSet<String>(); |
| // NOTE: DO NOT ADD A "/" AT THE END! |
| sGoogleOrigins.add("http://www.google.com"); |
| sGoogleOrigins.add("http://www.google.co.uk"); |
| } |
| |
| private static GoogleLocationSettingManager sGoogleLocationSettingManager = null; |
| private static int sRefCount = 0; |
| |
| static GoogleLocationSettingManager getInstance() { |
| if (sGoogleLocationSettingManager == null) { |
| sGoogleLocationSettingManager = new GoogleLocationSettingManager(); |
| } |
| return sGoogleLocationSettingManager; |
| } |
| |
| private GoogleLocationSettingManager() {} |
| |
| /** |
| * Starts the manager. Checks whether the setting has changed and |
| * installs an observer to listen for future changes. |
| */ |
| public void start(Context context) { |
| // Are we running in the browser? |
| if (context == null || !BROWSER_PACKAGE_NAME.equals(context.getPackageName())) { |
| return; |
| } |
| // Increase the refCount |
| sRefCount++; |
| // Are we already registered? |
| if (mSettingObserver != null) { |
| return; |
| } |
| // Read and apply the settings if needed. |
| maybeApplySetting(context); |
| // Register to receive notifications when the system settings change. |
| mSettingObserver = new GoogleLocationSettingObserver(); |
| mSettingObserver.observe(context); |
| } |
| |
| /** |
| * Stops the manager. |
| */ |
| public void stop() { |
| // Are we already registered? |
| if (mSettingObserver == null) { |
| return; |
| } |
| if (--sRefCount == 0) { |
| mSettingObserver.doNotObserve(); |
| mSettingObserver = null; |
| } |
| } |
| /** |
| * Checks to see if the system setting has changed and if so, |
| * updates the Geolocation permissions accordingly. |
| * @param the Application context |
| */ |
| private void maybeApplySetting(Context context) { |
| int setting = getSystemSetting(context); |
| if (settingChanged(setting, context)) { |
| applySetting(setting); |
| } |
| } |
| |
| /** |
| * Gets the current system setting for 'Use location for Google services'. |
| * @param the Application context |
| * @return The system setting. |
| */ |
| private int getSystemSetting(Context context) { |
| return Settings.Secure.getInt(context.getContentResolver(), |
| Settings.Secure.USE_LOCATION_FOR_SERVICES, |
| sSystemSettingFalse); |
| } |
| |
| /** |
| * Determines whether the supplied setting has changed from the last |
| * value read by the browser. |
| * @param setting The setting. |
| * @param the Application context |
| * @return Whether the setting has changed from the last value read |
| * by the browser. |
| */ |
| private boolean settingChanged(int setting, Context context) { |
| SharedPreferences preferences = |
| PreferenceManager.getDefaultSharedPreferences(context); |
| // Default to false. If the system setting is false the first time it is ever read by the |
| // browser, there's nothing to do. |
| int lastReadSetting = sSystemSettingFalse; |
| lastReadSetting = preferences.getInt(LAST_READ_USE_LOCATION_FOR_SERVICES, |
| lastReadSetting); |
| |
| if (lastReadSetting == setting) { |
| return false; |
| } |
| |
| Editor editor = preferences.edit(); |
| editor.putInt(LAST_READ_USE_LOCATION_FOR_SERVICES, setting); |
| editor.commit(); |
| return true; |
| } |
| |
| /** |
| * Applies the supplied setting to the Geolocation permissions. |
| * @param setting The setting. |
| */ |
| private void applySetting(int setting) { |
| for (String origin : sGoogleOrigins) { |
| if (setting == sSystemSettingTrue) { |
| GeolocationPermissions.getInstance().allow(origin); |
| } else { |
| GeolocationPermissions.getInstance().clear(origin); |
| } |
| } |
| } |
| |
| /** |
| * This class implements an observer to listen for changes to the |
| * system setting. |
| */ |
| private class GoogleLocationSettingObserver extends ContentObserver { |
| private Context mContext; |
| |
| GoogleLocationSettingObserver() { |
| super(new Handler()); |
| } |
| |
| void observe(Context context) { |
| if (mContext != null) { |
| return; |
| } |
| ContentResolver resolver = context.getContentResolver(); |
| resolver.registerContentObserver(Settings.Secure.getUriFor( |
| Settings.Secure.USE_LOCATION_FOR_SERVICES), false, this); |
| mContext = context; |
| } |
| |
| void doNotObserve() { |
| if (mContext == null) { |
| return; |
| } |
| ContentResolver resolver = mContext.getContentResolver(); |
| resolver.unregisterContentObserver(this); |
| mContext = null; |
| } |
| |
| @Override |
| public void onChange(boolean selfChange) { |
| // This may come after the call to doNotObserve() above, |
| // so mContext may be null. |
| if (mContext != null) { |
| maybeApplySetting(mContext); |
| } |
| } |
| } |
| } |