Preloader.java revision e1dbb956d762c3f07033f247c05270a9882a79a7
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.browser;
17
18import android.content.Context;
19import android.os.Handler;
20import android.os.Looper;
21import android.util.Log;
22import android.webkit.WebView;
23
24import java.util.HashMap;
25import java.util.Map;
26
27/**
28 * Singleton class for handling preload requests.
29 */
30public class Preloader {
31
32    private final static String LOGTAG = "browser.preloader";
33    private final static boolean LOGD_ENABLED = com.android.browser.Browser.LOGD_ENABLED;
34
35    private static final int PRERENDER_TIMEOUT_MILLIS = 30 * 1000; // 30s
36
37    private static Preloader sInstance;
38
39    private final Context mContext;
40    private final Handler mHandler;
41    private final BrowserWebViewFactory mFactory;
42    private final HashMap<String, PreloaderSession> mSessions;
43
44    public static void initialize(Context context) {
45        sInstance = new Preloader(context);
46    }
47
48    public static Preloader getInstance() {
49        return sInstance;
50    }
51
52    private Preloader(Context context) {
53        mContext = context;
54        mHandler = new Handler(Looper.getMainLooper());
55        mSessions = new HashMap<String, PreloaderSession>();
56        mFactory = new BrowserWebViewFactory(context);
57
58    }
59
60    private PreloaderSession getSession(String id) {
61        PreloaderSession s = mSessions.get(id);
62        if (s == null) {
63            if (LOGD_ENABLED) Log.d(LOGTAG, "Create new preload session " + id);
64            s = new PreloaderSession(id);
65            mSessions.put(id, s);
66            WebViewTimersControl.getInstance().onPrerenderStart(s.getWebView());
67        }
68        return s;
69    }
70
71    private PreloaderSession takeSession(String id) {
72        PreloaderSession s = mSessions.remove(id);
73        if (s != null) {
74            s.cancelTimeout();
75        }
76        if (mSessions.size() == 0) {
77            WebViewTimersControl.getInstance().onPrerenderDone(s == null ? null : s.getWebView());
78        }
79        return s;
80    }
81
82    public void handlePreloadRequest(String id, String url, Map<String, String> headers,
83            String searchBoxQuery) {
84        PreloaderSession s = getSession(id);
85        s.touch(); // reset timer
86        PreloadedTabControl tab = s.getTabControl();
87        if (searchBoxQuery != null) {
88            tab.loadUrlIfChanged(url, headers);
89            tab.setQuery(searchBoxQuery);
90        } else {
91            tab.loadUrl(url, headers);
92        }
93    }
94
95    public void discardPreload(String id) {
96        PreloaderSession s = takeSession(id);
97        if (s != null) {
98            if (LOGD_ENABLED) Log.d(LOGTAG, "Discard preload session " + id);
99            PreloadedTabControl t = s.getTabControl();
100            t.destroy();
101        } else {
102            if (LOGD_ENABLED) Log.d(LOGTAG, "Ignored discard request " + id);
103        }
104    }
105
106    /**
107     * Return a preloaded tab, and remove it from the preloader. This is used when the
108     * view is about to be displayed.
109     */
110    public PreloadedTabControl getPreloadedTab(String id) {
111        PreloaderSession s = takeSession(id);
112        if (LOGD_ENABLED) Log.d(LOGTAG, "Showing preload session " + id + "=" + s);
113        return s == null ? null : s.getTabControl();
114    }
115
116    private class PreloaderSession {
117        private final String mId;
118        private final PreloadedTabControl mTabControl;
119
120        private final Runnable mTimeoutTask = new Runnable(){
121            @Override
122            public void run() {
123                if (LOGD_ENABLED) Log.d(LOGTAG, "Preload session timeout " + mId);
124                discardPreload(mId);
125            }};
126
127        public PreloaderSession(String id) {
128            mId = id;
129            mTabControl = new PreloadedTabControl(
130                    new Tab(new PreloadController(mContext), mFactory.createWebView(false)));
131            touch();
132        }
133
134        public void cancelTimeout() {
135            mHandler.removeCallbacks(mTimeoutTask);
136        }
137
138        public void touch() {
139            cancelTimeout();
140            mHandler.postDelayed(mTimeoutTask, PRERENDER_TIMEOUT_MILLIS);
141        }
142
143        public PreloadedTabControl getTabControl() {
144            return mTabControl;
145        }
146
147        public WebView getWebView() {
148            Tab t = mTabControl.getTab();
149            return t == null? null : t.getWebView();
150        }
151
152    }
153
154}
155