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

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

Issue 2800833003: Revert of Android: Remove GetApplicationContext part 2 (Closed)
Patch Set: 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;
7 import android.content.res.AssetManager; 8 import android.content.res.AssetManager;
8 import android.net.Uri; 9 import android.net.Uri;
9 import android.util.Log; 10 import android.util.Log;
10 import android.util.TypedValue; 11 import android.util.TypedValue;
11 12
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 * 36 * @param context The context manager.
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(String url) { 41 public static InputStream open(Context context, 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(uri); 50 return openAsset(context, uri);
51 } else if (path.startsWith(nativeGetAndroidResourcePath())) { 51 } else if (path.startsWith(nativeGetAndroidResourcePath())) {
52 return openResource(uri); 52 return openResource(context, uri);
53 } 53 }
54 } else if (uri.getScheme().equals(CONTENT_SCHEME)) { 54 } else if (uri.getScheme().equals(CONTENT_SCHEME)) {
55 return openContent(uri); 55 return openContent(context, 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(String assetType) throws ClassNotFoundExcep tion { 72 private static Class<?> getClazz(Context context, String packageName, String assetType)
73 return ContextUtils.getApplicationContext().getClassLoader().loadClass( 73 throws ClassNotFoundException {
74 ContextUtils.getApplicationContext().getPackageName() + ".R$" + assetType); 74 return context.getClassLoader().loadClass(packageName + ".R$" + assetTyp e);
75 } 75 }
76 76
77 private static int getFieldId(String assetType, String assetName) 77 private static int getFieldId(Context context, String assetType, String asse tName)
78 throws ClassNotFoundException, NoSuchFieldException, IllegalAccessEx ception { 78 throws ClassNotFoundException, NoSuchFieldException, IllegalAccessExcept ion {
79 Class<?> clazz = null; 79 Class<?> clazz = null;
80 try { 80 try {
81 clazz = getClazz(assetType); 81 clazz = getClazz(context, context.getPackageName(), 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 = ContextUtils.getApplicationContext().getPackage Name(); 85 String packageName = context.getPackageName();
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(assetType); 91 clazz = getClazz(context, packageName, 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(int fieldId) { 103 private static int getValueType(Context context, int fieldId) {
104 TypedValue value = new TypedValue(); 104 TypedValue value = new TypedValue();
105 ContextUtils.getApplicationContext().getResources().getValue(fieldId, va lue, true); 105 context.getResources().getValue(fieldId, value, true);
106 return value.type; 106 return value.type;
107 } 107 }
108 108
109 private static InputStream openResource(Uri uri) { 109 private static InputStream openResource(Context context, 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 int fieldId = getFieldId(assetType, assetName); 130 // Use the application context for resolving the resource package na me so that we do
131 int valueType = getValueType(fieldId); 131 // not use the browser's own resources. Note that if 'context' here belongs to the
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);
132 if (valueType == TypedValue.TYPE_STRING) { 139 if (valueType == TypedValue.TYPE_STRING) {
133 return ContextUtils.getApplicationContext().getResources().openR awResource(fieldId); 140 return context.getResources().openRawResource(fieldId);
134 } else { 141 } else {
135 Log.e(TAG, "Asset not of type string: " + uri); 142 Log.e(TAG, "Asset not of type string: " + uri);
136 return null; 143 return null;
137 } 144 }
138 } catch (ClassNotFoundException e) { 145 } catch (ClassNotFoundException e) {
139 Log.e(TAG, "Unable to open resource URL: " + uri, e); 146 Log.e(TAG, "Unable to open resource URL: " + uri, e);
140 return null; 147 return null;
141 } catch (NoSuchFieldException e) { 148 } catch (NoSuchFieldException e) {
142 Log.e(TAG, "Unable to open resource URL: " + uri, e); 149 Log.e(TAG, "Unable to open resource URL: " + uri, e);
143 return null; 150 return null;
144 } catch (IllegalAccessException e) { 151 } catch (IllegalAccessException e) {
145 Log.e(TAG, "Unable to open resource URL: " + uri, e); 152 Log.e(TAG, "Unable to open resource URL: " + uri, e);
146 return null; 153 return null;
147 } 154 }
148 } 155 }
149 156
150 private static InputStream openAsset(Uri uri) { 157 private static InputStream openAsset(Context context, Uri uri) {
151 assert uri.getScheme().equals(FILE_SCHEME); 158 assert uri.getScheme().equals(FILE_SCHEME);
152 assert uri.getPath() != null; 159 assert uri.getPath() != null;
153 assert uri.getPath().startsWith(nativeGetAndroidAssetPath()); 160 assert uri.getPath().startsWith(nativeGetAndroidAssetPath());
154 String path = uri.getPath().replaceFirst(nativeGetAndroidAssetPath(), "" ); 161 String path = uri.getPath().replaceFirst(nativeGetAndroidAssetPath(), "" );
155 try { 162 try {
156 AssetManager assets = ContextUtils.getApplicationContext().getAssets (); 163 AssetManager assets = context.getAssets();
157 return assets.open(path, AssetManager.ACCESS_STREAMING); 164 return assets.open(path, AssetManager.ACCESS_STREAMING);
158 } catch (IOException e) { 165 } catch (IOException e) {
159 Log.e(TAG, "Unable to open asset URL: " + uri); 166 Log.e(TAG, "Unable to open asset URL: " + uri);
160 return null; 167 return null;
161 } 168 }
162 } 169 }
163 170
164 private static InputStream openContent(Uri uri) { 171 private static InputStream openContent(Context context, Uri uri) {
165 assert uri.getScheme().equals(CONTENT_SCHEME); 172 assert uri.getScheme().equals(CONTENT_SCHEME);
166 try { 173 try {
167 return ContextUtils.getApplicationContext().getContentResolver().ope nInputStream(uri); 174 return context.getContentResolver().openInputStream(uri);
168 } catch (Exception e) { 175 } catch (Exception e) {
169 Log.e(TAG, "Unable to open content URL: " + uri); 176 Log.e(TAG, "Unable to open content URL: " + uri);
170 return null; 177 return null;
171 } 178 }
172 } 179 }
173 180
174 /** 181 /**
175 * Determine the mime type for an Android resource. 182 * Determine the mime type for an Android resource.
176 * 183 * @param context The context manager.
177 * @param stream The opened input stream which to examine. 184 * @param stream The opened input stream which to examine.
178 * @param url The url from which the stream was opened. 185 * @param url The url from which the stream was opened.
179 * @return The mime type or null if the type is unknown. 186 * @return The mime type or null if the type is unknown.
180 */ 187 */
181 @CalledByNative 188 @CalledByNative
182 public static String getMimeType(InputStream stream, String url) { 189 public static String getMimeType(Context context, InputStream stream, String url) {
183 Uri uri = verifyUrl(url); 190 Uri uri = verifyUrl(url);
184 if (uri == null) { 191 if (uri == null) {
185 return null; 192 return null;
186 } 193 }
187 try { 194 try {
188 String path = uri.getPath(); 195 String path = uri.getPath();
189 // The content URL type can be queried directly. 196 // The content URL type can be queried directly.
190 if (uri.getScheme().equals(CONTENT_SCHEME)) { 197 if (uri.getScheme().equals(CONTENT_SCHEME)) {
191 return ContextUtils.getApplicationContext().getContentResolver() .getType(uri); 198 return context.getContentResolver().getType(uri);
192 // Asset files may have a known extension. 199 // Asset files may have a known extension.
193 } else if (uri.getScheme().equals(FILE_SCHEME) 200 } else if (uri.getScheme().equals(FILE_SCHEME)
194 && path.startsWith(nativeGetAndroidAssetPath())) { 201 && path.startsWith(nativeGetAndroidAssetPath())) {
195 String mimeType = URLConnection.guessContentTypeFromName(path); 202 String mimeType = URLConnection.guessContentTypeFromName(path);
196 if (mimeType != null) { 203 if (mimeType != null) {
197 return mimeType; 204 return mimeType;
198 } 205 }
199 } 206 }
200 } catch (Exception ex) { 207 } catch (Exception ex) {
201 Log.e(TAG, "Unable to get mime type" + url); 208 Log.e(TAG, "Unable to get mime type" + url);
202 return null; 209 return null;
203 } 210 }
204 // Fall back to sniffing the type from the stream. 211 // Fall back to sniffing the type from the stream.
205 try { 212 try {
206 return URLConnection.guessContentTypeFromStream(stream); 213 return URLConnection.guessContentTypeFromStream(stream);
207 } catch (IOException e) { 214 } catch (IOException e) {
208 return null; 215 return null;
209 } 216 }
210 } 217 }
211 218
212 /** 219 /**
213 * Make sure the given string URL is correctly formed and parse it into a Ur i. 220 * Make sure the given string URL is correctly formed and parse it into a Ur i.
214 *
215 * @return a Uri instance, or null if the URL was invalid. 221 * @return a Uri instance, or null if the URL was invalid.
216 */ 222 */
217 private static Uri verifyUrl(String url) { 223 private static Uri verifyUrl(String url) {
218 if (url == null) { 224 if (url == null) {
219 return null; 225 return null;
220 } 226 }
221 Uri uri = Uri.parse(url); 227 Uri uri = Uri.parse(url);
222 if (uri == null) { 228 if (uri == null) {
223 Log.e(TAG, "Malformed URL: " + url); 229 Log.e(TAG, "Malformed URL: " + url);
224 return null; 230 return null;
225 } 231 }
226 String path = uri.getPath(); 232 String path = uri.getPath();
227 if (path == null || path.length() == 0) { 233 if (path == null || path.length() == 0) {
228 Log.e(TAG, "URL does not have a path: " + url); 234 Log.e(TAG, "URL does not have a path: " + url);
229 return null; 235 return null;
230 } 236 }
231 return uri; 237 return uri;
232 } 238 }
233 239
240 /**
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
249 private static native void nativeSetResourceContextForTesting(Context contex t);
234 private static native String nativeGetAndroidAssetPath(); 250 private static native String nativeGetAndroidAssetPath();
235
236 private static native String nativeGetAndroidResourcePath(); 251 private static native String nativeGetAndroidResourcePath();
237 } 252 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698