blob: 7fe449cf1e50b226494edbd4716d488dbab27931 [file] [log] [blame]
/*
* Copyright (C) 2014 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.webview.chromium;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.SQLException;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import android.webkit.WebView;
import org.chromium.android_webview.AwContentsStatics;
import java.lang.reflect.Field;
/**
* Controls data reduction proxy. This logic will be moved to upstream fully.
*/
public final class DataReductionProxyManager {
// The setting Uri. Used when querying GoogleSettings.
private static final Uri CONTENT_URI = Uri.parse("content://com.google.settings/partner");
// Setting name for allowing data reduction proxy. Used when querying GoogleSettings.
// Setting type: int ( 0 = disallow, 1 = allow )
private static final String WEBVIEW_DATA_REDUCTION_PROXY = "use_webview_data_reduction_proxy";
private static final String DRP_CLASS = "com.android.webview.chromium.Drp";
private static final String TAG = "DataReductionProxySettingListener";
/*
* Listen for DataReductionProxySetting changes and take action.
* TODO: This is the old mechanism. Will be obsolete after L release.
* remove before release.
*/
private static final class ProxySettingListener extends BroadcastReceiver {
final String mKey;
ProxySettingListener(final String key) {
mKey = key;
}
@Override
public void onReceive(Context context, Intent intent) {
applyDataReductionProxySettingsAsync(context, mKey);
}
}
private ProxySettingListener mProxySettingListener;
private ContentObserver mProxySettingObserver;
public DataReductionProxyManager() { }
public void start(final Context context) {
final String key = readKey();
if (key == null || key.isEmpty()) {
return;
}
applyDataReductionProxySettingsAsync(context, key);
IntentFilter filter = new IntentFilter();
filter.addAction(WebView.DATA_REDUCTION_PROXY_SETTING_CHANGED);
mProxySettingListener = new ProxySettingListener(key);
context.registerReceiver(mProxySettingListener, filter);
ContentResolver resolver = context.getContentResolver();
mProxySettingObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange, Uri uri) {
applyDataReductionProxySettingsAsync(context, key);
}
};
resolver.registerContentObserver(
Uri.withAppendedPath(CONTENT_URI, WEBVIEW_DATA_REDUCTION_PROXY),
false, mProxySettingObserver);
}
private String readKey() {
try {
Class<?> cls = Class.forName(DRP_CLASS);
Field f = cls.getField("KEY");
return (String) f.get(null);
} catch (ClassNotFoundException ex) {
Log.e(TAG, "No DRP key due to exception:" + ex);
} catch (NoSuchFieldException ex) {
Log.e(TAG, "No DRP key due to exception:" + ex);
} catch (SecurityException ex) {
Log.e(TAG, "No DRP key due to exception:" + ex);
} catch (IllegalArgumentException ex) {
Log.e(TAG, "No DRP key due to exception:" + ex);
} catch (IllegalAccessException ex) {
Log.e(TAG, "No DRP key due to exception:" + ex);
} catch (NullPointerException ex) {
Log.e(TAG, "No DRP key due to exception:" + ex);
}
return null;
}
private static void applyDataReductionProxySettingsAsync(final Context context,
final String key) {
AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... params) {
return isDataReductionProxyEnabled(context);
}
@Override
protected void onPostExecute(Boolean enabled) {
if (enabled) {
// Set the data reduction proxy key.
AwContentsStatics.setDataReductionProxyKey(key);
}
AwContentsStatics.setDataReductionProxyEnabled(enabled);
}
};
task.execute();
}
private static boolean isDataReductionProxyEnabled(Context context) {
boolean enabled = getProxySetting(context.getContentResolver(),
WEBVIEW_DATA_REDUCTION_PROXY) != 0;
// intentional fallback. remove before L release.
if (!enabled) {
enabled = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.WEBVIEW_DATA_REDUCTION_PROXY, 0) != 0;
}
return enabled;
}
// Read query setting from GoogleSettings.
private static int getProxySetting(ContentResolver resolver, String name) {
String value = null;
Cursor c = null;
try {
c = resolver.query(CONTENT_URI, new String[] { "value" },
"name=?", new String[]{ name }, null);
if (c != null && c.moveToNext()) value = c.getString(0);
} catch (SQLException e) {
// SQL error: return null, but don't cache it.
Log.e(TAG, "Can't get key " + name + " from " + CONTENT_URI, e);
} finally {
if (c != null) c.close();
}
int enabled = 0;
try {
if (value != null) {
enabled = Integer.parseInt(value);
}
} catch (NumberFormatException e) {
Log.e(TAG, "cannot parse" + value, e);
}
return enabled;
}
}