/*
* Copyright (C) 2011 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.browser;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.webkit.WebView;
import java.util.Map;
/**
* Singleton class for handling preload requests.
*/
public class Preloader {
private final static String LOGTAG = "browser.preloader";
private final static boolean LOGD_ENABLED = com.android.browser.Browser.LOGD_ENABLED;
private static final int PRERENDER_TIMEOUT_MILLIS = 30 * 1000; // 30s
private static Preloader sInstance;
private final Context mContext;
private final Handler mHandler;
private final BrowserWebViewFactory mFactory;
private volatile PreloaderSession mSession;
public static void initialize(Context context) {
sInstance = new Preloader(context);
}
public static Preloader getInstance() {
return sInstance;
}
private Preloader(Context context) {
mContext = context.getApplicationContext();
mHandler = new Handler(Looper.getMainLooper());
mSession = null;
mFactory = new BrowserWebViewFactory(context);
}
private PreloaderSession getSession(String id) {
if (mSession == null) {
if (LOGD_ENABLED) Log.d(LOGTAG, "Create new preload session " + id);
mSession = new PreloaderSession(id);
WebViewTimersControl.getInstance().onPrerenderStart(
mSession.getWebView());
return mSession;
} else if (mSession.mId.equals(id)) {
if (LOGD_ENABLED) Log.d(LOGTAG, "Returning existing preload session " + id);
return mSession;
}
if (LOGD_ENABLED) Log.d(LOGTAG, "Existing session in progress : " + mSession.mId +
" returning null.");
return null;
}
private PreloaderSession takeSession(String id) {
PreloaderSession s = null;
if (mSession != null && mSession.mId.equals(id)) {
s = mSession;
mSession = null;
}
if (s != null) {
s.cancelTimeout();
}
return s;
}
public void handlePreloadRequest(String id, String url, Map<String, String> headers,
String searchBoxQuery) {
PreloaderSession s = getSession(id);
if (s == null) {
if (LOGD_ENABLED) Log.d(LOGTAG, "Discarding preload request, existing"
+ " session in progress");
return;
}
s.touch(); // reset timer
PreloadedTabControl tab = s.getTabControl();
if (searchBoxQuery != null) {
tab.loadUrlIfChanged(url, headers);
tab.setQuery(searchBoxQuery);
} else {
tab.loadUrl(url, headers);
}
}
public void cancelSearchBoxPreload(String id) {
PreloaderSession s = getSession(id);
if (s != null) {
s.touch(); // reset timer
PreloadedTabControl tab = s.getTabControl();
tab.searchBoxCancel();
}
}
public void discardPreload(String id) {
PreloaderSession s = takeSession(id);
if (s != null) {
if (LOGD_ENABLED) Log.d(LOGTAG, "Discard preload session " + id);
WebViewTimersControl.getInstance().onPrerenderDone(s == null ? null : s.getWebView());
PreloadedTabControl t = s.getTabControl();
t.destroy();
} else {
if (LOGD_ENABLED) Log.d(LOGTAG, "Ignored discard request " + id);
}
}
/**
* Return a preloaded tab, and remove it from the preloader. This is used when the
* view is about to be displayed.
*/
public PreloadedTabControl getPreloadedTab(String id) {
PreloaderSession s = takeSession(id);
if (LOGD_ENABLED) Log.d(LOGTAG, "Showing preload session " + id + "=" + s);
return s == null ? null : s.getTabControl();
}
private class PreloaderSession {
private final String mId;
private final PreloadedTabControl mTabControl;
private final Runnable mTimeoutTask = new Runnable(){
@Override
public void run() {
if (LOGD_ENABLED) Log.d(LOGTAG, "Preload session timeout " + mId);
discardPreload(mId);
}};
public PreloaderSession(String id) {
mId = id;
mTabControl = new PreloadedTabControl(
new Tab(new PreloadController(mContext), mFactory.createWebView(false)));
touch();
}
public void cancelTimeout() {
mHandler.removeCallbacks(mTimeoutTask);
}
public void touch() {
cancelTimeout();
mHandler.postDelayed(mTimeoutTask, PRERENDER_TIMEOUT_MILLIS);
}
public PreloadedTabControl getTabControl() {
return mTabControl;
}
public WebView getWebView() {
Tab t = mTabControl.getTab();
return t == null? null : t.getWebView();
}
}
}