Merge tag android-5.1.0_r1 into AOSP_5.1_MERGE

Change-Id: Id8c68d4000043d7976b6130a09c40f5b7f7e850e
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 315a958..9a2ccd0 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -19,12 +19,14 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.htmlviewer">
-
     <original-package android:name="com.android.htmlviewer" />
+
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
     <application android:label="@string/app_label">
-        <activity android:name="HTMLViewerActivity" android:label="HTMLViewer"
-                  android:theme="@android:style/Theme.Holo" >
+        <activity android:name="HTMLViewerActivity"
+                android:label="@string/app_label"
+                android:theme="@android:style/Theme.DeviceDefault">
             <intent-filter>
                 <category android:name="android.intent.category.DEFAULT" />
                 <action android:name="android.intent.action.VIEW" />
@@ -36,14 +38,5 @@
                 <data android:mimeType="application/vnd.wap.xhtml+xml"/>
             </intent-filter>
          </activity>
-
-         <provider android:name="FileContentProvider"
-                 android:exported="false"
-                 android:authorities="com.android.htmlfileprovider"
-                 android:syncable="false" android:multiprocess="false"
-                 android:grantUriPermissions="true" />
-
     </application>
-
 </manifest>
-
diff --git a/res/layout/main.xml b/res/layout/main.xml
new file mode 100644
index 0000000..8a9f48a
--- /dev/null
+++ b/res/layout/main.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@*android:color/white">
+
+    <WebView
+        android:id="@+id/webview"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <ProgressBar
+        android:id="@+id/loading"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:indeterminate="true"
+        style="?android:attr/progressBarStyle" />
+
+</FrameLayout>
diff --git a/src/com/android/htmlviewer/FileContentProvider.java b/src/com/android/htmlviewer/FileContentProvider.java
deleted file mode 100644
index 4cf16a6..0000000
--- a/src/com/android/htmlviewer/FileContentProvider.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * 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 java.io.FileNotFoundException;
-import java.io.File;
-import java.lang.UnsupportedOperationException;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.ParcelFileDescriptor;
-import android.os.Process;
-
-/**
- * WebView does not support file: loading. This class wraps a file load
- * with a content provider.
- * As HTMLViewer does not have internet access nor does it allow
- * Javascript to be run, it is safe to load file based HTML content.
-*/
-public class FileContentProvider extends ContentProvider {
-
-    public static final String BASE_URI =
-            "content://com.android.htmlfileprovider";
-
-    @Override
-    public String getType(Uri uri) {
-        // If the mimetype is not appended to the uri, then return an empty string
-        String mimetype = uri.getQuery();
-        return mimetype == null ? "" : mimetype;
-    }
-
-    @Override
-    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
-        // android:exported="false" is broken in older releases so we have to
-        // manually enforce the calling identity.
-        if (Process.myUid() != Binder.getCallingUid()) {
-            throw new SecurityException("Permission denied");
-        }
-        if (!"r".equals(mode)) {
-            throw new FileNotFoundException("Bad mode for " + uri + ": " + mode);
-        }
-        String filename = uri.getPath();
-        File f = new File(filename);
-        if (f.isDirectory()) {
-            return null;
-        }
-        return ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
-    }
-
-    @Override
-    public int delete(Uri uri, String selection, String[] selectionArgs) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Uri insert(Uri uri, ContentValues values) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean onCreate() {
-        return true;
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] projection, String selection,
-            String[] selectionArgs, String sortOrder) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int update(Uri uri, ContentValues values, String selection,
-            String[] selectionArgs) {
-        throw new UnsupportedOperationException();
-    }
-
-}
diff --git a/src/com/android/htmlviewer/HTMLViewerActivity.java b/src/com/android/htmlviewer/HTMLViewerActivity.java
index d4f4f73..8a945a9 100644
--- a/src/com/android/htmlviewer/HTMLViewerActivity.java
+++ b/src/com/android/htmlviewer/HTMLViewerActivity.java
@@ -17,73 +17,51 @@
 package com.android.htmlviewer;
 
 import android.app.Activity;
+import android.content.ContentResolver;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
 import android.util.Log;
