/* * 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(); } } }