/* * Copyright (C) 2008 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.htmlviewer; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.ContentResolver; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.provider.Browser; import android.util.Log; import android.view.View; import android.webkit.WebChromeClient; import android.webkit.WebResourceRequest; import android.webkit.WebResourceResponse; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; import java.io.IOException; import java.io.InputStream; import java.net.URISyntaxException; import java.util.zip.GZIPInputStream; /** * Simple activity that shows the requested HTML page. This utility is * purposefully very limited in what it supports, including no network or * JavaScript. */ public class HTMLViewerActivity extends Activity { private static final String TAG = "HTMLViewer"; private WebView mWebView; private View mLoading; private Intent mIntent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mWebView = findViewById(R.id.webview); mLoading = findViewById(R.id.loading); mWebView.setWebChromeClient(new ChromeClient()); mWebView.setWebViewClient(new ViewClient()); WebSettings s = mWebView.getSettings(); s.setUseWideViewPort(true); s.setSupportZoom(true); s.setBuiltInZoomControls(true); s.setDisplayZoomControls(false); s.setSavePassword(false); s.setSaveFormData(false); s.setBlockNetworkLoads(true); // Javascript is purposely disabled, so that nothing can be // automatically run. s.setJavaScriptEnabled(false); s.setDefaultTextEncodingName("utf-8"); mIntent = getIntent(); loadUrl(); } private void loadUrl() { if (mIntent.hasExtra(Intent.EXTRA_TITLE)) { setTitle(mIntent.getStringExtra(Intent.EXTRA_TITLE)); } mWebView.loadUrl(String.valueOf(mIntent.getData())); } @Override protected void onDestroy() { super.onDestroy(); mWebView.destroy(); } private class ChromeClient extends WebChromeClient { @Override public void onReceivedTitle(WebView view, String title) { if (!getIntent().hasExtra(Intent.EXTRA_TITLE)) { HTMLViewerActivity.this.setTitle(title); } } } private class ViewClient extends WebViewClient { @Override public void onPageFinished(WebView view, String url) { mLoading.setVisibility(View.GONE); } @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { String url = request.getUrl().toString(); Intent intent; // Perform generic parsing of the URI to turn it into an Intent. try { intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); } catch (URISyntaxException ex) { Log.w(TAG, "Bad URI " + url + ": " + ex.getMessage()); Toast.makeText(HTMLViewerActivity.this, R.string.cannot_open_link, Toast.LENGTH_SHORT).show(); return true; } // Sanitize the Intent, ensuring web pages can not bypass browser // security (only access to BROWSABLE activities). intent.addCategory(Intent.CATEGORY_BROWSABLE); intent.setComponent(null); Intent selector = intent.getSelector(); if (selector != null) { selector.addCategory(Intent.CATEGORY_BROWSABLE); selector.setComponent(null); } // Pass the package name as application ID so that the intent from the // same application can be opened in the same tab. intent.putExtra(Browser.EXTRA_APPLICATION_ID, view.getContext().getPackageName()); try { view.getContext().startActivity(intent); } catch (ActivityNotFoundException | SecurityException ex) { Log.w(TAG, "No application can handle " + url); Toast.makeText(HTMLViewerActivity.this, R.string.cannot_open_link, Toast.LENGTH_SHORT).show(); } return true; } @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { final Uri uri = request.getUrl(); if (ContentResolver.SCHEME_FILE.equals(uri.getScheme()) && uri.getPath().endsWith(".gz")) { Log.d(TAG, "Trying to decompress " + uri + " on the fly"); try { final InputStream in = new GZIPInputStream( getContentResolver().openInputStream(uri)); final WebResourceResponse resp = new WebResourceResponse( getIntent().getType(), "utf-8", in); resp.setStatusCodeAndReasonPhrase(200, "OK"); return resp; } catch (IOException e) { Log.w(TAG, "Failed to decompress; falling back", e); } } return null; } } }