OSDN Git Service

Avoid superfluous calls to CacheManager with the Chromium HTTP stack
[android-x86/frameworks-base.git] / core / java / android / webkit / WebViewWorker.java
1 /*
2  * Copyright (C) 2010 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  */
16
17 package android.webkit;
18
19 import java.io.IOException;
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import android.net.http.Headers;
24 import android.os.Handler;
25 import android.os.HandlerThread;
26 import android.os.Looper;
27 import android.os.Message;
28
29 /**
30  * WebViewWorker executes in a separate thread other than UI and WebViewCore. To
31  * avoid blocking UI or WebKit's execution, the caller can send a message to
32  * WebViewWorker.getHandler() and it will be handled in the WebViewWorkerThread.
33  */
34 final class WebViewWorker extends Handler {
35
36     private static final String THREAD_NAME = "WebViewWorkerThread";
37
38     private static WebViewWorker sWorkerHandler;
39
40     private static Map<LoadListener, CacheManager.CacheResult> mCacheResultMap
41             = new HashMap<LoadListener, CacheManager.CacheResult>();
42
43     /**
44      * Package level class to be used while creating a cache entry.
45      */
46     static class CacheCreateData {
47         LoadListener mListener;
48         String mUrl;
49         String mMimeType;
50         int mStatusCode;
51         long mPostId;
52         Headers mHeaders;
53     }
54
55     /**
56      * Package level class to be used while saving a cache entry.
57      */
58     static class CacheSaveData {
59         LoadListener mListener;
60         String mUrl;
61         long mPostId;
62     }
63
64     /**
65      * Package level class to be used while updating a cache entry's encoding.
66      */
67     static class CacheEncoding {
68         LoadListener mListener;
69         String mEncoding;
70     }
71
72     /**
73      * Package level class to be used while appending data to a cache entry.
74      */
75     static class CacheData {
76         LoadListener mListener;
77         ByteArrayBuilder.Chunk mChunk;
78     }
79
80     static synchronized WebViewWorker getHandler() {
81         if (sWorkerHandler == null) {
82             HandlerThread thread = new HandlerThread(THREAD_NAME,
83                     android.os.Process.THREAD_PRIORITY_DEFAULT
84                             + android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
85             thread.start();
86             sWorkerHandler = new WebViewWorker(thread.getLooper());
87         }
88         return sWorkerHandler;
89     }
90
91     private WebViewWorker(Looper looper) {
92         super(looper);
93     }
94
95     // trigger transaction once a minute
96     private static final int CACHE_TRANSACTION_TICKER_INTERVAL = 60 * 1000;
97
98     private static boolean mCacheTickersBlocked = true;
99
100     // message ids
101     static final int MSG_ADD_STREAMLOADER = 101;
102     static final int MSG_ADD_HTTPLOADER = 102;
103     static final int MSG_CREATE_CACHE = 103;
104     static final int MSG_UPDATE_CACHE_ENCODING = 104;
105     static final int MSG_APPEND_CACHE = 105;
106     static final int MSG_SAVE_CACHE = 106;
107     static final int MSG_REMOVE_CACHE = 107;
108     static final int MSG_TRIM_CACHE = 108;
109     static final int MSG_CLEAR_CACHE = 109;
110     static final int MSG_CACHE_TRANSACTION_TICKER = 110;
111     static final int MSG_PAUSE_CACHE_TRANSACTION = 111;
112     static final int MSG_RESUME_CACHE_TRANSACTION = 112;
113
114     @Override
115     public void handleMessage(Message msg) {
116         switch(msg.what) {
117             case MSG_ADD_STREAMLOADER: {
118                 StreamLoader loader = (StreamLoader) msg.obj;
119                 loader.load();
120                 break;
121             }
122             case MSG_ADD_HTTPLOADER: {
123                 FrameLoader loader = (FrameLoader) msg.obj;
124                 loader.handleHTTPLoad();
125                 break;
126             }
127             case MSG_CREATE_CACHE: {
128                 assert !JniUtil.useChromiumHttpStack();
129                 CacheCreateData data = (CacheCreateData) msg.obj;
130                 CacheManager.CacheResult cache = CacheManager.createCacheFile(
131                         data.mUrl, data.mStatusCode, data.mHeaders,
132                         data.mMimeType, data.mPostId, false);
133                 if (cache != null) {
134                     mCacheResultMap.put(data.mListener, cache);
135                 } else {
136                     mCacheResultMap.remove(data.mListener);
137                 }
138                 break;
139             }
140             case MSG_UPDATE_CACHE_ENCODING: {
141                 assert !JniUtil.useChromiumHttpStack();
142                 CacheEncoding data = (CacheEncoding) msg.obj;
143                 CacheManager.CacheResult cache = mCacheResultMap
144                         .get(data.mListener);
145                 if (cache != null) {
146                     cache.encoding = data.mEncoding;
147                 }
148                 break;
149             }
150             case MSG_APPEND_CACHE: {
151                 assert !JniUtil.useChromiumHttpStack();
152                 CacheData data = (CacheData) msg.obj;
153                 CacheManager.CacheResult cache = mCacheResultMap
154                         .get(data.mListener);
155                 if (cache != null) {
156                     cache.contentLength += data.mChunk.mLength;
157                     if (cache.contentLength > CacheManager.CACHE_MAX_SIZE) {
158                         CacheManager.cleanupCacheFile(cache);
159                         mCacheResultMap.remove(data.mListener);
160                     } else {
161                         try {
162                             cache.outStream.write(data.mChunk.mArray, 0,
163                                     data.mChunk.mLength);
164                         } catch (IOException e) {
165                             CacheManager.cleanupCacheFile(cache);
166                             mCacheResultMap.remove(data.mListener);
167                         }
168                     }
169                 }
170                 data.mChunk.release();
171                 break;
172             }
173             case MSG_SAVE_CACHE: {
174                 assert !JniUtil.useChromiumHttpStack();
175                 CacheSaveData data = (CacheSaveData) msg.obj;
176                 CacheManager.CacheResult cache = mCacheResultMap
177                         .get(data.mListener);
178                 if (cache != null) {
179                     CacheManager.saveCacheFile(data.mUrl, data.mPostId, cache);
180                     mCacheResultMap.remove(data.mListener);
181                 }
182                 break;
183             }
184             case MSG_REMOVE_CACHE: {
185                 assert !JniUtil.useChromiumHttpStack();
186                 LoadListener listener = (LoadListener) msg.obj;
187                 CacheManager.CacheResult cache = mCacheResultMap.get(listener);
188                 if (cache != null) {
189                     CacheManager.cleanupCacheFile(cache);
190                     mCacheResultMap.remove(listener);
191                 }
192                 break;
193             }
194             case MSG_TRIM_CACHE: {
195                 assert !JniUtil.useChromiumHttpStack();
196                 CacheManager.trimCacheIfNeeded();
197                 break;
198             }
199             case MSG_CLEAR_CACHE: {
200                 assert !JniUtil.useChromiumHttpStack();
201                 CacheManager.clearCache();
202                 break;
203             }
204             case MSG_CACHE_TRANSACTION_TICKER: {
205                 assert !JniUtil.useChromiumHttpStack();
206                 if (!mCacheTickersBlocked) {
207                     CacheManager.endTransaction();
208                     CacheManager.startTransaction();
209                     sendEmptyMessageDelayed(MSG_CACHE_TRANSACTION_TICKER,
210                             CACHE_TRANSACTION_TICKER_INTERVAL);
211                 }
212                 break;
213             }
214             case MSG_PAUSE_CACHE_TRANSACTION: {
215                 assert !JniUtil.useChromiumHttpStack();
216                 if (CacheManager.disableTransaction()) {
217                     mCacheTickersBlocked = true;
218                     removeMessages(MSG_CACHE_TRANSACTION_TICKER);
219                 }
220                 break;
221             }
222             case MSG_RESUME_CACHE_TRANSACTION: {
223                 assert !JniUtil.useChromiumHttpStack();
224                 if (CacheManager.enableTransaction()) {
225                     mCacheTickersBlocked = false;
226                     sendEmptyMessageDelayed(MSG_CACHE_TRANSACTION_TICKER,
227                             CACHE_TRANSACTION_TICKER_INTERVAL);
228                 }
229                 break;
230             }
231         }
232     }
233 }