├── .gitignore
├── LICENSE
├── README.md
├── build.gradle
└── src
├── androidTest
├── AndroidManifest.xml
├── assets
│ └── www
│ │ └── test_with_title.html
├── java
│ └── com
│ │ └── google
│ │ └── webviewlocalserver
│ │ ├── IntegrationTest.java
│ │ ├── TestActivity.java
│ │ ├── UriMatcherTest.java
│ │ └── WebViewLocalServerTest.java
└── res
│ ├── drawable-hdpi
│ └── ic_launcher.png
│ ├── drawable-mdpi
│ └── ic_launcher.png
│ ├── drawable-xhdpi
│ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ └── ic_launcher.png
│ ├── raw
│ └── test_with_title.html
│ └── values
│ └── strings.xml
└── main
├── AndroidManifest.xml
├── java
└── com
│ └── google
│ └── webviewlocalserver
│ └── WebViewLocalServer.java
└── third_party
├── android
├── LICENSE
└── java
│ └── com
│ └── google
│ └── webviewlocalserver
│ └── third_party
│ └── android
│ └── UriMatcher.java
└── chromium
├── LICENSE
└── java
└── com
└── google
└── webviewlocalserver
└── third_party
└── chromium
└── AndroidProtocolHandler.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | build
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # IMPORTANT
2 |
3 | This project is archived and no longer maintained. Please use the official
4 | AndroidX API [androidx.webkit.WebViewAssetLoader](https://developer.android.com/reference/androidx/webkit/WebViewAssetLoader)
5 | instead.
6 |
7 | # WebView-Local-Server
8 |
9 | ## Overview
10 |
11 | The purpose of this library is to enable hosting local content (such as assets
12 | or resources) under an http(s):// URL.
13 | The traditional way to access local resources is to use `file:///android_asset`
14 | or `file://android_res/` URLs but using the `file:` scheme poses problems with
15 | [the Same-Origin policy](http://en.wikipedia.org/wiki/Same-origin_policy) and
16 | makes it problematic to reference local content from content loaded over
17 | a secure (`https:`) connection.
18 |
19 | ## Usage
20 |
21 | Using the WebView-Local-Server requires the following steps:
22 |
23 | 1. Create a `WebViewLocalServer` instance.
24 |
25 | WebViewLocalServer assetServer = new WebViewLocalServer(context);
26 |
27 | 1. Tell the server where to host the resources.
28 |
29 | // The server uses a random prefix to make it harder for unauthorized content to guess.
30 | WebViewLocalServer.AssetHostingDetails details =
31 | assetServer.hostAssets("/www");
32 | // Assuming you want to know the http address of assets/www/index.hml:
33 | String indexUrl =
34 | details.getHttpPrefix().buildUpon().appendPath("index.html").toString();
35 |
36 | 1. Hook up the server in the `shouldInterceptRequest` method.
37 |
38 | class MyWebViewClient extends WebViewClient {
39 | // For KitKat and earlier.
40 | @Override
41 | public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
42 | return assetServer.shouldInterceptRequest(url);
43 | }
44 | // For Lollipop and above.
45 | @Override
46 | public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
47 | return assetServer.shouldInterceptRequest(request);
48 | }
49 | }
50 |
51 | 1. Consider using the following settings in order to maximize security:
52 |
53 | webView.getSettings().setAllowFileAccessFromFileURLs(false);
54 | webView.getSettings().setAllowUniversalAccessFromFileURLs(false);
55 |
56 | // Keeping these off is less critical but still a good idea, especially
57 | // if your app is not using file:// or content:// URLs.
58 | webView.getSettings().setAllowFileAccess(false);
59 | webView.getSettings().setAllowContentAccess(false);
60 |
61 | ## Picking a domain.
62 |
63 | One potential problem of hosting local resources on a http(s):// URL is that
64 | doing so may conflict with a real website. This means that local resources
65 | should only be hosted on domains that the user has control of or which have
66 | been dedicated for this purpose.
67 | The `androidplatform.net` domain has been specifically reserved for this
68 | purpose and you are free to use it.
69 |
70 | By default the `WebViewLocalServer` will attempt to host assets/resources on
71 | a random subdomain of `androidplatform.net` (something like
72 | `123e4567-e89b-12d3-a456-426655440000.androidplatform.net`). This random
73 | subdomain is chosen once per `WebViewLocalServer`.
74 | To find out which prefix has been assigned to your resources you need to look at
75 | the `AssetHostingDetails` instance returned by the call to `hostAssets` or
76 | `hostResources`.
77 |
78 | Should using a random subdomain be inconvenient for some reason it is possible
79 | to use a fixed domain (like `androidplatform.net` or a domain you own).
80 |
81 | ## Disclaimer
82 |
83 | This is not an official Google product (experimental or otherwise), it is just
84 | code that happens to be owned by Google.
85 |
86 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:0.13.2'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | apply plugin: 'com.android.library'
22 |
23 | android {
24 | compileSdkVersion 21
25 | buildToolsVersion "19.1.0"
26 |
27 | defaultConfig {
28 | applicationId "com.google.webviewlocalserver"
29 | minSdkVersion 18
30 | targetSdkVersion 21
31 | versionCode 1
32 | versionName "0.1"
33 | }
34 | buildTypes {
35 | release {
36 | runProguard false
37 | }
38 | }
39 | sourceSets {
40 | main {
41 | java.srcDirs = [
42 | 'src/main/java',
43 | 'src/main/third_party/android/java',
44 | 'src/main/third_party/chromium/java']
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/androidTest/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
47 | * WebViewLocalServer localServer = new WebViewLocalServer(this); 48 | * // For security WebViewLocalServer uses a unique subdomain by default. 49 | * AssetHostingDetails ahd = localServer.hostAssets("/www"); 50 | * webView.setWebViewClient(new WebViewClient() { 51 | * @Override 52 | * public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { 53 | * return localServer.shouldInterceptRequest(request); 54 | * } 55 | * }); 56 | * // If your application's assets are in the "main/assets" folder this will read the file 57 | * // from "main/assets/www/index.html" and load it as if it were hosted on: 58 | * // https://{uuid}.androidplatform.net/assets/index.html 59 | * webview.loadUrl(ahd.getHttpsPrefix().buildUpon().appendPath("index.html").build().toString()); 60 | * 61 | *62 | */ 63 | public class WebViewLocalServer { 64 | private static String TAG = "WebViewAssetServer"; 65 | /** 66 | * The androidplatform.net domain currently belongs to Google and has been reserved for the 67 | * purpose of Android applications intercepting navigations/requests directed there. 68 | */ 69 | public final static String knownUnusedAuthority = "androidplatform.net"; 70 | private final static String httpScheme = "http"; 71 | private final static String httpsScheme = "https"; 72 | 73 | private final UriMatcher uriMatcher; 74 | private final AndroidProtocolHandler protocolHandler; 75 | private final String authority; 76 | 77 | /** 78 | * A handler that produces responses for paths on the virtual asset server. 79 | * 80 | * Methods of this handler will be invoked on a background thread and care must be taken to 81 | * correctly synchronize access to any shared state. 82 | * 83 | * On Android KitKat and above these methods may be called on more than one thread. This thread 84 | * may be different than the thread on which the shouldInterceptRequest method was invoke. 85 | * This means that on Android KitKat and above it is possible to block in this method without 86 | * blocking other resources from loading. The number of threads used to parallelize loading 87 | * is an internal implementation detail of the WebView and may change between updates which 88 | * means that the amount of time spend blocking in this method should be kept to an absolute 89 | * minimum. 90 | */ 91 | public abstract static class PathHandler { 92 | private String mimeType; 93 | private String encoding; 94 | private String charset; 95 | private int statusCode; 96 | private String reasonPhrase; 97 | private Map
request
.
209 | * This method should be invoked from within
210 | * {@link android.webkit.WebViewClient#shouldInterceptRequest(android.webkit.WebView,
211 | * android.webkit.WebResourceRequest)}.
212 | *
213 | * @param request the request to process.
214 | * @return a response if the request URL had a matching handler, null if no handler was found.
215 | */
216 | public WebResourceResponse shouldInterceptRequest(WebResourceRequest request) {
217 | PathHandler handler;
218 | synchronized (uriMatcher) {
219 | handler = (PathHandler) uriMatcher.match(request.getUrl());
220 | }
221 | if (handler == null) {
222 | return null;
223 | }
224 |
225 | return new WebResourceResponse(handler.getMimeType(), handler.getEncoding(),
226 | handler.getStatusCode(), handler.getReasonPhrase(), handler.getResponseHeaders(),
227 | new LollipopLazyInputStream(handler, request));
228 | }
229 |
230 | /**
231 | * Attempt to retrieve the WebResourceResponse associated with the given url
.
232 | * This method should be invoked from within
233 | * {@link android.webkit.WebViewClient#shouldInterceptRequest(android.webkit.WebView, String)}.
234 | *
235 | * @param url the url to process.
236 | * @return a response if the request URL had a matching handler, null if no handler was found.
237 | */
238 | public WebResourceResponse shouldInterceptRequest(String url) {
239 | PathHandler handler = null;
240 | Uri uri = parseAndVerifyUrl(url);
241 | if (uri != null) {
242 | synchronized (uriMatcher) {
243 | handler = (PathHandler) uriMatcher.match(uri);
244 | }
245 | }
246 | if (handler == null)
247 | return null;
248 |
249 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
250 | return new WebResourceResponse(handler.getMimeType(), handler.getEncoding(),
251 | new LegacyLazyInputStream(handler, uri));
252 | } else {
253 | InputStream is = handler.handle(uri);
254 | return new WebResourceResponse(handler.getMimeType(), handler.getEncoding(),
255 | is);
256 | }
257 | }
258 |
259 | /**
260 | * Registers a handler for the given uri
. The handler
will be invoked
261 | * every time the shouldInterceptRequest
method of the instance is called with
262 | * a matching uri
.
263 | *
264 | * @param uri the uri to use the handler for. The scheme and authority (domain) will be matched
265 | * exactly. The path may contain a '*' element which will match a single element of
266 | * a path (so a handler registered for /a/* will be invoked for /a/b and /a/c.html
267 | * but not for /a/b/b) or the '**' element which will match any number of path
268 | * elements.
269 | * @param handler the handler to use for the uri.
270 | */
271 | void register(Uri uri, PathHandler handler) {
272 | synchronized (uriMatcher) {
273 | uriMatcher.addURI(uri.getScheme(), uri.getAuthority(), uri.getPath(), handler);
274 | }
275 | }
276 |
277 | /**
278 | * Hosts the application's assets on an http(s):// URL. Assets from the local path
279 | * assetPath/...
will be available under
280 | * http(s)://{uuid}.androidplatform.net/assets/...
.
281 | *
282 | * @param assetPath the local path in the application's asset folder which will be made
283 | * available by the server (for example "/www").
284 | * @return prefixes under which the assets are hosted.
285 | */
286 | public AssetHostingDetails hostAssets(String assetPath) {
287 | return hostAssets(authority, assetPath, "/assets", true, true);
288 | }
289 |
290 |
291 | /**
292 | * Hosts the application's assets on an http(s):// URL. Assets from the local path
293 | * assetPath/...
will be available under
294 | * http(s)://{uuid}.androidplatform.net/{virtualAssetPath}/...
.
295 | *
296 | * @param assetPath the local path in the application's asset folder which will be made
297 | * available by the server (for example "/www").
298 | * @param virtualAssetPath the path on the local server under which the assets should be hosted.
299 | * @param enableHttp whether to enable hosting using the http scheme.
300 | * @param enableHttps whether to enable hosting using the https scheme.
301 | * @return prefixes under which the assets are hosted.
302 | */
303 | public AssetHostingDetails hostAssets(final String assetPath, final String virtualAssetPath,
304 | boolean enableHttp, boolean enableHttps) {
305 | return hostAssets(authority, assetPath, virtualAssetPath, enableHttp,
306 | enableHttps);
307 | }
308 |
309 | /**
310 | * Hosts the application's assets on an http(s):// URL. Assets from the local path
311 | * assetPath/...
will be available under
312 | * http(s)://{domain}/{virtualAssetPath}/...
.
313 | *
314 | * @param domain custom domain on which the assets should be hosted (for example "example.com").
315 | * @param assetPath the local path in the application's asset folder which will be made
316 | * available by the server (for example "/www").
317 | * @param virtualAssetPath the path on the local server under which the assets should be hosted.
318 | * @param enableHttp whether to enable hosting using the http scheme.
319 | * @param enableHttps whether to enable hosting using the https scheme.
320 | * @return prefixes under which the assets are hosted.
321 | */
322 | public AssetHostingDetails hostAssets(final String domain,
323 | final String assetPath, final String virtualAssetPath,
324 | boolean enableHttp, boolean enableHttps) {
325 | Uri.Builder uriBuilder = new Uri.Builder();
326 | uriBuilder.scheme(httpScheme);
327 | uriBuilder.authority(domain);
328 | uriBuilder.path(virtualAssetPath);
329 |
330 | if (assetPath.indexOf('*') != -1) {
331 | throw new IllegalArgumentException("assetPath cannot contain the '*' character.");
332 | }
333 | if (virtualAssetPath.indexOf('*') != -1) {
334 | throw new IllegalArgumentException(
335 | "virtualAssetPath cannot contain the '*' character.");
336 | }
337 |
338 | Uri httpPrefix = null;
339 | Uri httpsPrefix = null;
340 |
341 | PathHandler handler = new PathHandler() {
342 | @Override
343 | public InputStream handle(Uri url) {
344 | InputStream stream;
345 | String path = url.getPath().replaceFirst(virtualAssetPath, assetPath);
346 | try {
347 | stream = protocolHandler.openAsset(path);
348 | } catch (IOException e) {
349 | Log.e(TAG, "Unable to open asset URL: " + url);
350 | return null;
351 | }
352 |
353 | String mimeType = null;
354 | try {
355 | mimeType = URLConnection.guessContentTypeFromName(path);
356 | if (mimeType == null)
357 | mimeType = URLConnection.guessContentTypeFromStream(stream);
358 | } catch (Exception ex) {
359 | Log.e(TAG, "Unable to get mime type" + url);
360 | }
361 |
362 | return stream;
363 | }
364 | };
365 |
366 | if (enableHttp) {
367 | httpPrefix = uriBuilder.build();
368 | register(Uri.withAppendedPath(httpPrefix, "**"), handler);
369 | }
370 | if (enableHttps) {
371 | uriBuilder.scheme(httpsScheme);
372 | httpsPrefix = uriBuilder.build();
373 | register(Uri.withAppendedPath(httpsPrefix, "**"), handler);
374 | }
375 | return new AssetHostingDetails(httpPrefix, httpsPrefix);
376 | }
377 |
378 | /**
379 | * Hosts the application's resources on an http(s):// URL. Resources
380 | * http(s)://{uuid}.androidplatform.net/res/{resource_type}/{resource_name}
.
381 | *
382 | * @return prefixes under which the resources are hosted.
383 | */
384 | public AssetHostingDetails hostResources() {
385 | return hostResources(authority, "/res", true, true);
386 | }
387 |
388 | /**
389 | * Hosts the application's resources on an http(s):// URL. Resources
390 | * http(s)://{uuid}.androidplatform.net/{virtualResourcesPath}/{resource_type}/{resource_name}
.
391 | *
392 | * @param virtualResourcesPath the path on the local server under which the resources
393 | * should be hosted.
394 | * @param enableHttp whether to enable hosting using the http scheme.
395 | * @param enableHttps whether to enable hosting using the https scheme.
396 | * @return prefixes under which the resources are hosted.
397 | */
398 | public AssetHostingDetails hostResources(final String virtualResourcesPath, boolean enableHttp,
399 | boolean enableHttps) {
400 | return hostResources(authority, virtualResourcesPath, enableHttp, enableHttps);
401 | }
402 |
403 | /**
404 | * Hosts the application's resources on an http(s):// URL. Resources
405 | * http(s)://{domain}/{virtualResourcesPath}/{resource_type}/{resource_name}
.
406 | *
407 | * @param domain custom domain on which the assets should be hosted (for example "example.com").
408 | * If untrusted content is to be loaded into the WebView it is advised to make
409 | * this random.
410 | * @param virtualResourcesPath the path on the local server under which the resources
411 | * should be hosted.
412 | * @param enableHttp whether to enable hosting using the http scheme.
413 | * @param enableHttps whether to enable hosting using the https scheme.
414 | * @return prefixes under which the resources are hosted.
415 | */
416 | public AssetHostingDetails hostResources(final String domain,
417 | final String virtualResourcesPath, boolean enableHttp,
418 | boolean enableHttps) {
419 | if (virtualResourcesPath.indexOf('*') != -1) {
420 | throw new IllegalArgumentException(
421 | "virtualResourcesPath cannot contain the '*' character.");
422 | }
423 |
424 | Uri.Builder uriBuilder = new Uri.Builder();
425 | uriBuilder.scheme(httpScheme);
426 | uriBuilder.authority(domain);
427 | uriBuilder.path(virtualResourcesPath);
428 |
429 | Uri httpPrefix = null;
430 | Uri httpsPrefix = null;
431 |
432 | PathHandler handler = new PathHandler() {
433 | @Override
434 | public InputStream handle(Uri url) {
435 | InputStream stream = protocolHandler.openResource(url);
436 | String mimeType = null;
437 | try {
438 | mimeType = URLConnection.guessContentTypeFromStream(stream);
439 | } catch (Exception ex) {
440 | Log.e(TAG, "Unable to get mime type" + url);
441 | }
442 |
443 | return stream;
444 | }
445 | };
446 |
447 | if (enableHttp) {
448 | httpPrefix = uriBuilder.build();
449 | register(Uri.withAppendedPath(httpPrefix, "**"), handler);
450 | }
451 | if (enableHttps) {
452 | uriBuilder.scheme(httpsScheme);
453 | httpsPrefix = uriBuilder.build();
454 | register(Uri.withAppendedPath(httpsPrefix, "**"), handler);
455 | }
456 | return new AssetHostingDetails(httpPrefix, httpsPrefix);
457 | }
458 |
459 | /**
460 | * The KitKat WebView reads the InputStream on a separate threadpool. We can use that to
461 | * parallelize loading.
462 | */
463 | private static abstract class LazyInputStream extends InputStream {
464 | protected final PathHandler handler;
465 | private InputStream is = null;
466 |
467 | public LazyInputStream(PathHandler handler) {
468 | this.handler = handler;
469 | }
470 |
471 | private InputStream getInputStream() {
472 | if (is == null) {
473 | is = handle();
474 | }
475 | return is;
476 | }
477 |
478 | protected abstract InputStream handle();
479 |
480 | @Override
481 | public int available() throws IOException {
482 | InputStream is = getInputStream();
483 | return (is != null) ? is.available() : 0;
484 | }
485 |
486 | @Override
487 | public int read() throws IOException {
488 | InputStream is = getInputStream();
489 | return (is != null) ? is.read() : -1;
490 | }
491 |
492 | @Override
493 | public int read(byte b[]) throws IOException {
494 | InputStream is = getInputStream();
495 | return (is != null) ? is.read(b) : -1;
496 | }
497 |
498 | @Override
499 | public int read(byte b[], int off, int len) throws IOException {
500 | InputStream is = getInputStream();
501 | return (is != null) ? is.read(b, off, len) : -1;
502 | }
503 |
504 | @Override
505 | public long skip(long n) throws IOException {
506 | InputStream is = getInputStream();
507 | return (is != null) ? is.skip(n) : 0;
508 | }
509 | }
510 |
511 | // For earlier than L.
512 | private static class LegacyLazyInputStream extends LazyInputStream {
513 | private Uri uri;
514 | private InputStream is;
515 |
516 | public LegacyLazyInputStream(PathHandler handler, Uri uri) {
517 | super(handler);
518 | this.uri = uri;
519 | }
520 |
521 | @Override
522 | protected InputStream handle() {
523 | return handler.handle(uri);
524 | }
525 | }
526 |
527 | // For L and above.
528 | private static class LollipopLazyInputStream extends LazyInputStream {
529 | private WebResourceRequest request;
530 | private InputStream is;
531 |
532 | public LollipopLazyInputStream(PathHandler handler, WebResourceRequest request) {
533 | super(handler);
534 | this.request = request;
535 | }
536 |
537 | @Override
538 | protected InputStream handle() {
539 | return handler.handle(request);
540 | }
541 | }
542 | }
543 |
--------------------------------------------------------------------------------
/src/main/third_party/android/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/src/main/third_party/android/java/com/google/webviewlocalserver/third_party/android/UriMatcher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2006 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.google.webviewlocalserver.third_party.android;
17 |
18 | import android.net.Uri;
19 |
20 | import java.util.ArrayList;
21 | import java.util.List;
22 | import java.util.regex.Pattern;
23 |
24 | public class UriMatcher
25 | {
26 | /**
27 | * Creates the root node of the URI tree.
28 | *
29 | * @param code the code to match for the root URI
30 | */
31 | public UriMatcher(Object code)
32 | {
33 | mCode = code;
34 | mWhich = -1;
35 | mChildren = new ArrayList
53 | * Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
54 | * this method will accept a leading slash in the path.
55 | *
56 | * @param authority the authority to match
57 | * @param path the path to match. * may be used as a wild card for
58 | * any text, and # may be used as a wild card for numbers.
59 | * @param code the code that is returned when a URI is matched
60 | * against the given components. Must be positive.
61 | */
62 | public void addURI(String scheme, String authority, String path, Object code)
63 | {
64 | if (code == null) {
65 | throw new IllegalArgumentException("Code can't be null");
66 | }
67 |
68 | String[] tokens = null;
69 | if (path != null) {
70 | String newPath = path;
71 | // Strip leading slash if present.
72 | if (path.length() > 0 && path.charAt(0) == '/') {
73 | newPath = path.substring(1);
74 | }
75 | tokens = PATH_SPLIT_PATTERN.split(newPath);
76 | }
77 |
78 | int numTokens = tokens != null ? tokens.length : 0;
79 | UriMatcher node = this;
80 | for (int i = -2; i < numTokens; i++) {
81 | String token;
82 | if (i == -2)
83 | token = scheme;
84 | else if (i == -1)
85 | token = authority;
86 | else
87 | token = tokens[i];
88 | ArrayList