11461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb/* 21461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * Copyright (C) 2011 The Android Open Source Project 31461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * 41461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * Licensed under the Apache License, Version 2.0 (the "License"); 51461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * you may not use this file except in compliance with the License. 61461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * You may obtain a copy of the License at 71461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * 81461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * http://www.apache.org/licenses/LICENSE-2.0 91461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * 101461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * Unless required by applicable law or agreed to in writing, software 111461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * distributed under the License is distributed on an "AS IS" BASIS, 121461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * See the License for the specific language governing permissions and 141461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * limitations under the License. 151461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb */ 161461244018a225006a8d4c203f9dfe294ffe94faMichael Kolbpackage com.android.browser; 171461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 181461244018a225006a8d4c203f9dfe294ffe94faMichael Kolbimport android.content.Context; 191461244018a225006a8d4c203f9dfe294ffe94faMichael Kolbimport android.os.Handler; 201461244018a225006a8d4c203f9dfe294ffe94faMichael Kolbimport android.os.Looper; 211461244018a225006a8d4c203f9dfe294ffe94faMichael Kolbimport android.util.Log; 22e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwoodimport android.webkit.WebView; 231461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 241461244018a225006a8d4c203f9dfe294ffe94faMichael Kolbimport java.util.Map; 251461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 261461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb/** 271461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * Singleton class for handling preload requests. 281461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb */ 291461244018a225006a8d4c203f9dfe294ffe94faMichael Kolbpublic class Preloader { 301461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 311461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb private final static String LOGTAG = "browser.preloader"; 3229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood private final static boolean LOGD_ENABLED = com.android.browser.Browser.LOGD_ENABLED; 331461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 341461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb private static final int PRERENDER_TIMEOUT_MILLIS = 30 * 1000; // 30s 351461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 361461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb private static Preloader sInstance; 371461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 381461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb private final Context mContext; 391461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb private final Handler mHandler; 401461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb private final BrowserWebViewFactory mFactory; 41f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath private volatile PreloaderSession mSession; 421461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 431461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb public static void initialize(Context context) { 441461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb sInstance = new Preloader(context); 451461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 461461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 471461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb public static Preloader getInstance() { 481461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb return sInstance; 491461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 501461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 511461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb private Preloader(Context context) { 52914c5591baeb86bf30a5bc28930071442a822d60Ben Murdoch mContext = context.getApplicationContext(); 531461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb mHandler = new Handler(Looper.getMainLooper()); 54f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath mSession = null; 551461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb mFactory = new BrowserWebViewFactory(context); 561461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 571461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 581461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 591461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb private PreloaderSession getSession(String id) { 60f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath if (mSession == null) { 611461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb if (LOGD_ENABLED) Log.d(LOGTAG, "Create new preload session " + id); 62f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath mSession = new PreloaderSession(id); 63f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath WebViewTimersControl.getInstance().onPrerenderStart( 64f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath mSession.getWebView()); 65f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath return mSession; 66f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath } else if (mSession.mId.equals(id)) { 67f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath if (LOGD_ENABLED) Log.d(LOGTAG, "Returning existing preload session " + id); 68f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath return mSession; 691461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 70f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath 71f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath if (LOGD_ENABLED) Log.d(LOGTAG, "Existing session in progress : " + mSession.mId + 72f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath " returning null."); 73f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath return null; 741461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 751461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 761461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb private PreloaderSession takeSession(String id) { 77f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath PreloaderSession s = null; 78f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath if (mSession != null && mSession.mId.equals(id)) { 79f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath s = mSession; 80f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath mSession = null; 81f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath } 82f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath 831461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb if (s != null) { 841461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb s.cancelTimeout(); 851461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 86f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath 871461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb return s; 881461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 891461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 9029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood public void handlePreloadRequest(String id, String url, Map<String, String> headers, 9129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood String searchBoxQuery) { 921461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb PreloaderSession s = getSession(id); 93f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath if (s == null) { 94f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath if (LOGD_ENABLED) Log.d(LOGTAG, "Discarding preload request, existing" 95f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath + " session in progress"); 96f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath return; 97f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath } 98f27b710afe310d5df6ae3fac9c88b23ac78cbfe6Narayan Kamath 991461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb s.touch(); // reset timer 10029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood PreloadedTabControl tab = s.getTabControl(); 10129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood if (searchBoxQuery != null) { 10229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood tab.loadUrlIfChanged(url, headers); 10329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood tab.setQuery(searchBoxQuery); 10429721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood } else { 10529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood tab.loadUrl(url, headers); 10629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood } 1071461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 1081461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 109dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood public void cancelSearchBoxPreload(String id) { 110dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood PreloaderSession s = getSession(id); 111dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood if (s != null) { 112dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood s.touch(); // reset timer 113dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood PreloadedTabControl tab = s.getTabControl(); 114dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood tab.searchBoxCancel(); 115dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood } 116dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood } 117dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood 1181461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb public void discardPreload(String id) { 1191461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb PreloaderSession s = takeSession(id); 1201461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb if (s != null) { 1211461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb if (LOGD_ENABLED) Log.d(LOGTAG, "Discard preload session " + id); 122cf9120ebd80d9ecdf54ec387bc1e8c4b9b91c6eaMathew Inwood WebViewTimersControl.getInstance().onPrerenderDone(s == null ? null : s.getWebView()); 12329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood PreloadedTabControl t = s.getTabControl(); 1241461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb t.destroy(); 12529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood } else { 12629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood if (LOGD_ENABLED) Log.d(LOGTAG, "Ignored discard request " + id); 1271461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 1281461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 1291461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 1301461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb /** 1311461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * Return a preloaded tab, and remove it from the preloader. This is used when the 1321461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb * view is about to be displayed. 1331461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb */ 13429721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood public PreloadedTabControl getPreloadedTab(String id) { 1351461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb PreloaderSession s = takeSession(id); 1361461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb if (LOGD_ENABLED) Log.d(LOGTAG, "Showing preload session " + id + "=" + s); 13729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood return s == null ? null : s.getTabControl(); 1381461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 1391461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 1401461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb private class PreloaderSession { 1411461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb private final String mId; 14229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood private final PreloadedTabControl mTabControl; 1431461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 1441461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb private final Runnable mTimeoutTask = new Runnable(){ 1451461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb @Override 1461461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb public void run() { 1471461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb if (LOGD_ENABLED) Log.d(LOGTAG, "Preload session timeout " + mId); 1481461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb discardPreload(mId); 1491461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb }}; 1501461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 1511461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb public PreloaderSession(String id) { 1521461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb mId = id; 15329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood mTabControl = new PreloadedTabControl( 15429721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood new Tab(new PreloadController(mContext), mFactory.createWebView(false))); 1551461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb touch(); 1561461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 1571461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 1581461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb public void cancelTimeout() { 1591461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb mHandler.removeCallbacks(mTimeoutTask); 1601461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 1611461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 1621461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb public void touch() { 1631461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb cancelTimeout(); 1641461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb mHandler.postDelayed(mTimeoutTask, PRERENDER_TIMEOUT_MILLIS); 1651461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 1661461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 16729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood public PreloadedTabControl getTabControl() { 16829721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood return mTabControl; 1691461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 1701461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 171e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood public WebView getWebView() { 172e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood Tab t = mTabControl.getTab(); 173e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood return t == null? null : t.getWebView(); 174e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood } 175e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood 1761461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb } 1771461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb 1781461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb} 179