Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: android_webview/java/src/org/chromium/android_webview/AndroidProtocolHandler.java

Issue 2784353002: Android: Remove GetApplicationContext part 2 (Closed)
Patch Set: Fix tests Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.android_webview; 5 package org.chromium.android_webview;
6 6
7 import android.content.Context;
8 import android.content.res.AssetManager; 7 import android.content.res.AssetManager;
9 import android.net.Uri; 8 import android.net.Uri;
10 import android.util.Log; 9 import android.util.Log;
11 import android.util.TypedValue; 10 import android.util.TypedValue;
12 11
12 import org.chromium.base.ContextUtils;
13 import org.chromium.base.annotations.CalledByNative; 13 import org.chromium.base.annotations.CalledByNative;
14 import org.chromium.base.annotations.JNINamespace; 14 import org.chromium.base.annotations.JNINamespace;
15 15
16 import java.io.IOException; 16 import java.io.IOException;
17 import java.io.InputStream; 17 import java.io.InputStream;
18 import java.net.URLConnection; 18 import java.net.URLConnection;
19 import java.util.List; 19 import java.util.List;
20 20
21 /** 21 /**
22 * Implements the Java side of Android URL protocol jobs. 22 * Implements the Java side of Android URL protocol jobs.
23 * See android_protocol_handler.cc. 23 * See android_protocol_handler.cc.
24 */ 24 */
25 @JNINamespace("android_webview") 25 @JNINamespace("android_webview")
26 public class AndroidProtocolHandler { 26 public class AndroidProtocolHandler {
27 private static final String TAG = "AndroidProtocolHandler"; 27 private static final String TAG = "AndroidProtocolHandler";
28 28
29 // Supported URL schemes. This needs to be kept in sync with 29 // Supported URL schemes. This needs to be kept in sync with
30 // clank/native/framework/chrome/url_request_android_job.cc. 30 // clank/native/framework/chrome/url_request_android_job.cc.
31 private static final String FILE_SCHEME = "file"; 31 private static final String FILE_SCHEME = "file";
32 private static final String CONTENT_SCHEME = "content"; 32 private static final String CONTENT_SCHEME = "content";
33 33
34 /** 34 /**
35 * Open an InputStream for an Android resource. 35 * Open an InputStream for an Android resource.
36 * @param context The context manager. 36 *
37 * @param url The url to load. 37 * @param url The url to load.
38 * @return An InputStream to the Android resource. 38 * @return An InputStream to the Android resource.
39 */ 39 */
40 @CalledByNative 40 @CalledByNative
41 public static InputStream open(Context context, String url) { 41 public static InputStream open(String url) {
42 Uri uri = verifyUrl(url); 42 Uri uri = verifyUrl(url);
43 if (uri == null) { 43 if (uri == null) {
44 return null; 44 return null;
45 } 45 }
46 try { 46 try {
47 String path = uri.getPath(); 47 String path = uri.getPath();
48 if (uri.getScheme().equals(FILE_SCHEME)) { 48 if (uri.getScheme().equals(FILE_SCHEME)) {
49 if (path.startsWith(nativeGetAndroidAssetPath())) { 49 if (path.startsWith(nativeGetAndroidAssetPath())) {
50 return openAsset(context, uri); 50 return openAsset(uri);
51 } else if (path.startsWith(nativeGetAndroidResourcePath())) { 51 } else if (path.startsWith(nativeGetAndroidResourcePath())) {
52 return openResource(context, uri); 52 return openResource(uri);
53 } 53 }
54 } else if (uri.getScheme().equals(CONTENT_SCHEME)) { 54 } else if (uri.getScheme().equals(CONTENT_SCHEME)) {
55 return openContent(context, uri); 55 return openContent(uri);
56 } 56 }
57 } catch (Exception ex) { 57 } catch (Exception ex) {
58 Log.e(TAG, "Error opening inputstream: " + url); 58 Log.e(TAG, "Error opening inputstream: " + url);
59 } 59 }
60 return null; 60 return null;
61 } 61 }
62 62
63 // Assumes input string is in the format "foo.bar.baz" and strips out the la st component. 63 // Assumes input string is in the format "foo.bar.baz" and strips out the la st component.
64 // Returns null on failure. 64 // Returns null on failure.
65 private static String removeOneSuffix(String input) { 65 private static String removeOneSuffix(String input) {
66 if (input == null) return null; 66 if (input == null) return null;
67 int lastDotIndex = input.lastIndexOf('.'); 67 int lastDotIndex = input.lastIndexOf('.');
68 if (lastDotIndex == -1) return null; 68 if (lastDotIndex == -1) return null;
69 return input.substring(0, lastDotIndex); 69 return input.substring(0, lastDotIndex);
70 } 70 }
71 71
72 private static Class<?> getClazz(Context context, String packageName, String assetType) 72 private static Class<?> getClazz(String assetType) throws ClassNotFoundExcep tion {
73 throws ClassNotFoundException { 73 return ContextUtils.getApplicationContext().getClassLoader().loadClass(
74 return context.getClassLoader().loadClass(packageName + ".R$" + assetTyp e); 74 ContextUtils.getApplicationContext().getPackageName() + ".R$" + assetType);
75 } 75 }
76 76
77 private static int getFieldId(Context context, String assetType, String asse tName) 77 private static int getFieldId(String assetType, String assetName)
78 throws ClassNotFoundException, NoSuchFieldException, IllegalAccessExcept ion { 78 throws ClassNotFoundException, NoSuchFieldException, IllegalAccessEx ception {
79 Class<?> clazz = null; 79 Class<?> clazz = null;
80 try { 80 try {
81 clazz = getClazz(context, context.getPackageName(), assetType); 81 clazz = getClazz(assetType);
82 } catch (ClassNotFoundException e) { 82 } catch (ClassNotFoundException e) {
83 // Strip out components from the end so gradle generated application suffix such as 83 // Strip out components from the end so gradle generated application suffix such as
84 // com.example.my.pkg.pro works. This is by no means bulletproof. 84 // com.example.my.pkg.pro works. This is by no means bulletproof.
85 String packageName = context.getPackageName(); 85 String packageName = ContextUtils.getApplicationContext().getPackage Name();
86 while (clazz == null) { 86 while (clazz == null) {
87 packageName = removeOneSuffix(packageName); 87 packageName = removeOneSuffix(packageName);
88 // Throw original exception which contains the entire package id . 88 // Throw original exception which contains the entire package id .
89 if (packageName == null) throw e; 89 if (packageName == null) throw e;
90 try { 90 try {
91 clazz = getClazz(context, packageName, assetType); 91 clazz = getClazz(assetType);
92 } catch (ClassNotFoundException ignored) { 92 } catch (ClassNotFoundException ignored) {
93 // Strip and try again. 93 // Strip and try again.
94 } 94 }
95 } 95 }
96 } 96 }
97 97
98 java.lang.reflect.Field field = clazz.getField(assetName); 98 java.lang.reflect.Field field = clazz.getField(assetName);
99 int id = field.getInt(null); 99 int id = field.getInt(null);
100 return id; 100 return id;
101 } 101 }
102 102
103 private static int getValueType(Context context, int fieldId) { 103 private static int getValueType(int fieldId) {
104 TypedValue value = new TypedValue(); 104 TypedValue value = new TypedValue();
105 context.getResources().getValue(fieldId, value, true); 105 ContextUtils.getApplicationContext().getResources().getValue(fieldId, va lue, true);
106 return value.type; 106 return value.type;
107 } 107 }
108 108
109 private static InputStream openResource(Context context, Uri uri) { 109 private static InputStream openResource(Uri uri) {
110 assert uri.getScheme().equals(FILE_SCHEME); 110 assert uri.getScheme().equals(FILE_SCHEME);
111 assert uri.getPath() != null; 111 assert uri.getPath() != null;
112 assert uri.getPath().startsWith(nativeGetAndroidResourcePath()); 112 assert uri.getPath().startsWith(nativeGetAndroidResourcePath());
113 // The path must be of the form "/android_res/asset_type/asset_name.ext" . 113 // The path must be of the form "/android_res/asset_type/asset_name.ext" .
114 List<String> pathSegments = uri.getPathSegments(); 114 List<String> pathSegments = uri.getPathSegments();
115 if (pathSegments.size() != 3) { 115 if (pathSegments.size() != 3) {
116 Log.e(TAG, "Incorrect resource path: " + uri); 116 Log.e(TAG, "Incorrect resource path: " + uri);
117 return null; 117 return null;
118 } 118 }
119 String assetPath = pathSegments.get(0); 119 String assetPath = pathSegments.get(0);
120 String assetType = pathSegments.get(1); 120 String assetType = pathSegments.get(1);
121 String assetName = pathSegments.get(2); 121 String assetName = pathSegments.get(2);
122 if (!("/" + assetPath + "/").equals(nativeGetAndroidResourcePath())) { 122 if (!("/" + assetPath + "/").equals(nativeGetAndroidResourcePath())) {
123 Log.e(TAG, "Resource path does not start with " + nativeGetAndroidRe sourcePath() 123 Log.e(TAG, "Resource path does not start with " + nativeGetAndroidRe sourcePath()
124 + ": " + uri); 124 + ": " + uri);
125 return null; 125 return null;
126 } 126 }
127 // Drop the file extension. 127 // Drop the file extension.
128 assetName = assetName.split("\\.")[0]; 128 assetName = assetName.split("\\.")[0];
129 try { 129 try {
130 // Use the application context for resolving the resource package na me so that we do 130 int fieldId = getFieldId(assetType, assetName);
131 // not use the browser's own resources. Note that if 'context' here belongs to the 131 int valueType = getValueType(fieldId);
132 // test suite, it does not have a separate application context. In t hat case we use
133 // the original context object directly.
134 if (context.getApplicationContext() != null) {
135 context = context.getApplicationContext();
136 }
137 int fieldId = getFieldId(context, assetType, assetName);
138 int valueType = getValueType(context, fieldId);
139 if (valueType == TypedValue.TYPE_STRING) { 132 if (valueType == TypedValue.TYPE_STRING) {
140 return context.getResources().openRawResource(fieldId); 133 return ContextUtils.getApplicationContext().getResources().openR awResource(fieldId);
141 } else { 134 } else {
142 Log.e(TAG, "Asset not of type string: " + uri); 135 Log.e(TAG, "Asset not of type string: " + uri);
143 return null; 136 return null;
144 } 137 }
145 } catch (ClassNotFoundException e) { 138 } catch (ClassNotFoundException e) {
146 Log.e(TAG, "Unable to open resource URL: " + uri, e); 139 Log.e(TAG, "Unable to open resource URL: " + uri, e);
147 return null; 140 return null;
148 } catch (NoSuchFieldException e) { 141 } catch (NoSuchFieldException e) {
149 Log.e(TAG, "Unable to open resource URL: " + uri, e); 142 Log.e(TAG, "Unable to open resource URL: " + uri, e);
150 return null; 143 return null;
151 } catch (IllegalAccessException e) { 144 } catch (IllegalAccessException e) {
152 Log.e(TAG, "Unable to open resource URL: " + uri, e); 145 Log.e(TAG, "Unable to open resource URL: " + uri, e);
153 return null; 146 return null;
154 } 147 }
155 } 148 }
156 149
157 private static InputStream openAsset(Context context, Uri uri) { 150 private static InputStream openAsset(Uri uri) {
158 assert uri.getScheme().equals(FILE_SCHEME); 151 assert uri.getScheme().equals(FILE_SCHEME);
159 assert uri.getPath() != null; 152 assert uri.getPath() != null;
160 assert uri.getPath().startsWith(nativeGetAndroidAssetPath()); 153 assert uri.getPath().startsWith(nativeGetAndroidAssetPath());
161 String path = uri.getPath().replaceFirst(nativeGetAndroidAssetPath(), "" ); 154 String path = uri.getPath().replaceFirst(nativeGetAndroidAssetPath(), "" );
162 try { 155 try {
163 AssetManager assets = context.getAssets(); 156 AssetManager assets = ContextUtils.getApplicationContext().getAssets ();
164 return assets.open(path, AssetManager.ACCESS_STREAMING); 157 return assets.open(path, AssetManager.ACCESS_STREAMING);
165 } catch (IOException e) { 158 } catch (IOException e) {
166 Log.e(TAG, "Unable to open asset URL: " + uri); 159 Log.e(TAG, "Unable to open asset URL: " + uri);
167 return null; 160 return null;
168 } 161 }
169 } 162 }
170 163
171 private static InputStream openContent(Context context, Uri uri) { 164 private static InputStream openContent(Uri uri) {
172 assert uri.getScheme().equals(CONTENT_SCHEME); 165 assert uri.getScheme().equals(CONTENT_SCHEME);
173 try { 166 try {
174 return context.getContentResolver().openInputStream(uri); 167 return ContextUtils.getApplicationContext().getContentResolver().ope nInputStream(uri);
175 } catch (Exception e) { 168 } catch (Exception e) {
176 Log.e(TAG, "Unable to open content URL: " + uri); 169 Log.e(TAG, "Unable to open content URL: " + uri);
177 return null; 170 return null;
178 } 171 }
179 } 172 }
180 173
181 /** 174 /**
182 * Determine the mime type for an Android resource. 175 * Determine the mime type for an Android resource.
183 * @param context The context manager. 176 *
184 * @param stream The opened input stream which to examine. 177 * @param stream The opened input stream which to examine.
185 * @param url The url from which the stream was opened. 178 * @param url The url from which the stream was opened.
186 * @return The mime type or null if the type is unknown. 179 * @return The mime type or null if the type is unknown.
187 */ 180 */
188 @CalledByNative 181 @CalledByNative
189 public static String getMimeType(Context context, InputStream stream, String url) { 182 public static String getMimeType(InputStream stream, String url) {
190 Uri uri = verifyUrl(url); 183 Uri uri = verifyUrl(url);
191 if (uri == null) { 184 if (uri == null) {
192 return null; 185 return null;
193 } 186 }
194 try { 187 try {
195 String path = uri.getPath(); 188 String path = uri.getPath();
196 // The content URL type can be queried directly. 189 // The content URL type can be queried directly.
197 if (uri.getScheme().equals(CONTENT_SCHEME)) { 190 if (uri.getScheme().equals(CONTENT_SCHEME)) {
198 return context.getContentResolver().getType(uri); 191 return ContextUtils.getApplicationContext().getContentResolver() .getType(uri);
199 // Asset files may have a known extension. 192 // Asset files may have a known extension.
200 } else if (uri.getScheme().equals(FILE_SCHEME) 193 } else if (uri.getScheme().equals(FILE_SCHEME)
201 && path.startsWith(nativeGetAndroidAssetPath())) { 194 && path.startsWith(nativeGetAndroidAssetPath())) {
202 String mimeType = URLConnection.guessContentTypeFromName(path); 195 String mimeType = URLConnection.guessContentTypeFromName(path);
203 if (mimeType != null) { 196 if (mimeType != null) {
204 return mimeType; 197 return mimeType;
205 } 198 }
206 } 199 }
207 } catch (Exception ex) { 200 } catch (Exception ex) {
208 Log.e(TAG, "Unable to get mime type" + url); 201 Log.e(TAG, "Unable to get mime type" + url);
209 return null; 202 return null;
210 } 203 }
211 // Fall back to sniffing the type from the stream. 204 // Fall back to sniffing the type from the stream.
212 try { 205 try {
213 return URLConnection.guessContentTypeFromStream(stream); 206 return URLConnection.guessContentTypeFromStream(stream);
214 } catch (IOException e) { 207 } catch (IOException e) {
215 return null; 208 return null;
216 } 209 }
217 } 210 }
218 211
219 /** 212 /**
220 * Make sure the given string URL is correctly formed and parse it into a Ur i. 213 * Make sure the given string URL is correctly formed and parse it into a Ur i.
214 *
221 * @return a Uri instance, or null if the URL was invalid. 215 * @return a Uri instance, or null if the URL was invalid.
222 */ 216 */
223 private static Uri verifyUrl(String url) { 217 private static Uri verifyUrl(String url) {
224 if (url == null) { 218 if (url == null) {
225 return null; 219 return null;
226 } 220 }
227 Uri uri = Uri.parse(url); 221 Uri uri = Uri.parse(url);
228 if (uri == null) { 222 if (uri == null) {
229 Log.e(TAG, "Malformed URL: " + url); 223 Log.e(TAG, "Malformed URL: " + url);
230 return null; 224 return null;
231 } 225 }
232 String path = uri.getPath(); 226 String path = uri.getPath();
233 if (path == null || path.length() == 0) { 227 if (path == null || path.length() == 0) {
234 Log.e(TAG, "URL does not have a path: " + url); 228 Log.e(TAG, "URL does not have a path: " + url);
235 return null; 229 return null;
236 } 230 }
237 return uri; 231 return uri;
238 } 232 }
239 233
240 /** 234 private static native String nativeGetAndroidAssetPath();
241 * Set the context to be used for resolving resource queries.
242 * @param context Context to be used, or null for the default application
243 * context.
244 */
245 public static void setResourceContextForTesting(Context context) {
246 nativeSetResourceContextForTesting(context);
247 }
248 235
249 private static native void nativeSetResourceContextForTesting(Context contex t);
250 private static native String nativeGetAndroidAssetPath();
251 private static native String nativeGetAndroidResourcePath(); 236 private static native String nativeGetAndroidResourcePath();
252 } 237 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698