Preloading support in browser
Apps like the QSB can request the browser to preload a
web page.
- preloaded pages are not added to the browser history
if they'r not seen by the user
- when a request is received, a new tab is created for the
preloaded page, but not added to the tab list
- upon receiving the view intent for the preloaded page
the tab is added to the tab list, and shown
- if several pages are preloaded consecutively in the same tab,
the back stack is cleared before it is displayed
- preloaded pages use the main browser cookie jar, so pages that
have never been viewed by the user can drop cookies
Change-Id: I9ed21f2c9560fda0ed042b460b73bb33988a2e8a
diff --git a/src/com/android/browser/Preloader.java b/src/com/android/browser/Preloader.java
new file mode 100644
index 0000000..5a5f687
--- /dev/null
+++ b/src/com/android/browser/Preloader.java
@@ -0,0 +1,137 @@
+/*
+ * 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.AttributeSet;
+import android.util.Log;
+import android.webkit.WebView;
+
+import java.util.HashMap;
+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 = true;//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 final HashMap<String, PreloaderSession> mSessions;
+
+ public static void initialize(Context context) {
+ sInstance = new Preloader(context);
+ }
+
+ public static Preloader getInstance() {
+ return sInstance;
+ }
+
+ private Preloader(Context context) {
+ mContext = context;
+ mHandler = new Handler(Looper.getMainLooper());
+ mSessions = new HashMap<String, PreloaderSession>();
+ mFactory = new BrowserWebViewFactory(context);
+
+ }
+
+ private PreloaderSession getSession(String id) {
+ PreloaderSession s = mSessions.get(id);
+ if (s == null) {
+ if (LOGD_ENABLED) Log.d(LOGTAG, "Create new preload session " + id);
+ s = new PreloaderSession(id);
+ mSessions.put(id, s);
+ }
+ return s;
+ }
+
+ private PreloaderSession takeSession(String id) {
+ PreloaderSession s = mSessions.remove(id);
+ if (s != null) {
+ s.cancelTimeout();
+ }
+ return s;
+ }
+
+ public void handlePreloadRequest(String id, String url, Map<String, String> headers) {
+ PreloaderSession s = getSession(id);
+ s.touch(); // reset timer
+ if (LOGD_ENABLED) Log.d(LOGTAG, "Preloading " + url);
+ s.getTab().loadUrl(url, headers);
+ }
+
+ public void discardPreload(String id) {
+ PreloaderSession s = takeSession(id);
+ if (s != null) {
+ if (LOGD_ENABLED) Log.d(LOGTAG, "Discard preload session " + id);
+ Tab t = s.getTab();
+ t.destroy();
+ }
+ }
+
+ /**
+ * Return a preloaded tab, and remove it from the preloader. This is used when the
+ * view is about to be displayed.
+ */
+ public Tab getPreloadedTab(String id) {
+ PreloaderSession s = takeSession(id);
+ if (LOGD_ENABLED) Log.d(LOGTAG, "Showing preload session " + id + "=" + s);
+ return s == null ? null : s.getTab();
+ }
+
+ private class PreloaderSession {
+ private final String mId;
+ private final Tab mTab;
+
+ 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;
+ mTab = 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 Tab getTab() {
+ return mTab;
+ }
+
+ }
+
+}