OLD | NEW |
| (Empty) |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 package org.chromium.android_webview; | |
6 | |
7 import android.content.ContentResolver; | |
8 import android.content.Context; | |
9 import android.database.ContentObserver; | |
10 import android.database.Cursor; | |
11 import android.database.SQLException; | |
12 import android.net.Uri; | |
13 import android.os.AsyncTask; | |
14 import android.os.Handler; | |
15 | |
16 import org.chromium.base.CommandLine; | |
17 import org.chromium.base.Log; | |
18 import org.chromium.base.ThreadUtils; | |
19 | |
20 import java.lang.reflect.Field; | |
21 | |
22 /** | |
23 * Controls data reduction proxy. | |
24 */ | |
25 public final class AwDataReductionProxyManager { | |
26 // The setting Uri. Used when querying GoogleSettings. | |
27 // TODO: This GoogleSettings Uri does not exist yet! | |
28 private static final Uri CONTENT_URI = Uri.parse("content://com.google.setti
ngs/partner"); | |
29 | |
30 // Setting name for allowing data reduction proxy. Used when querying Google
Settings. | |
31 // Setting type: int ( 0 = disallow, 1 = allow ) | |
32 private static final String WEBVIEW_DATA_REDUCTION_PROXY = "use_webview_data
_reduction_proxy"; | |
33 | |
34 private static final String DRP_CLASS = "com.android.webview.chromium.Drp"; | |
35 private static final String TAG = "DRP"; | |
36 | |
37 // This is the same as Chromium data_reduction_proxy::switches::kEnableDataR
eductionProxy. | |
38 private static final String ENABLE_DATA_REDUCTION_PROXY = "enable-spdy-proxy
-auth"; | |
39 // This is the same as Chromium data_reduction_proxy::switches::kDataReducti
onProxyKey. | |
40 private static final String DATA_REDUCTION_PROXY_KEY = "spdy-proxy-auth-valu
e"; | |
41 | |
42 private ContentObserver mProxySettingObserver; | |
43 | |
44 public AwDataReductionProxyManager() {} | |
45 | |
46 public void start(final Context context) { | |
47 // This is the DRP key embedded in WebView apk. | |
48 final String embeddedKey = readKey(); | |
49 | |
50 // Developers could test DRP by passing ENABLE_DATA_REDUCTION_PROXY and
(optionally) | |
51 // DATA_REDUCTION_PROXY_KEY to the commandline switches. In this case,
we will try to | |
52 // initialize DRP from commandline. And ignore user's preference. If | |
53 // DATA_REDUCTION_PROXY_KEY is specified in commandline, use it. Otherw
ise, use the key | |
54 // embedded in WebView apk. | |
55 CommandLine cl = CommandLine.getInstance(); | |
56 if (cl.hasSwitch(ENABLE_DATA_REDUCTION_PROXY)) { | |
57 String key = cl.getSwitchValue(DATA_REDUCTION_PROXY_KEY, embeddedKey
); | |
58 if (key == null || key.isEmpty()) { | |
59 return; | |
60 } | |
61 | |
62 // Now we will enable DRP because we've got a commandline switch to
enable it. | |
63 // We won't listen to Google Settings preference change because comm
andline switches | |
64 // trump that. | |
65 AwContentsStatics.setDataReductionProxyKey(key); | |
66 AwContentsStatics.setDataReductionProxyEnabled(true); | |
67 return; | |
68 } | |
69 | |
70 // Now, there is no commandline switches to enable DRP, and reading the | |
71 // DRP key from WebView apk failed. Just return and leave DRP disabled. | |
72 if (embeddedKey == null || embeddedKey.isEmpty()) { | |
73 return; | |
74 } | |
75 | |
76 applyDataReductionProxySettingsAsync(context, embeddedKey); | |
77 ContentResolver resolver = context.getContentResolver(); | |
78 mProxySettingObserver = new ContentObserver(new Handler()) { | |
79 @Override | |
80 public void onChange(boolean selfChange, Uri uri) { | |
81 applyDataReductionProxySettingsAsync(context, embeddedKey); | |
82 } | |
83 }; | |
84 resolver.registerContentObserver( | |
85 Uri.withAppendedPath(CONTENT_URI, WEBVIEW_DATA_REDUCTION_PROXY),
false, | |
86 mProxySettingObserver); | |
87 } | |
88 | |
89 private String readKey() { | |
90 try { | |
91 Class<?> cls = Class.forName(DRP_CLASS); | |
92 Field f = cls.getField("KEY"); | |
93 return (String) f.get(null); | |
94 } catch (ClassNotFoundException ex) { | |
95 // Class not found is a normal case, simply log. | |
96 Log.i(TAG, "No DRP key due to exception:" + ex); | |
97 } catch (NoSuchFieldException ex) { | |
98 Log.e(TAG, "No DRP key due to exception:" + ex); | |
99 } catch (SecurityException ex) { | |
100 Log.e(TAG, "No DRP key due to exception:" + ex); | |
101 } catch (IllegalArgumentException ex) { | |
102 Log.e(TAG, "No DRP key due to exception:" + ex); | |
103 } catch (IllegalAccessException ex) { | |
104 Log.e(TAG, "No DRP key due to exception:" + ex); | |
105 } catch (NullPointerException ex) { | |
106 Log.e(TAG, "No DRP key due to exception:" + ex); | |
107 } | |
108 return null; | |
109 } | |
110 | |
111 private static void applyDataReductionProxySettingsAsync( | |
112 final Context context, final String key) { | |
113 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() { | |
114 @Override | |
115 public void run() { | |
116 final boolean enabled = isDataReductionProxyEnabled(context); | |
117 | |
118 ThreadUtils.runOnUiThread(new Runnable() { | |
119 @Override | |
120 public void run() { | |
121 if (enabled) { | |
122 // Set the data reduction proxy key. | |
123 AwContentsStatics.setDataReductionProxyKey(key); | |
124 } | |
125 AwContentsStatics.setDataReductionProxyEnabled(enabled); | |
126 } | |
127 }); | |
128 } | |
129 }); | |
130 } | |
131 | |
132 private static boolean isDataReductionProxyEnabled(Context context) { | |
133 return getProxySetting(context.getContentResolver(), WEBVIEW_DATA_REDUCT
ION_PROXY) != 0; | |
134 } | |
135 | |
136 // Read query setting from GoogleSettings. | |
137 private static int getProxySetting(ContentResolver resolver, String name) { | |
138 String value = null; | |
139 Cursor c = null; | |
140 try { | |
141 c = resolver.query( | |
142 CONTENT_URI, new String[] {"value"}, "name=?", new String[]
{name}, null); | |
143 if (c != null && c.moveToNext()) value = c.getString(0); | |
144 } catch (SQLException e) { | |
145 // SQL error: return null, but don't cache it. | |
146 Log.e(TAG, "Can't get key " + name + " from " + CONTENT_URI, e); | |
147 } finally { | |
148 if (c != null) c.close(); | |
149 } | |
150 int enabled = 0; | |
151 try { | |
152 if (value != null) { | |
153 enabled = Integer.parseInt(value); | |
154 } | |
155 } catch (NumberFormatException e) { | |
156 Log.e(TAG, "cannot parse" + value, e); | |
157 } | |
158 return enabled; | |
159 } | |
160 } | |
OLD | NEW |