blob: 3a6ee81b8d76b2b4ec632ccfd7c4fceedaf94668 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package io.v.android.apps.reader;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.webkit.JavascriptInterface;
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 com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.SettableFuture;
import java.io.InputStream;
import io.v.android.apps.reader.db.DB;
/**
* Wrapper class for the PDF Viewer library.
*
* May be replaced with another library if needed.
*/
public class PdfViewWrapper extends WebView {
private static final String TAG = PdfViewWrapper.class.getSimpleName();
private SettableFuture<Boolean> mPageLoaded;
private int mPageCount;
public PdfViewWrapper(Context context, AttributeSet attrs) {
super(context, attrs);
mPageLoaded = SettableFuture.create();
}
public void init() {
WebSettings settings = getSettings();
settings.setJavaScriptEnabled(true);
settings.setAllowUniversalAccessFromFileURLs(true);
setWebChromeClient(new WebChromeClient());
setWebViewClient(new PdfViewClient());
addJavascriptInterface(new JSInterface(), "android");
loadUrl("file:///android_asset/pdfjs/pdf-web-view.html");
}
/**
* Loads the PDF file at the given path into the pdf.js component within WebView.
*/
public void loadPdfFile(final String filePath) {
Futures.addCallback(mPageLoaded, new FutureCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
Log.i(TAG, "loadPdfFile called: " + filePath);
evaluateJavascript("window.client.open(\"" + filePath + "\");", null);
// leave the page count as 0 until the page count value is properly set from JS side.
mPageCount = 0;
}
@Override
public void onFailure(Throwable t) {
// Nothing to do.
}
});
}
/**
* Jumps to the given page number. Page number is one-based.
*
* @param page the page number to jump to. Page number is one-based.
*/
public void setPage(int page) {
evaluateJavascript("window.client.page(" + page + ");", null);
}
public int getPageCount() {
return mPageCount;
}
/**
* This class provides public methods that can be called from the JavaScript side.
*/
private class JSInterface {
private final String TAG = JSInterface.class.getSimpleName();
@JavascriptInterface
public void setPageCount(int pageCount) {
Log.d(TAG, "setPageCount(" + pageCount + ") called.");
mPageCount = pageCount;
}
}
private class PdfViewClient extends WebViewClient {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
Log.i(TAG, "shouldInterceptRequest called");
String path = request.getUrl().getPath();
if (!path.startsWith("/file_id/")) {
Log.i(TAG, "Not a file id path. Falling back to super.shouldInterceptRequest");
return super.shouldInterceptRequest(view, request);
}
String fileId = request.getUrl().getLastPathSegment();
Log.i(TAG, "File ID: " + fileId);
// Should NOT close the stream here, so that the stream can be read by WebView.
InputStream in = DB.Singleton.get(getContext()).getInputStreamForFile(fileId);
if (in != null) {
Log.i(TAG, "returning a custom WebResourceResponse");
return new WebResourceResponse("application/pdf", "binary", in);
} else {
Log.i(TAG, "Could not open an input stream. " +
"Falling back to super.shouldInterceptRequest");
return super.shouldInterceptRequest(view, request);
}
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
mPageLoaded.set(true);
}
}
}