-import android.view.Window;
-import android.webkit.CookieSyncManager;
+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 java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
 
 /**
- * Wraps a WebView widget within an Activity. When launched, it uses the
- * URI from the intent as the URL to load into the WebView.
- * It supports all URLs schemes that a standard WebView supports, as well as
- * loading the top level markup using the file scheme.
- * The WebView default settings are used with the exception of normal layout
- * is set.
- * This activity shows a loading progress bar in the window title and sets
- * the window title to the title of the content.
- *
+ * 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";
 
-    /*
-     * The WebView that is placed in this Activity
-     */
     private WebView mWebView;
-
-    /*
-     * As the file content is loaded completely into RAM first, set
-     * a limitation on the file size so we don't use too much RAM. If someone
-     * wants to load content that is larger than this, then a content
-     * provider should be used.
-     */
-    static final int MAXFILESIZE = 8096;
-
-    static final String LOGTAG = "HTMLViewerActivity";
+    private View mLoading;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        // Call createInstance() explicitly. createInstance() is called in
-        // BrowserFrame by WebView. As it is called in WebCore thread, it can
-        // happen after onResume() is called. To use getInstance() in onResume,
-        // createInstance() needs to be called first.
-        CookieSyncManager.createInstance(this);
+        setContentView(R.layout.main);
 
-        requestWindowFeature(Window.FEATURE_PROGRESS);
+        mWebView = (WebView) findViewById(R.id.webview);
+        mLoading = findViewById(R.id.loading);
 
-        mWebView = new WebView(this);
-        setContentView(mWebView);
+        mWebView.setWebChromeClient(new ChromeClient());
+        mWebView.setWebViewClient(new ViewClient());
 
-        // Setup callback support for title and progress bar
-        mWebView.setWebChromeClient( new WebChrome() );
-
-        // Configure the webview
         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);
@@ -91,46 +69,14 @@
         // Javascript is purposely disabled, so that nothing can be
         // automatically run.
         s.setJavaScriptEnabled(false);
-
         s.setDefaultTextEncodingName("utf-8");
 
-        // Restore a webview if we are meant to restore
-        if (savedInstanceState != null) {
-            mWebView.restoreState(savedInstanceState);
-        } else {
-            // Check the intent for the content to view
-            Intent intent = getIntent();
-            if (intent.getData() != null) {
-                Uri uri = intent.getData();
-                String contentUri = "file".equals(uri.getScheme())
-                        ? FileContentProvider.BASE_URI + uri.getEncodedPath()
-                        : uri.toString();
-                mWebView.loadUrl(contentUri);
-            }
+        final Intent intent = getIntent();
+        if (intent.hasExtra(Intent.EXTRA_TITLE)) {
+            setTitle(intent.getStringExtra(Intent.EXTRA_TITLE));
         }
-    }
 
-    @Override
-    protected void onResume() {
-        super.onResume();
-        CookieSyncManager.getInstance().startSync();
-    }
-
-    @Override
-    protected void onSaveInstanceState(Bundle outState) {
-        // the default implementation requires each view to have an id. As the
-        // browser handles the state itself and it doesn't use id for the views,
-        // don't call the default implementation. Otherwise it will trigger the
-        // warning like this, "couldn't save which view has focus because the
-        // focused view XXX has no id".
-        mWebView.saveState(outState);
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-
-        CookieSyncManager.getInstance().stopSync();
+        mWebView.loadUrl(String.valueOf(intent.getData()));
     }
 
     @Override
@@ -139,21 +85,40 @@
         mWebView.destroy();
     }
 
-    class WebChrome extends WebChromeClient {
-
+    private class ChromeClient extends WebChromeClient {
         @Override
         public void onReceivedTitle(WebView view, String title) {
-            HTMLViewerActivity.this.setTitle(title);
-        }
-
-        @Override
-        public void onProgressChanged(WebView view, int newProgress) {
-            getWindow().setFeatureInt(
-                    Window.FEATURE_PROGRESS, newProgress*100);
-            if (newProgress == 100) {
-                CookieSyncManager.getInstance().sync();
+            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 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;
+        }
+    }
 }